Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add optional cli parameter --preserve-digests to skopeo copy command. #1171

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
### Changed
* Enhance SSDS Document Generation Performance using New Atlassian APIs ([#1084](https://github.com/opendevstack/ods-jenkins-shared-library/issues/1084))
* Deprecation of vuln-type and scanners config in Trivy ([#1150](https://github.com/opendevstack/ods-jenkins-shared-library/issues/1150))
* Add preserve-digests cli option to skopeo copy command in CopyImageStage ([#1166](https://github.com/opendevstack/ods-jenkins-shared-library/issues/1166))

### Fixed
* Fix Tailor deployment drifts for D, Q envs ([#1055](https://github.com/opendevstack/ods-jenkins-shared-library/pull/1055))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ _List<String>_
Next to exact matches, it also supports prefixes (e.g. `feature/`) and all branches (`*`).


| *preserveDigests* +
_Boolean_
|preserveDigests allows to sync the source and destination image digests

The default is false, set to true to preserve digests


| *sourceCredential* +
_String_
|sourceCredential is the token to use, if any, to access the source registry
Expand Down
7 changes: 7 additions & 0 deletions src/org/ods/component/CopyImageOptions.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ class CopyImageOptions extends Options {
*/
Boolean verifyTLS

/**
* preserveDigests allows to sync the source and destination image digests
*
* The default is false, set to true to preserve digests
*/
Boolean preserveDigests

@SuppressWarnings('UnusedPrivateField')
private String registry
@SuppressWarnings('UnusedPrivateField')
Expand Down
14 changes: 11 additions & 3 deletions src/org/ods/component/CopyImageStage.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ class CopyImageStage extends Stage {
config.verifyTLS = true
}

if (config.preserveDigests == null) {
config.preserveDigests = false
}

this.options = new CopyImageOptions(config)
this.openShift = openShift
this.logger = logger
Expand All @@ -52,7 +56,10 @@ class CopyImageStage extends Stage {

def sourcetoken = options.sourceCredential ? "--src-creds ${options.sourceCredential}" : ''

int status = copyImage(sourcetoken, targetInternalRegistryToken, STR_DOCKER_PROTOCOL)
def copyparams = ""
if (this.options.preserveDigests) { copyparams += "--all --preserve-digests" }

int status = copyImage(sourcetoken, targetInternalRegistryToken, STR_DOCKER_PROTOCOL, copyparams)
if (status != 0) {
script.error("Could not copy `${this.options.sourceImageUrlIncludingRegistry}', status ${status}")
}
Expand Down Expand Up @@ -83,10 +90,11 @@ class CopyImageStage extends Stage {
}
}

private int copyImage(sourcetoken, targetInternalRegistryToken, String dockerProtocol) {
private int copyImage(sourcetoken, targetInternalRegistryToken, String dockerProtocol, String copyparams) {
int status = steps.sh(
script: """
skopeo copy --src-tls-verify=${this.options.verifyTLS} ${sourcetoken} \
skopeo copy ${copyparams} \
--src-tls-verify=${this.options.verifyTLS} ${sourcetoken} \
${this.options.registry}/${this.options.repo}/${this.options.image} \
--dest-creds openshift:${targetInternalRegistryToken} \
${dockerProtocol}${context.clusterRegistryAddress}/${context.cdProject}/${this.options.image} \
Expand Down
18 changes: 10 additions & 8 deletions test/groovy/vars/OdsComponentStageCopyImageSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class OdsComponentStageCopyImageSpec extends PipelineSpockTestBase {
def cfg = [
sourceImageUrlIncludingRegistry: sourceImageUrlIncludingRegistry,
verifyTLS : verifyTLS,
preserveDigests : preserveDigests,
tagIntoTargetEnv : tagIntoTargetEnv,
]
def ctxCfg = [
Expand Down Expand Up @@ -51,7 +52,8 @@ class OdsComponentStageCopyImageSpec extends PipelineSpockTestBase {
assertCallStackContains("Resolved source Image data: ${sourceImageUrlIncludingRegistry}")
assertCallStackContains("importing into: docker://internal-registry/project-cd/${imageName}:${imageTag}")
// FIXME: this should probably verify that the steps.sh is called with the correct string rather than checking the full callstack
assertCallStackContains("skopeo copy --src-tls-verify=${expectedVerifyTLS} docker://${sourceImageUrlIncludingRegistry} --dest-creds openshift:secret-token docker://internal-registry/project-cd/image:1f3d1 --dest-tls-verify=${expectedVerifyTLS}")
assertCallStackContains("skopeo copy ${expectedCopyParams}")
assertCallStackContains("--src-tls-verify=${expectedVerifyTLS} docker://${sourceImageUrlIncludingRegistry} --dest-creds openshift:secret-token docker://internal-registry/project-cd/image:1f3d1 --dest-tls-verify=${expectedVerifyTLS}")
if (tagIntoTargetEnv) {
1 * openShiftService.importImageTagFromProject('project-dev', imageName, 'project-cd', imageTag, imageTag)
1 * openShiftService.findOrCreateImageStream('project-dev', imageName)
Expand All @@ -60,13 +62,13 @@ class OdsComponentStageCopyImageSpec extends PipelineSpockTestBase {
assertJobStatusSuccess()

where:
registry || repo || imageName || imageTag || verifyTLS || expectedVerifyTLS || tagIntoTargetEnv
'example.com' || 'repo' || 'image' || '1f3d1' || true || true || true
'example.com' || 'repo' || 'image' || '1f3d1' || true || true || false
'example.com' || 'repo' || 'image' || '1f3d1' || false || false || true
'example.com' || 'repo' || 'image' || '1f3d1' || false || false || false
'example.com' || 'repo' || 'image' || '1f3d1' || null || true || true
'example.com' || 'repo' || 'image' || '1f3d1' || null || true || false
registry || repo || imageName || imageTag || preserveDigests || expectedCopyParams || verifyTLS || expectedVerifyTLS || tagIntoTargetEnv
'example.com' || 'repo' || 'image' || '1f3d1' || true || '--all --preserve-digests ' || true || true || true
'example.com' || 'repo' || 'image' || '1f3d1' || true || '--all --preserve-digests ' || true || true || false
'example.com' || 'repo' || 'image' || '1f3d1' || false || '' || false || false || true
'example.com' || 'repo' || 'image' || '1f3d1' || false || '' || false || false || false
'example.com' || 'repo' || 'image' || '1f3d1' || null || '' || null || true || true
'example.com' || 'repo' || 'image' || '1f3d1' || null || '' || null || true || false

}
}