From 0daf3b09ed297672ed29eacf674976cf9fecbdd5 Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Tue, 15 Feb 2022 15:32:48 +0000 Subject: [PATCH 01/14] support push docker image step --- vars/pushDockerImages.groovy | 108 +++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 vars/pushDockerImages.groovy diff --git a/vars/pushDockerImages.groovy b/vars/pushDockerImages.groovy new file mode 100644 index 000000000..cd602dc16 --- /dev/null +++ b/vars/pushDockerImages.groovy @@ -0,0 +1,108 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +/** + https://plugins.jenkins.io/github + Update the commit status on GitHub with the current status of the build. + + updateGithubCommitStatus( + repoUrl: "${GIT_URL}", + commitSha: "${GIT_COMMIT}", + message: 'Build result.' + ) + + updateGithubCommitStatus() + + updateGithubCommitStatus(message: 'Build result.') +*/ +def call(Map args = [:]) { + +} + +/** +* @param arch what architecture +*/ +def pushDockerImages(Map args = [:]) { + def name = args.containsKey('name') ? args.name : error('foo') + def arch = args.get('arch', 'amd64') + def variants = args.get('variants', ['']) + dockerLogin(secret: "${env.DOCKER_ELASTIC_SECRET}", registry: "${env.DOCKER_REGISTRY}") + def libbetaVer = env.BEAT_VERSION + def aliasVersion = "" + if("${env.SNAPSHOT}" == "true"){ + aliasVersion = libbetaVer.substring(0, libbetaVer.lastIndexOf(".")) // remove third number in version + + libbetaVer += "-SNAPSHOT" + aliasVersion += "-SNAPSHOT" + } + + def tagName = "${libbetaVer}" + if (isPR()) { + tagName = "pr-${env.CHANGE_ID}" + } + + // supported tags + def tags = [tagName, "${env.GIT_BASE_COMMIT}"] + if (!isPR() && aliasVersion != "") { + tags << aliasVersion + } + + variants.each { variant -> + // cloud docker images are stored in the private docker namespace. + def sourceNamespace = variant.equals('-cloud') ? 'beats-ci' : 'beats' + tags.each { tag -> + // TODO: + // For backward compatibility let's ensure we tag only for amd64, then E2E can benefit from until + // they support the versioning with the architecture + if ("${arch}" == "amd64") { + doTagAndPush(name: name, variant: variant, sourceTag: libbetaVer, targetTag: "${tag}", sourceNamespace: sourceNamespace) + } + doTagAndPush(name: name, variant: variant, sourceTag: libbetaVer, targetTag: "${tag}-${arch}", sourceNamespace: sourceNamespace) + } + } +} + +/** +* @param name of the docker image +* @param variant name of the variant used to build the docker image name +* @param sourceNamespace namespace to be used as source for the docker tag command +* @param targetNamespace namespace to be used as target for the docker tag command +* @param sourceTag tag to be used as source for the docker tag command, usually under the 'beats' namespace +* @param targetTag tag to be used as target for the docker tag command, usually under the 'observability-ci' namespace +*/ +def doTagAndPush(Map args = [:]) { + def name = args.name + def variant = args.variant + def sourceTag = args.sourceTag + def targetTag = args.targetTag + def sourceNamespace = args.sourceNamespace + def targetNamespace = args.targetNamespace + def sourceName = "${env.DOCKER_REGISTRY}/${sourceNamespace}/${name}${variant}:${sourceTag}" + def targetName = "${env.DOCKER_REGISTRY}/${targetNamespace}/${name}${variant}:${targetTag}" + def iterations = 0 + retryWithSleep(retries: 3, seconds: 5, backoff: true) { + iterations++ + def status = sh(label: "Change tag and push ${targetName}", + script: ".ci/scripts/docker-tag-push.sh ${sourceName} ${targetName}", + returnStatus: true) + if (status > 0 && iterations < 3) { + error("tag and push failed for ${name}, retry") + } else if (status > 0) { + log(level: 'WARN', text: "${name} doesn't have ${variant} docker images. See https://github.com/elastic/beats/pull/21621") + } + } +} From 3c5e90ec240b51a48ce7b47b23ef98418243f77e Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Tue, 15 Feb 2022 23:40:15 +0000 Subject: [PATCH 02/14] pushDockerImages --- .../groovy/PushDockerImagesStepTests.groovy | 151 ++++++++++++++++++ vars/pushDockerImages.groovy | 123 +++++++++----- vars/pushDockerImages.txt | 41 +++++ 3 files changed, 271 insertions(+), 44 deletions(-) create mode 100644 src/test/groovy/PushDockerImagesStepTests.groovy create mode 100644 vars/pushDockerImages.txt diff --git a/src/test/groovy/PushDockerImagesStepTests.groovy b/src/test/groovy/PushDockerImagesStepTests.groovy new file mode 100644 index 000000000..72dd86ae8 --- /dev/null +++ b/src/test/groovy/PushDockerImagesStepTests.groovy @@ -0,0 +1,151 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import org.junit.Before +import org.junit.Test +import static org.junit.Assert.assertTrue + +class PushDockerImagesStepTests extends ApmBasePipelineTest { + + @Override + @Before + void setUp() throws Exception { + super.setUp() + script = loadScript('vars/pushDockerImages.groovy') + env.GIT_BASE_COMMIT = 'commit' + } + + @Test + void test_windows() throws Exception { + testWindows() { + script.call() + } + } + + @Test + void test_missing_registry() throws Exception { + testMissingArgument('registry') { + script.call() + } + } + + @Test + void test_missing_secret() throws Exception { + testMissingArgument('secret') { + script.call(registry: 'foo') + } + } + @Test + void test_missing_targetNamespace() throws Exception { + testMissingArgument('targetNamespace') { + script.call(registry: 'foo', secret: 'bar') + } + } + + @Test + void test_missing_version() throws Exception { + testMissingArgument('version') { + script.call(registry: 'foo', secret: 'bar', targetNamespace: 'target') + } + } + + @Test + void test_missing_project() throws Exception { + testMissingArgument('project.name') { + script.call(registry: 'foo', secret: 'bar', targetNamespace: 'target', version: '1.2') + } + } + + @Test + void test_calculateTags_pr() throws Exception { + helper.registerAllowedMethod('isPR', { return true }) + env.CHANGE_ID = '1' + def ret = script.calculateTags('8.2-SNAPSHOT', '') + printCallStack() + assertTrue(ret.equals(['commit', 'pr-1'])) + } + + @Test + void test_calculateTags_branch() throws Exception { + helper.registerAllowedMethod('isPR', { return false }) + def ret = script.calculateTags('8.2-SNAPSHOT', '8.2.0-SNAPSHOT') + printCallStack() + assertTrue(ret.equals(['commit', '8.2-SNAPSHOT', '8.2.0-SNAPSHOT'])) + + ret = script.calculateTags('8.2-SNAPSHOT', '') + printCallStack() + assertTrue(ret.equals(['commit', '8.2-SNAPSHOT'])) + } + + @Test + void test_doTagAndPush() throws Exception { + helper.registerAllowedMethod('sh', [Map.class], { return 0 }) + script.doTagAndPush(registry: 'my-registry', + name: 'my-name', + variant: '-cloud', + sourceTag: '8.2-SNAPSHOT', + targetTag: 'commit', + sourceNamespace: 'beats', + targetNamespace: 'beats-ci') + printCallStack() + assertTrue(assertMethodCallContainsPattern('sh', '"my-registry/beats/my-name-cloud:8.2-SNAPSHOT" "my-registry/beats-ci/my-name-cloud:commit"')) + } + + @Test + void test_with_snapshots() throws Exception { + helper.registerAllowedMethod('sh', [Map.class], { return 0 }) + script.call( + secret: "my-secret", + registry: "my-registry", + arch: 'amd64', + version: '8.2.0', + snapshot: true, + project: [ + name: 'filebeat', + variants: [ + '' : 'beats', + '-cloud' : 'beats-ci' + ] + ], + targetNamespace: 'observability-ci' + ) + printCallStack() + assertTrue(assertMethodCallOccurrences('sh', 12)) + } + + @Test + void test_without_snapshots() throws Exception { + helper.registerAllowedMethod('sh', [Map.class], { return 0 }) + script.call( + secret: "my-secret", + registry: "my-registry", + arch: 'amd64', + version: '8.2.0', + snapshot: false, + project: [ + name: 'filebeat', + variants: [ + '' : 'beats', + '-cloud' : 'beats-ci' + ] + ], + targetNamespace: 'observability-ci' + ) + printCallStack() + assertTrue(assertMethodCallOccurrences('sh', 8)) + } +} diff --git a/vars/pushDockerImages.groovy b/vars/pushDockerImages.groovy index cd602dc16..9be82c51d 100644 --- a/vars/pushDockerImages.groovy +++ b/vars/pushDockerImages.groovy @@ -16,67 +16,79 @@ // under the License. /** - https://plugins.jenkins.io/github - Update the commit status on GitHub with the current status of the build. - updateGithubCommitStatus( - repoUrl: "${GIT_URL}", - commitSha: "${GIT_COMMIT}", - message: 'Build result.' - ) +Publish docker images in the given docker registry. For such, it +retags the existing docker images and publish them in the given +docker namespace. - updateGithubCommitStatus() +It also allows to transform the version and customise private docker +namespaces/registries. - updateGithubCommitStatus(message: 'Build result.') -*/ -def call(Map args = [:]) { - -} + pushDockerImages( + secret: "my-secret", + registry: "my-registry", + arch: 'amd64', + version: '8.2.0', + snapshot: true, + project: [ + name: 'filebeat', + variants: [ + '' : 'beats', + 'ubi8' : 'beats', + 'cloud' : 'beats-ci', + 'complete' : 'beats', + ] + ], + targetNamespace: 'observability-ci' + ) -/** -* @param arch what architecture */ -def pushDockerImages(Map args = [:]) { - def name = args.containsKey('name') ? args.name : error('foo') +def call(Map args = [:]) { + if(!isUnix()){ + error('publishToCDN: windows is not supported yet.') + } + def registry = args.containsKey('registry') ? args.registry : error('pushDockerImages: registry parameter is required') + def secret = args.containsKey('secret') ? args.secret : error('pushDockerImages: secret parameter is required') + def targetNamespace = args.containsKey('targetNamespace') ? args.targetNamespace : error('pushDockerImages: targetNamespace parameter is required') + def version = args.containsKey('version') ? args.version : error('pushDockerImages: version parameter is required') def arch = args.get('arch', 'amd64') - def variants = args.get('variants', ['']) - dockerLogin(secret: "${env.DOCKER_ELASTIC_SECRET}", registry: "${env.DOCKER_REGISTRY}") - def libbetaVer = env.BEAT_VERSION - def aliasVersion = "" - if("${env.SNAPSHOT}" == "true"){ - aliasVersion = libbetaVer.substring(0, libbetaVer.lastIndexOf(".")) // remove third number in version + def project = args.get('project', [:]) + def snapshot = args.get('snapshot', true) - libbetaVer += "-SNAPSHOT" - aliasVersion += "-SNAPSHOT" + if (!project.containsKey('name')) { + error('pushDockerImages: project.name parameter is required') } - def tagName = "${libbetaVer}" - if (isPR()) { - tagName = "pr-${env.CHANGE_ID}" + // Transform version in a snapshot. + def sourceTag = version + def aliasVersion = "" + if (snapshot) { + // remove third number in version + aliasVersion = version.substring(0, version.lastIndexOf(".")) + "-SNAPSHOT" + sourceTag += "-SNAPSHOT" } - // supported tags - def tags = [tagName, "${env.GIT_BASE_COMMIT}"] - if (!isPR() && aliasVersion != "") { - tags << aliasVersion - } + // What docker tags are gonna be used + def tags = calculateTags(sourceTag, aliasVersion) - variants.each { variant -> - // cloud docker images are stored in the private docker namespace. - def sourceNamespace = variant.equals('-cloud') ? 'beats-ci' : 'beats' + println tags + dockerLogin(secret: "${secret}", registry: "${registry}") + project.get('variants')?.each { variant, sourceNamespace -> tags.each { tag -> // TODO: // For backward compatibility let's ensure we tag only for amd64, then E2E can benefit from until // they support the versioning with the architecture if ("${arch}" == "amd64") { - doTagAndPush(name: name, variant: variant, sourceTag: libbetaVer, targetTag: "${tag}", sourceNamespace: sourceNamespace) + doTagAndPush(registry: registry, name: project.name, variant: variant, sourceTag: sourceTag, targetTag: "${tag}", sourceNamespace: sourceNamespace, targetNamespace: targetNamespace) } - doTagAndPush(name: name, variant: variant, sourceTag: libbetaVer, targetTag: "${tag}-${arch}", sourceNamespace: sourceNamespace) + doTagAndPush(registry: registry, name: project.name, variant: variant, sourceTag: sourceTag, targetTag: "${tag}-${arch}", sourceNamespace: sourceNamespace, targetNamespace: targetNamespace) } } } /** +* Tag and push the source docker image. It retries to add resilience. +* * @param name of the docker image * @param variant name of the variant used to build the docker image name * @param sourceNamespace namespace to be used as source for the docker tag command @@ -91,18 +103,41 @@ def doTagAndPush(Map args = [:]) { def targetTag = args.targetTag def sourceNamespace = args.sourceNamespace def targetNamespace = args.targetNamespace - def sourceName = "${env.DOCKER_REGISTRY}/${sourceNamespace}/${name}${variant}:${sourceTag}" - def targetName = "${env.DOCKER_REGISTRY}/${targetNamespace}/${name}${variant}:${targetTag}" + def registry = args.registry + + def sourceName = "${registry}/${sourceNamespace}/${name}${variant}:${sourceTag}" + def targetName = "${registry}/${targetNamespace}/${name}${variant}:${targetTag}" def iterations = 0 - retryWithSleep(retries: 3, seconds: 5, backoff: true) { + + waitUntil { iterations++ def status = sh(label: "Change tag and push ${targetName}", - script: ".ci/scripts/docker-tag-push.sh ${sourceName} ${targetName}", + script: """#!/bin/bash + set -e + if docker image inspect "${sourceName}" &> /dev/null ; then + docker tag "${sourceName}" "${targetName}" + docker push "${targetName}" + else + echo "docker image ${sourceName} does not exist" + fi""", returnStatus: true) if (status > 0 && iterations < 3) { - error("tag and push failed for ${name}, retry") + sleep 5 * iterations + return false } else if (status > 0) { - log(level: 'WARN', text: "${name} doesn't have ${variant} docker images. See https://github.com/elastic/beats/pull/21621") + return false + } else { + return true } } } + +def calculateTags(sourceTag, aliasVersion) { + def tags = [ env.GIT_BASE_COMMIT, + isPR() ? "pr-${env.CHANGE_ID}" : sourceTag ] + + if (!isPR() && aliasVersion.trim()) { + tags << aliasVersion + } + return tags +} diff --git a/vars/pushDockerImages.txt b/vars/pushDockerImages.txt new file mode 100644 index 000000000..dbff79564 --- /dev/null +++ b/vars/pushDockerImages.txt @@ -0,0 +1,41 @@ +Publish docker images in the given docker registry. For such, it +retags the existing docker images and publish them in the given +docker namespace. + +It also allows to transform the version and customise private docker +namespaces/registries. + +``` + // Given the filebeat project, and its generated docker + // images for the 8.2.0-SNAPSHOT and 4 different variants + // then publish them to observability-ci + pushDockerImages( + secret: "my-secret", + registry: "my-registry", + arch: 'amd64', + version: '8.2.0', + snapshot: true, + project: [ + name: 'filebeat', + variants: [ + '' : 'beats', + 'ubi8' : 'beats', + 'cloud' : 'beats-ci', + 'complete' : 'beats', + ] + ], + targetNamespace: 'observability-ci' + ) +``` + +* secret: the docker secret +* registry: the docker registry +* arch: the supported arch (amd64 or arm64) +* version: what version +* snapshot: snapshot support +* targetNamespace: what docker namespace to publish to. +* project: data structure to identify the name of the docker image, + what variants and what docker namespace to copy from. + + +__NOTE__: It requires *Nix where to run it from. From a1db62fe28a33b3b9bcf0093defd05ae14f62b4f Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Wed, 16 Feb 2022 08:39:11 +0000 Subject: [PATCH 03/14] add echo for debugging purposes --- vars/pushDockerImages.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/vars/pushDockerImages.groovy b/vars/pushDockerImages.groovy index 9be82c51d..b64f5af6a 100644 --- a/vars/pushDockerImages.groovy +++ b/vars/pushDockerImages.groovy @@ -114,6 +114,7 @@ def doTagAndPush(Map args = [:]) { def status = sh(label: "Change tag and push ${targetName}", script: """#!/bin/bash set -e + echo "source: '${sourceName}' target: '${targetName}'" if docker image inspect "${sourceName}" &> /dev/null ; then docker tag "${sourceName}" "${targetName}" docker push "${targetName}" From 83f0ee17d4873a614429e527eaf09f627e3058c8 Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Wed, 16 Feb 2022 17:55:34 +0000 Subject: [PATCH 04/14] change signature with a simpler data structure --- .../groovy/PushDockerImagesStepTests.groovy | 26 +++++++--------- vars/pushDockerImages.groovy | 31 ++++++++----------- vars/pushDockerImages.txt | 19 +++++------- 3 files changed, 32 insertions(+), 44 deletions(-) diff --git a/src/test/groovy/PushDockerImagesStepTests.groovy b/src/test/groovy/PushDockerImagesStepTests.groovy index 72dd86ae8..e041f8af5 100644 --- a/src/test/groovy/PushDockerImagesStepTests.groovy +++ b/src/test/groovy/PushDockerImagesStepTests.groovy @@ -64,8 +64,8 @@ class PushDockerImagesStepTests extends ApmBasePipelineTest { } @Test - void test_missing_project() throws Exception { - testMissingArgument('project.name') { + void test_missing_imageName() throws Exception { + testMissingArgument('imageName') { script.call(registry: 'foo', secret: 'bar', targetNamespace: 'target', version: '1.2') } } @@ -95,7 +95,7 @@ class PushDockerImagesStepTests extends ApmBasePipelineTest { void test_doTagAndPush() throws Exception { helper.registerAllowedMethod('sh', [Map.class], { return 0 }) script.doTagAndPush(registry: 'my-registry', - name: 'my-name', + imageName: 'my-name', variant: '-cloud', sourceTag: '8.2-SNAPSHOT', targetTag: 'commit', @@ -114,12 +114,10 @@ class PushDockerImagesStepTests extends ApmBasePipelineTest { arch: 'amd64', version: '8.2.0', snapshot: true, - project: [ - name: 'filebeat', - variants: [ - '' : 'beats', - '-cloud' : 'beats-ci' - ] + imageName: 'filebeat', + variants: [ + '' : 'beats', + '-cloud' : 'beats-ci' ], targetNamespace: 'observability-ci' ) @@ -136,12 +134,10 @@ class PushDockerImagesStepTests extends ApmBasePipelineTest { arch: 'amd64', version: '8.2.0', snapshot: false, - project: [ - name: 'filebeat', - variants: [ - '' : 'beats', - '-cloud' : 'beats-ci' - ] + imageName: 'filebeat', + variants: [ + '' : 'beats', + '-cloud' : 'beats-ci' ], targetNamespace: 'observability-ci' ) diff --git a/vars/pushDockerImages.groovy b/vars/pushDockerImages.groovy index b64f5af6a..76f217396 100644 --- a/vars/pushDockerImages.groovy +++ b/vars/pushDockerImages.groovy @@ -30,14 +30,12 @@ namespaces/registries. arch: 'amd64', version: '8.2.0', snapshot: true, - project: [ - name: 'filebeat', - variants: [ - '' : 'beats', - 'ubi8' : 'beats', - 'cloud' : 'beats-ci', - 'complete' : 'beats', - ] + imageName : 'filebeat', + variants: [ + '' : 'beats', + 'ubi8' : 'beats', + 'cloud' : 'beats-ci', + 'complete' : 'beats', ], targetNamespace: 'observability-ci' ) @@ -51,14 +49,11 @@ def call(Map args = [:]) { def secret = args.containsKey('secret') ? args.secret : error('pushDockerImages: secret parameter is required') def targetNamespace = args.containsKey('targetNamespace') ? args.targetNamespace : error('pushDockerImages: targetNamespace parameter is required') def version = args.containsKey('version') ? args.version : error('pushDockerImages: version parameter is required') + def imageName = args.containsKey('imageName') ? args.imageName : error('pushDockerImages: imageName parameter is required') def arch = args.get('arch', 'amd64') - def project = args.get('project', [:]) + def variants = args.get('variants', [:]) def snapshot = args.get('snapshot', true) - if (!project.containsKey('name')) { - error('pushDockerImages: project.name parameter is required') - } - // Transform version in a snapshot. def sourceTag = version def aliasVersion = "" @@ -73,15 +68,15 @@ def call(Map args = [:]) { println tags dockerLogin(secret: "${secret}", registry: "${registry}") - project.get('variants')?.each { variant, sourceNamespace -> + variants?.each { variant, sourceNamespace -> tags.each { tag -> // TODO: // For backward compatibility let's ensure we tag only for amd64, then E2E can benefit from until // they support the versioning with the architecture if ("${arch}" == "amd64") { - doTagAndPush(registry: registry, name: project.name, variant: variant, sourceTag: sourceTag, targetTag: "${tag}", sourceNamespace: sourceNamespace, targetNamespace: targetNamespace) + doTagAndPush(registry: registry, imageName: imageName, variant: variant, sourceTag: sourceTag, targetTag: "${tag}", sourceNamespace: sourceNamespace, targetNamespace: targetNamespace) } - doTagAndPush(registry: registry, name: project.name, variant: variant, sourceTag: sourceTag, targetTag: "${tag}-${arch}", sourceNamespace: sourceNamespace, targetNamespace: targetNamespace) + doTagAndPush(registry: registry, imageName: imageName, variant: variant, sourceTag: sourceTag, targetTag: "${tag}-${arch}", sourceNamespace: sourceNamespace, targetNamespace: targetNamespace) } } } @@ -89,7 +84,7 @@ def call(Map args = [:]) { /** * Tag and push the source docker image. It retries to add resilience. * -* @param name of the docker image +* @param imageName of the docker image * @param variant name of the variant used to build the docker image name * @param sourceNamespace namespace to be used as source for the docker tag command * @param targetNamespace namespace to be used as target for the docker tag command @@ -97,7 +92,7 @@ def call(Map args = [:]) { * @param targetTag tag to be used as target for the docker tag command, usually under the 'observability-ci' namespace */ def doTagAndPush(Map args = [:]) { - def name = args.name + def name = args.imageName def variant = args.variant def sourceTag = args.sourceTag def targetTag = args.targetTag diff --git a/vars/pushDockerImages.txt b/vars/pushDockerImages.txt index dbff79564..59d70895f 100644 --- a/vars/pushDockerImages.txt +++ b/vars/pushDockerImages.txt @@ -15,14 +15,12 @@ namespaces/registries. arch: 'amd64', version: '8.2.0', snapshot: true, - project: [ - name: 'filebeat', - variants: [ - '' : 'beats', - 'ubi8' : 'beats', - 'cloud' : 'beats-ci', - 'complete' : 'beats', - ] + imageName: 'filebeat', + variants: [ + '' : 'beats', + 'ubi8' : 'beats', + 'cloud' : 'beats-ci', + 'complete' : 'beats', ], targetNamespace: 'observability-ci' ) @@ -33,9 +31,8 @@ namespaces/registries. * arch: the supported arch (amd64 or arm64) * version: what version * snapshot: snapshot support +* imageName: the docker image name. +* variants: variants and docker namespace to copy from. * targetNamespace: what docker namespace to publish to. -* project: data structure to identify the name of the docker image, - what variants and what docker namespace to copy from. - __NOTE__: It requires *Nix where to run it from. From 4f0c192a694c3cbd31d8090962b8f89f8f878be9 Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Mon, 21 Feb 2022 11:05:32 +0000 Subject: [PATCH 05/14] Update vars/pushDockerImages.txt --- vars/pushDockerImages.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vars/pushDockerImages.txt b/vars/pushDockerImages.txt index 59d70895f..082cac968 100644 --- a/vars/pushDockerImages.txt +++ b/vars/pushDockerImages.txt @@ -18,9 +18,9 @@ namespaces/registries. imageName: 'filebeat', variants: [ '' : 'beats', - 'ubi8' : 'beats', - 'cloud' : 'beats-ci', - 'complete' : 'beats', + '-ubi8' : 'beats', + '-cloud' : 'beats-ci', + '-complete' : 'beats', ], targetNamespace: 'observability-ci' ) From 1c13fc66b7fbf8eda20da686a09a34dfaaa540b5 Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Mon, 21 Feb 2022 11:07:11 +0000 Subject: [PATCH 06/14] Update vars/pushDockerImages.groovy --- vars/pushDockerImages.groovy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vars/pushDockerImages.groovy b/vars/pushDockerImages.groovy index 76f217396..b71514fc0 100644 --- a/vars/pushDockerImages.groovy +++ b/vars/pushDockerImages.groovy @@ -33,9 +33,9 @@ namespaces/registries. imageName : 'filebeat', variants: [ '' : 'beats', - 'ubi8' : 'beats', - 'cloud' : 'beats-ci', - 'complete' : 'beats', + '-ubi8' : 'beats', + '-cloud' : 'beats-ci', + '-complete' : 'beats', ], targetNamespace: 'observability-ci' ) From 0b34a683dbeb8c6cf6eae94f4df70f780782fcd4 Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Mon, 21 Feb 2022 11:23:57 +0000 Subject: [PATCH 07/14] sleep with the step itself --- vars/pushDockerImages.groovy | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vars/pushDockerImages.groovy b/vars/pushDockerImages.groovy index b71514fc0..7122082eb 100644 --- a/vars/pushDockerImages.groovy +++ b/vars/pushDockerImages.groovy @@ -104,7 +104,7 @@ def doTagAndPush(Map args = [:]) { def targetName = "${registry}/${targetNamespace}/${name}${variant}:${targetTag}" def iterations = 0 - waitUntil { + waitUntil(initialRecurrencePeriod: 5000) { iterations++ def status = sh(label: "Change tag and push ${targetName}", script: """#!/bin/bash @@ -118,7 +118,6 @@ def doTagAndPush(Map args = [:]) { fi""", returnStatus: true) if (status > 0 && iterations < 3) { - sleep 5 * iterations return false } else if (status > 0) { return false From 55bcf25dc030deaf549fa4f34a10d91b3ba737eb Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Mon, 21 Feb 2022 11:24:09 +0000 Subject: [PATCH 08/14] remove print --- vars/pushDockerImages.groovy | 1 - 1 file changed, 1 deletion(-) diff --git a/vars/pushDockerImages.groovy b/vars/pushDockerImages.groovy index 7122082eb..0ebfebfbb 100644 --- a/vars/pushDockerImages.groovy +++ b/vars/pushDockerImages.groovy @@ -66,7 +66,6 @@ def call(Map args = [:]) { // What docker tags are gonna be used def tags = calculateTags(sourceTag, aliasVersion) - println tags dockerLogin(secret: "${secret}", registry: "${registry}") variants?.each { variant, sourceNamespace -> tags.each { tag -> From 5b9e38413ec2365ace7857442ed42aa347abfc92 Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Mon, 21 Feb 2022 11:25:33 +0000 Subject: [PATCH 09/14] simplify conditional --- vars/pushDockerImages.groovy | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/vars/pushDockerImages.groovy b/vars/pushDockerImages.groovy index 0ebfebfbb..818e98c80 100644 --- a/vars/pushDockerImages.groovy +++ b/vars/pushDockerImages.groovy @@ -116,13 +116,8 @@ def doTagAndPush(Map args = [:]) { echo "docker image ${sourceName} does not exist" fi""", returnStatus: true) - if (status > 0 && iterations < 3) { - return false - } else if (status > 0) { - return false - } else { - return true - } + // exit if above command run successfully or it reached the max of iterations. + return (status == 0 || iterations >= 3) } } From e187d6444cec9c0a94f3b36a80ba24a5f1526252 Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Mon, 21 Feb 2022 11:36:46 +0000 Subject: [PATCH 10/14] add example --- vars/pushDockerImages.txt | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/vars/pushDockerImages.txt b/vars/pushDockerImages.txt index 082cac968..c20197022 100644 --- a/vars/pushDockerImages.txt +++ b/vars/pushDockerImages.txt @@ -26,6 +26,35 @@ namespaces/registries. ) ``` +``` + // Given the filebeat project, and its generated docker + // images for the 8.2.0-SNAPSHOT and 2 different variants + // then publish them to observability-ci + // Source images follow the format: + // - "my-registry/beats/filebeat:8.2.0-SNAPSHOT" + // - "my-registry/beats-customise/filebeat-ubi8:8.2.0-SNAPSHOT" + // Generated images follow the format: + // - "my-registry/observability-ci/filebeat:8.2.0-SNAPSHOT" + // - "my-registry/observability-ci/filebeat-ubi8:8.2.0-SNAPSHOT" + // - "my-registry/observability-ci/filebeat:8.2.0-SNAPSHOT-amd64" + // - "my-registry/observability-ci/filebeat-ubi8:8.2.0-SNAPSHOT-amd64" + pushDockerImages( + secret: "my-secret", + registry: "my-registry", + arch: 'amd64', + version: '8.2.0', + snapshot: true, + imageName: 'filebeat', + variants: [ + '' : 'beats', + '-ubi8' : 'beats-ci' + ], + targetNamespace: 'observability-ci' + ) + + +``` + * secret: the docker secret * registry: the docker registry * arch: the supported arch (amd64 or arm64) From d8e30f3c58d430b2fc59f49d4cac0f238337fc26 Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Mon, 21 Feb 2022 11:55:27 +0000 Subject: [PATCH 11/14] mock waitUntil with a Map --- src/test/groovy/ApmBasePipelineTest.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/groovy/ApmBasePipelineTest.groovy b/src/test/groovy/ApmBasePipelineTest.groovy index 8ee271eed..da914bd6f 100644 --- a/src/test/groovy/ApmBasePipelineTest.groovy +++ b/src/test/groovy/ApmBasePipelineTest.groovy @@ -233,6 +233,7 @@ class ApmBasePipelineTest extends DeclarativePipelineTest { helper.registerAllowedMethod('timestamps', [], null) helper.registerAllowedMethod('triggers', [Closure.class], null) helper.registerAllowedMethod('unstable', [Closure.class], { body -> body() }) + helper.registerAllowedMethod('waitUntil', [Map.class, Closure.class], { m, body -> body() }) } void registerScriptedMethods() { From 341b7cdfc74a3d494873c3106770245973bd90f8 Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Tue, 22 Feb 2022 10:37:17 +0000 Subject: [PATCH 12/14] Simplify the signature --- .../groovy/PushDockerImagesStepTests.groovy | 41 ++++---------- vars/pushDockerImages.groovy | 54 ++++++++----------- vars/pushDockerImages.txt | 53 ++++++++---------- 3 files changed, 53 insertions(+), 95 deletions(-) diff --git a/src/test/groovy/PushDockerImagesStepTests.groovy b/src/test/groovy/PushDockerImagesStepTests.groovy index e041f8af5..8031d72f9 100644 --- a/src/test/groovy/PushDockerImagesStepTests.groovy +++ b/src/test/groovy/PushDockerImagesStepTests.groovy @@ -49,12 +49,6 @@ class PushDockerImagesStepTests extends ApmBasePipelineTest { script.call(registry: 'foo') } } - @Test - void test_missing_targetNamespace() throws Exception { - testMissingArgument('targetNamespace') { - script.call(registry: 'foo', secret: 'bar') - } - } @Test void test_missing_version() throws Exception { @@ -63,13 +57,6 @@ class PushDockerImagesStepTests extends ApmBasePipelineTest { } } - @Test - void test_missing_imageName() throws Exception { - testMissingArgument('imageName') { - script.call(registry: 'foo', secret: 'bar', targetNamespace: 'target', version: '1.2') - } - } - @Test void test_calculateTags_pr() throws Exception { helper.registerAllowedMethod('isPR', { return true }) @@ -95,12 +82,10 @@ class PushDockerImagesStepTests extends ApmBasePipelineTest { void test_doTagAndPush() throws Exception { helper.registerAllowedMethod('sh', [Map.class], { return 0 }) script.doTagAndPush(registry: 'my-registry', - imageName: 'my-name', - variant: '-cloud', sourceTag: '8.2-SNAPSHOT', targetTag: 'commit', - sourceNamespace: 'beats', - targetNamespace: 'beats-ci') + source: 'beats/my-name-cloud', + target: 'beats-ci/my-name-cloud') printCallStack() assertTrue(assertMethodCallContainsPattern('sh', '"my-registry/beats/my-name-cloud:8.2-SNAPSHOT" "my-registry/beats-ci/my-name-cloud:commit"')) } @@ -111,15 +96,12 @@ class PushDockerImagesStepTests extends ApmBasePipelineTest { script.call( secret: "my-secret", registry: "my-registry", - arch: 'amd64', version: '8.2.0', snapshot: true, - imageName: 'filebeat', - variants: [ - '' : 'beats', - '-cloud' : 'beats-ci' - ], - targetNamespace: 'observability-ci' + images: [ + [ source: "beats/filebeat", arch: 'amd64', target: "observability-ci/filebeat"], + [ source: "beats-ci/filebeat-cloud", arch: 'amd64', target: "observability-ci/filebeat-cloud"] + ] ) printCallStack() assertTrue(assertMethodCallOccurrences('sh', 12)) @@ -131,15 +113,12 @@ class PushDockerImagesStepTests extends ApmBasePipelineTest { script.call( secret: "my-secret", registry: "my-registry", - arch: 'amd64', version: '8.2.0', snapshot: false, - imageName: 'filebeat', - variants: [ - '' : 'beats', - '-cloud' : 'beats-ci' - ], - targetNamespace: 'observability-ci' + images: [ + [ source: "beats/filebeat", arch: 'amd64', target: "observability-ci/filebeat"], + [ source: "beats-ci/filebeat-cloud", arch: 'amd64', target: "observability-ci/filebeat-cloud"] + ] ) printCallStack() assertTrue(assertMethodCallOccurrences('sh', 8)) diff --git a/vars/pushDockerImages.groovy b/vars/pushDockerImages.groovy index 818e98c80..36188b3e2 100644 --- a/vars/pushDockerImages.groovy +++ b/vars/pushDockerImages.groovy @@ -17,27 +17,21 @@ /** -Publish docker images in the given docker registry. For such, it +Publish the give docker images in the given docker registry. For such, it retags the existing docker images and publish them in the given docker namespace. -It also allows to transform the version and customise private docker -namespaces/registries. - pushDockerImages( - secret: "my-secret", registry: "my-registry", - arch: 'amd64', + secret: "my-secret", version: '8.2.0', snapshot: true, - imageName : 'filebeat', - variants: [ - '' : 'beats', - '-ubi8' : 'beats', - '-cloud' : 'beats-ci', - '-complete' : 'beats', - ], - targetNamespace: 'observability-ci' + images: [ + [ source: "beats/filebeat", arch: 'amd64', target: "observability-ci/filebeat"], + [ source: "beats/filebeat-ubi8", arch: 'amd64', target: "observability-ci/filebeat-ubi8"], + [ source: "beats-ci/filebeat-cloud", arch: 'amd64', target: "observability-ci/filebeat-cloud"], + [ source: "beats-ci/filebeat-complete", arch: 'amd64', target: "observability-ci/filebeat-complete"] + ] ) */ @@ -47,12 +41,9 @@ def call(Map args = [:]) { } def registry = args.containsKey('registry') ? args.registry : error('pushDockerImages: registry parameter is required') def secret = args.containsKey('secret') ? args.secret : error('pushDockerImages: secret parameter is required') - def targetNamespace = args.containsKey('targetNamespace') ? args.targetNamespace : error('pushDockerImages: targetNamespace parameter is required') def version = args.containsKey('version') ? args.version : error('pushDockerImages: version parameter is required') - def imageName = args.containsKey('imageName') ? args.imageName : error('pushDockerImages: imageName parameter is required') - def arch = args.get('arch', 'amd64') - def variants = args.get('variants', [:]) def snapshot = args.get('snapshot', true) + def images = args.get('images', [:]) // Transform version in a snapshot. def sourceTag = version @@ -67,15 +58,15 @@ def call(Map args = [:]) { def tags = calculateTags(sourceTag, aliasVersion) dockerLogin(secret: "${secret}", registry: "${registry}") - variants?.each { variant, sourceNamespace -> + images?.each { image -> tags.each { tag -> // TODO: // For backward compatibility let's ensure we tag only for amd64, then E2E can benefit from until // they support the versioning with the architecture - if ("${arch}" == "amd64") { - doTagAndPush(registry: registry, imageName: imageName, variant: variant, sourceTag: sourceTag, targetTag: "${tag}", sourceNamespace: sourceNamespace, targetNamespace: targetNamespace) + if ("${image.arch}" == "amd64") { + doTagAndPush(registry: registry, sourceTag: sourceTag, targetTag: "${tag}", source: image.source, target: image.target) } - doTagAndPush(registry: registry, imageName: imageName, variant: variant, sourceTag: sourceTag, targetTag: "${tag}-${arch}", sourceNamespace: sourceNamespace, targetNamespace: targetNamespace) + doTagAndPush(registry: registry, sourceTag: sourceTag, targetTag: "${tag}-${image.arch}", source: image.source, target: image.target) } } } @@ -83,24 +74,21 @@ def call(Map args = [:]) { /** * Tag and push the source docker image. It retries to add resilience. * -* @param imageName of the docker image -* @param variant name of the variant used to build the docker image name -* @param sourceNamespace namespace to be used as source for the docker tag command -* @param targetNamespace namespace to be used as target for the docker tag command +* @param source the namespace and docker image to be used +* @param target the namespace and docker image to be pushed * @param sourceTag tag to be used as source for the docker tag command, usually under the 'beats' namespace * @param targetTag tag to be used as target for the docker tag command, usually under the 'observability-ci' namespace +* @param registry the docker registry */ def doTagAndPush(Map args = [:]) { - def name = args.imageName - def variant = args.variant + def registry = args.registry + def source = args.source def sourceTag = args.sourceTag + def target = args.target def targetTag = args.targetTag - def sourceNamespace = args.sourceNamespace - def targetNamespace = args.targetNamespace - def registry = args.registry - def sourceName = "${registry}/${sourceNamespace}/${name}${variant}:${sourceTag}" - def targetName = "${registry}/${targetNamespace}/${name}${variant}:${targetTag}" + def sourceName = "${registry}/${source}:${sourceTag}" + def targetName = "${registry}/${target}:${targetTag}" def iterations = 0 waitUntil(initialRecurrencePeriod: 5000) { diff --git a/vars/pushDockerImages.txt b/vars/pushDockerImages.txt index c20197022..b348684ff 100644 --- a/vars/pushDockerImages.txt +++ b/vars/pushDockerImages.txt @@ -2,27 +2,26 @@ Publish docker images in the given docker registry. For such, it retags the existing docker images and publish them in the given docker namespace. -It also allows to transform the version and customise private docker -namespaces/registries. +It uses a map of images, this map contains an entry for each docker image +to be pushed, what architecture and the name of the docker image to be pushed. + +The version is required to tag the docker image accordingly and also it uses +the snapshot if needed. ``` // Given the filebeat project, and its generated docker - // images for the 8.2.0-SNAPSHOT and 4 different variants - // then publish them to observability-ci + // images for the 8.2.0-SNAPSHOT and 2 different variants + // then publish them to the observability-ci namespace. In addition + // tag them as default, arch=amd64 is the default tag image pushDockerImages( - secret: "my-secret", registry: "my-registry", - arch: 'amd64', + secret: "my-secret", version: '8.2.0', snapshot: true, - imageName: 'filebeat', - variants: [ - '' : 'beats', - '-ubi8' : 'beats', - '-cloud' : 'beats-ci', - '-complete' : 'beats', - ], - targetNamespace: 'observability-ci' + images: [ + [ source: "beats/filebeat", arch: 'amd64', target: "observability-ci/filebeat"], + [ source: "beats/filebeat-ubi8", arch: 'amd64', target: "observability-ci/filebeat-ubi8"] + ] ) ``` @@ -32,36 +31,28 @@ namespaces/registries. // then publish them to observability-ci // Source images follow the format: // - "my-registry/beats/filebeat:8.2.0-SNAPSHOT" - // - "my-registry/beats-customise/filebeat-ubi8:8.2.0-SNAPSHOT" + // - "my-registry/beats-ci/filebeat-cloud:8.2.0-SNAPSHOT" // Generated images follow the format: // - "my-registry/observability-ci/filebeat:8.2.0-SNAPSHOT" - // - "my-registry/observability-ci/filebeat-ubi8:8.2.0-SNAPSHOT" + // - "my-registry/observability-ci/filebeat-cloud:8.2.0-SNAPSHOT" // - "my-registry/observability-ci/filebeat:8.2.0-SNAPSHOT-amd64" - // - "my-registry/observability-ci/filebeat-ubi8:8.2.0-SNAPSHOT-amd64" + // - "my-registry/observability-ci/filebeat-cloud:8.2.0-SNAPSHOT-amd64" pushDockerImages( - secret: "my-secret", registry: "my-registry", - arch: 'amd64', + secret: "my-secret", version: '8.2.0', snapshot: true, - imageName: 'filebeat', - variants: [ - '' : 'beats', - '-ubi8' : 'beats-ci' - ], - targetNamespace: 'observability-ci' + images: [ + [ source: "beats/filebeat", arch: 'amd64', target: "observability-ci/filebeat"], + [ source: "beats-ci/filebeat-cloud", arch: 'amd64', target: "observability-ci/filebeat-ubi8"] + ] ) - - ``` * secret: the docker secret * registry: the docker registry -* arch: the supported arch (amd64 or arm64) * version: what version * snapshot: snapshot support -* imageName: the docker image name. -* variants: variants and docker namespace to copy from. -* targetNamespace: what docker namespace to publish to. +* images: list of the docker image to be retagged to, architecture and docker image to be pushed to. __NOTE__: It requires *Nix where to run it from. From 7b575415d9be008237b2d5fcf4d1f06055cecd56 Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Tue, 22 Feb 2022 10:37:34 +0000 Subject: [PATCH 13/14] fix typo --- vars/pushDockerImages.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vars/pushDockerImages.groovy b/vars/pushDockerImages.groovy index 36188b3e2..a456ec49d 100644 --- a/vars/pushDockerImages.groovy +++ b/vars/pushDockerImages.groovy @@ -37,7 +37,7 @@ docker namespace. */ def call(Map args = [:]) { if(!isUnix()){ - error('publishToCDN: windows is not supported yet.') + error('pushDockerImages: windows is not supported yet.') } def registry = args.containsKey('registry') ? args.registry : error('pushDockerImages: registry parameter is required') def secret = args.containsKey('secret') ? args.secret : error('pushDockerImages: secret parameter is required') From 981b31ebbb939bb1a4fbe8b8dbf1353ef1939d61 Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Tue, 22 Feb 2022 10:37:52 +0000 Subject: [PATCH 14/14] update docs --- vars/README.md | 74 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/vars/README.md b/vars/README.md index 441cc9431..a32a1fb7c 100644 --- a/vars/README.md +++ b/vars/README.md @@ -184,6 +184,7 @@ Override the `build` step to highlight in BO the URL to the downstream job. ``` build(job: 'foo', parameters: [string(name: "my param", value: some_value)]) +build 'foo' ``` See https://jenkins.io/doc/pipeline/steps/pipeline-build-step/#build-build-a-job @@ -194,9 +195,11 @@ Builds the Docker image for Kibana, from a branch or a pull Request. ``` buildKibanaDockerImage(refspec: 'main') buildKibanaDockerImage(refspec: 'PR/12345') +buildKibanaDockerImage(refspec: 'cf25ac3d1f8edff8f20003add707bfdc85d89fff', depth: 10) + ``` -* refspec: A branch (i.e. main), or a pull request identified by the "pr/" prefix and the pull request ID. +* refspec: A branch (i.e. main), a commit SHA, a tag, or a pull request identified by the "pr/" prefix and the pull request ID. * packageJSON: Full name of the package.json file. Defaults to 'package.json' * baseDir: Directory where to clone the Kibana repository. Defaults to "${env.BASE_DIR}/build" * credentialsId: Credentials used access Github repositories. @@ -205,6 +208,9 @@ buildKibanaDockerImage(refspec: 'PR/12345') * dockerRegistrySecret: Name of the Vault secret with the credentials for logining into the registry. Defaults to 'secret/observability-team/ci/docker-registry/prod' * dockerImageSource: Name of the source Docker image when tagging. Defaults to '${dockerRegistry}/kibana/kibana' * dockerImageTarget: Name of the target Docker image to be tagged. Defaults to '${dockerRegistry}/observability-ci/kibana' +* reference: Path to the Git reference repo to improve checkout speed. Default to '/var/lib/jenkins/kibana.git' +* depth: Number of commits pull down in the Git shallow clone. Default to 1 +* shallow: Enable shallow cloning. Default to true. ## buildStatus Fetch the current build status for a given job @@ -667,7 +673,7 @@ update the name of the branch when a new minor release branch is created. ``` // Return the branch name for the main, 8.minor and 8.next-minor branches -def branches = getBranchesFromAliases(aliases: ['main', '8.', '8.']) +def branches = getBranchesFromAliases(aliases: ['main', '8.', '8.']) ``` @@ -1543,6 +1549,7 @@ Upload the given pattern files to the given bucket. * credentialsId: The credentials to access the repo (repo permissions). Optional. Default to `JOB_GCS_CREDENTIALS` * pattern: The file to pattern to search and copy. Mandatory. * sharedPublicly: Whether to shared those objects publicly. Optional. Default false. +* extraFlags: Extra flags to use with gsutil cp. Optional ## gsutil Wrapper to interact with the gsutil command line. It returns the stdout output. @@ -2526,6 +2533,66 @@ with the given headers. __NOTE__: It requires *Nix where to run it from. +## pushDockerImages +Publish docker images in the given docker registry. For such, it +retags the existing docker images and publish them in the given +docker namespace. + +It uses a map of images, this map contains an entry for each docker image +to be pushed, what architecture and the name of the docker image to be pushed. + +The version is required to tag the docker image accordingly and also it uses +the snapshot if needed. + +``` + // Given the filebeat project, and its generated docker + // images for the 8.2.0-SNAPSHOT and 2 different variants + // then publish them to the observability-ci namespace. In addition + // tag them as default, arch=amd64 is the default tag image + pushDockerImages( + registry: "my-registry", + secret: "my-secret", + version: '8.2.0', + snapshot: true, + images: [ + [ source: "beats/filebeat", arch: 'amd64', target: "observability-ci/filebeat"], + [ source: "beats/filebeat-ubi8", arch: 'amd64', target: "observability-ci/filebeat-ubi8"] + ] + ) +``` + +``` + // Given the filebeat project, and its generated docker + // images for the 8.2.0-SNAPSHOT and 2 different variants + // then publish them to observability-ci + // Source images follow the format: + // - "my-registry/beats/filebeat:8.2.0-SNAPSHOT" + // - "my-registry/beats-ci/filebeat-cloud:8.2.0-SNAPSHOT" + // Generated images follow the format: + // - "my-registry/observability-ci/filebeat:8.2.0-SNAPSHOT" + // - "my-registry/observability-ci/filebeat-cloud:8.2.0-SNAPSHOT" + // - "my-registry/observability-ci/filebeat:8.2.0-SNAPSHOT-amd64" + // - "my-registry/observability-ci/filebeat-cloud:8.2.0-SNAPSHOT-amd64" + pushDockerImages( + registry: "my-registry", + secret: "my-secret", + version: '8.2.0', + snapshot: true, + images: [ + [ source: "beats/filebeat", arch: 'amd64', target: "observability-ci/filebeat"], + [ source: "beats-ci/filebeat-cloud", arch: 'amd64', target: "observability-ci/filebeat-ubi8"] + ] + ) +``` + +* secret: the docker secret +* registry: the docker registry +* version: what version +* snapshot: snapshot support +* images: list of the docker image to be retagged to, architecture and docker image to be pushed to. + +__NOTE__: It requires *Nix where to run it from. + ## randomNumber it generates a random number, by default the number is between 1 to 100. @@ -3049,9 +3116,10 @@ not overridden once they are created. ``` * repo: The GitHub repository name. Optional. Default to `REPO` -* bucket: The Google Storage bucket name. Mandatory +* bucket: The Google Storage bucket name. Optional. Default to `JOB_GCS_BUCKET` * credentialsId: The credentials to access the repo (repo permissions). Optional. Default to `JOB_GCS_CREDENTIALS` * pattern: The file to pattern to search and copy. Optional. Default to `build/distributions/**/*` +* folder: The folder to be added to the calculated bucket uri folder. Optional. NOTE: It works with the Multibranch Pipeline only, therefore it requires to use `gitCheckout` to be able to populate the gitBaseCommit.