From f4f54708068870cdc6a1076cc0be22070d3c2382 Mon Sep 17 00:00:00 2001 From: Sascha Schwarze Date: Thu, 21 Nov 2024 21:18:22 +0100 Subject: [PATCH] Extend Dockerfile based build strategies with target build stage Signed-off-by: Sascha Schwarze --- ...gy_buildah_shipwright_managed_push_cr.yaml | 29 +++++-- ...tegy_buildah_strategy_managed_push_cr.yaml | 23 ++++- .../buildkit/buildstrategy_buildkit_cr.yaml | 87 ++++++++++--------- .../kaniko/buildstrategy_kaniko_cr.yaml | 14 ++- .../build_buildah_cr_target_stage.yaml | 23 +++++ .../build_buildkit_cr_target_stage.yaml | 23 +++++ .../v1beta1/build_kaniko_cr_target_stage.yaml | 23 +++++ .../buildrun_buildah_cr_target_stage.yaml | 8 ++ .../buildrun_buildkit_cr_target_stage.yaml | 8 ++ .../buildrun_kaniko_cr_target_stage.yaml | 8 ++ test/e2e/v1beta1/e2e_test.go | 66 ++++++++++++++ 11 files changed, 258 insertions(+), 54 deletions(-) create mode 100644 test/data/v1beta1/build_buildah_cr_target_stage.yaml create mode 100644 test/data/v1beta1/build_buildkit_cr_target_stage.yaml create mode 100644 test/data/v1beta1/build_kaniko_cr_target_stage.yaml create mode 100644 test/data/v1beta1/buildrun_buildah_cr_target_stage.yaml create mode 100644 test/data/v1beta1/buildrun_buildkit_cr_target_stage.yaml create mode 100644 test/data/v1beta1/buildrun_kaniko_cr_target_stage.yaml diff --git a/samples/v1beta1/buildstrategy/buildah/buildstrategy_buildah_shipwright_managed_push_cr.yaml b/samples/v1beta1/buildstrategy/buildah/buildstrategy_buildah_shipwright_managed_push_cr.yaml index 468dda51ae..b98c43c5cc 100644 --- a/samples/v1beta1/buildstrategy/buildah/buildstrategy_buildah_shipwright_managed_push_cr.yaml +++ b/samples/v1beta1/buildstrategy/buildah/buildstrategy_buildah_shipwright_managed_push_cr.yaml @@ -22,8 +22,8 @@ spec: context= dockerfile= image= - target= - buildArgs=() + outputDirectory= + budArgs=() inBuildArgs=false registriesBlock="" inRegistriesBlock=false @@ -56,12 +56,21 @@ spec: inRegistriesSearch=false image="$1" shift + elif [ "${arg}" == "--output-directory" ]; then + inBuildArgs=false + inRegistriesBlock=false + inRegistriesInsecure=false + inRegistriesSearch=false + outputDirectory="$1" + shift elif [ "${arg}" == "--target" ]; then inBuildArgs=false inRegistriesBlock=false inRegistriesInsecure=false inRegistriesSearch=false - target="$1" + if [ "$1" != "" ]; then + budArgs+=(--target "$1") + fi shift elif [ "${arg}" == "--build-args" ]; then inBuildArgs=true @@ -84,7 +93,7 @@ spec: inRegistriesBlock=false inRegistriesInsecure=false elif [ "${inBuildArgs}" == "true" ]; then - buildArgs+=("--build-arg" "${arg}") + budArgs+=(--build-arg "${arg}") elif [ "${inRegistriesBlock}" == "true" ]; then registriesBlock="${registriesBlock}'${arg}', " elif [ "${inRegistriesInsecure}" == "true" ]; then @@ -140,7 +149,7 @@ spec: # Building the image echo "[INFO] Building image ${image}" buildah --storage-driver=$(params.storage-driver) \ - bud "${buildArgs[@]}" \ + bud "${budArgs[@]}" \ --registries-conf=/tmp/registries.conf \ --tag="${image}" \ --file="${dockerfile}" \ @@ -150,11 +159,13 @@ spec: echo "[INFO] Writing image ${image}" buildah --storage-driver=$(params.storage-driver) push \ "${image}" \ - "oci:${target}" + "oci:${outputDirectory}" # That's the separator between the shell script and its args - -- - --context - $(params.shp-source-context) + - --output-directory + - $(params.shp-output-directory) - --dockerfile - $(params.dockerfile) - --image @@ -168,7 +179,7 @@ spec: - --registries-search - $(params.registries-search[*]) - --target - - $(params.shp-output-directory) + - $(params.target) resources: limits: cpu: "1" @@ -204,6 +215,10 @@ spec: type: string default: "vfs" # For details see the "--storage-driver" section of https://github.com/containers/buildah/blob/main/docs/buildah.1.md#options + - name: target + description: "Sets the target stage to be built." + type: string + default: "" securityContext: runAsUser: 0 runAsGroup: 0 diff --git a/samples/v1beta1/buildstrategy/buildah/buildstrategy_buildah_strategy_managed_push_cr.yaml b/samples/v1beta1/buildstrategy/buildah/buildstrategy_buildah_strategy_managed_push_cr.yaml index ed6b0792a4..f552bbf62a 100644 --- a/samples/v1beta1/buildstrategy/buildah/buildstrategy_buildah_strategy_managed_push_cr.yaml +++ b/samples/v1beta1/buildstrategy/buildah/buildstrategy_buildah_strategy_managed_push_cr.yaml @@ -24,7 +24,7 @@ spec: context= dockerfile= image= - buildArgs=() + budArgs=() inBuildArgs=false registriesBlock="" inRegistriesBlock=false @@ -58,6 +58,15 @@ spec: inRegistriesSearch=false image="$1" shift + elif [ "${arg}" == "--target" ]; then + inBuildArgs=false + inRegistriesBlock=false + inRegistriesInsecure=false + inRegistriesSearch=false + if [ "$1" != "" ]; then + budArgs+=(--target "$1") + fi + shift elif [ "${arg}" == "--build-args" ]; then inBuildArgs=true inRegistriesBlock=false @@ -79,7 +88,7 @@ spec: inRegistriesBlock=false inRegistriesInsecure=false elif [ "${inBuildArgs}" == "true" ]; then - buildArgs+=("--build-arg" "${arg}") + budArgs+=(--build-arg "${arg}") elif [ "${inRegistriesBlock}" == "true" ]; then registriesBlock="${registriesBlock}'${arg}', " elif [ "${inRegistriesInsecure}" == "true" ]; then @@ -140,7 +149,7 @@ spec: # Building the image echo "[INFO] Building image ${image}" buildah --storage-driver=$(params.storage-driver) \ - bud "${buildArgs[@]}" \ + bud "${budArgs[@]}" \ --registries-conf=/tmp/registries.conf \ --tag="${image}" \ --file="${dockerfile}" \ @@ -169,6 +178,8 @@ spec: - $(params.registries-insecure[*]) - --registries-search - $(params.registries-search[*]) + - --target + - $(params.target) resources: limits: cpu: "1" @@ -200,10 +211,14 @@ spec: type: string default: "Dockerfile" - name: storage-driver - description: "The storage driver to use, such as 'overlay' or 'vfs'" + description: "The storage driver to use, such as 'overlay' or 'vfs'." type: string default: "vfs" # For details see the "--storage-driver" section of https://github.com/containers/buildah/blob/main/docs/buildah.1.md#options + - name: target + description: "Sets the target stage to be built." + type: string + default: "" securityContext: runAsUser: 0 runAsGroup: 0 diff --git a/samples/v1beta1/buildstrategy/buildkit/buildstrategy_buildkit_cr.yaml b/samples/v1beta1/buildstrategy/buildkit/buildstrategy_buildkit_cr.yaml index fddd6bb748..546f8c4409 100644 --- a/samples/v1beta1/buildstrategy/buildkit/buildstrategy_buildkit_cr.yaml +++ b/samples/v1beta1/buildstrategy/buildkit/buildstrategy_buildkit_cr.yaml @@ -11,26 +11,30 @@ metadata: container.seccomp.security.alpha.kubernetes.io/step-build-and-push: unconfined spec: parameters: - - name: build-args - description: "The values for the ARGs in the Dockerfile. Values must be in the format KEY=VALUE." - type: array - defaults: [] - - name: cache - description: "Configure BuildKit's cache usage. Allowed values are 'disabled' and 'registry'. The default is 'registry'." - type: string - default: registry - - name: platforms - description: "Build the image for different platforms. By default, the image is built for the platform used by the FROM image. If that is present for multiple platforms, then it is built for the environment's platform." - type: array - defaults: [] - - name: secrets - description: "The secrets to pass to the build. Values must be in the format ID=FILE_CONTENT." - type: array - defaults: [] - - name: dockerfile - description: The path to the Dockerfile to be used for building the image. - type: string - default: "Dockerfile" + - name: build-args + description: "The values for the ARGs in the Dockerfile. Values must be in the format KEY=VALUE." + type: array + defaults: [] + - name: cache + description: "Configure BuildKit's cache usage. Allowed values are 'disabled' and 'registry'. The default is 'registry'." + type: string + default: registry + - name: dockerfile + description: The path to the Dockerfile to be used for building the image. + type: string + default: Dockerfile + - name: platforms + description: "Build the image for different platforms. By default, the image is built for the platform used by the FROM image. If that is present for multiple platforms, then it is built for the environment's platform." + type: array + defaults: [] + - name: secrets + description: "The secrets to pass to the build. Values must be in the format ID=FILE_CONTENT." + type: array + defaults: [] + - name: target + description: "Sets the target stage to be built." + type: string + default: "" steps: - name: build-and-push image: moby/buildkit:v0.17.0-rootless @@ -43,25 +47,27 @@ spec: - SETUID workingDir: $(params.shp-source-root) env: - - name: DOCKER_CONFIG - value: /tekton/home/.docker - - name: HOME - value: /tekton/home - # See https://github.com/moby/buildkit/blob/master/docs/rootless.md#about---oci-worker-no-process-sandbox for more information - - name: BUILDKITD_FLAGS - value: --oci-worker-no-process-sandbox - - name: PARAM_SOURCE_CONTEXT - value: $(params.shp-source-context) - - name: PARAM_DOCKERFILE - value: $(params.dockerfile) - - name: PARAM_OUTPUT_DIRECTORY - value: $(params.shp-output-directory) - - name: PARAM_OUTPUT_IMAGE - value: $(params.shp-output-image) - - name: PARAM_OUTPUT_INSECURE - value: $(params.shp-output-insecure) - - name: PARAM_CACHE - value: $(params.cache) + - name: DOCKER_CONFIG + value: /tekton/home/.docker + - name: HOME + value: /tekton/home + # See https://github.com/moby/buildkit/blob/master/docs/rootless.md#about---oci-worker-no-process-sandbox for more information + - name: BUILDKITD_FLAGS + value: --oci-worker-no-process-sandbox + - name: PARAM_SOURCE_CONTEXT + value: $(params.shp-source-context) + - name: PARAM_DOCKERFILE + value: $(params.dockerfile) + - name: PARAM_OUTPUT_DIRECTORY + value: $(params.shp-output-directory) + - name: PARAM_OUTPUT_IMAGE + value: $(params.shp-output-image) + - name: PARAM_OUTPUT_INSECURE + value: $(params.shp-output-insecure) + - name: PARAM_CACHE + value: $(params.cache) + - name: PARAM_TARGET + value: $(params.target) command: - /bin/ash args: @@ -112,6 +118,9 @@ spec: echo -n "An invalid value for the parameter 'cache' has been provided: '${PARAM_CACHE}'. Allowed values are 'disabled' and 'registry'." > '$(results.shp-error-message.path)' exit 1 fi + if [ "${PARAM_TARGET}" != "" ]; then + echo "--opt=target=${PARAM_TARGET} \\" >> /tmp/run.sh + fi stage="" platforms="" diff --git a/samples/v1beta1/buildstrategy/kaniko/buildstrategy_kaniko_cr.yaml b/samples/v1beta1/buildstrategy/kaniko/buildstrategy_kaniko_cr.yaml index a96976c1d6..54587bb707 100644 --- a/samples/v1beta1/buildstrategy/kaniko/buildstrategy_kaniko_cr.yaml +++ b/samples/v1beta1/buildstrategy/kaniko/buildstrategy_kaniko_cr.yaml @@ -41,6 +41,8 @@ spec: - --no-push - --tar-path - $(params.shp-output-directory)/image.tar + - --target + - $(params.target) # https://github.com/GoogleContainerTools/kaniko/issues/2164 - --ignore-path - /product_uuid @@ -52,10 +54,14 @@ spec: cpu: 250m memory: 65Mi parameters: - - name: dockerfile - description: The path to the Dockerfile to be used for building the image. - type: string - default: "Dockerfile" + - name: dockerfile + description: The path to the Dockerfile to be used for building the image. + type: string + default: "Dockerfile" + - name: target + description: "Sets the target stage to be built." + type: string + default: "" securityContext: runAsUser: 0 runAsGroup: 0 diff --git a/test/data/v1beta1/build_buildah_cr_target_stage.yaml b/test/data/v1beta1/build_buildah_cr_target_stage.yaml new file mode 100644 index 0000000000..2cdbfe1cc0 --- /dev/null +++ b/test/data/v1beta1/build_buildah_cr_target_stage.yaml @@ -0,0 +1,23 @@ +--- +apiVersion: shipwright.io/v1beta1 +kind: Build +metadata: + name: buildah-target-stage +spec: + source: + type: Git + git: + url: https://github.com/shipwright-io/sample-go + contextDir: docker-build-with-broken-final-stage + strategy: + name: buildah-shipwright-managed-push + kind: ClusterBuildStrategy + paramValues: + - name: dockerfile + value: Dockerfile + - name: target + value: working-final + retention: + atBuildDeletion: false + output: + image: image-registry.openshift-image-registry.svc:5000/build-examples/advanced-dockerfile diff --git a/test/data/v1beta1/build_buildkit_cr_target_stage.yaml b/test/data/v1beta1/build_buildkit_cr_target_stage.yaml new file mode 100644 index 0000000000..fc1d98755e --- /dev/null +++ b/test/data/v1beta1/build_buildkit_cr_target_stage.yaml @@ -0,0 +1,23 @@ +--- +apiVersion: shipwright.io/v1beta1 +kind: Build +metadata: + name: buildkit-target-stage +spec: + source: + type: Git + git: + url: https://github.com/shipwright-io/sample-go + contextDir: docker-build-with-broken-final-stage + strategy: + name: buildkit + kind: ClusterBuildStrategy + paramValues: + - name: dockerfile + value: Dockerfile + - name: target + value: working-final + retention: + atBuildDeletion: false + output: + image: image-registry.openshift-image-registry.svc:5000/build-examples/advanced-dockerfile diff --git a/test/data/v1beta1/build_kaniko_cr_target_stage.yaml b/test/data/v1beta1/build_kaniko_cr_target_stage.yaml new file mode 100644 index 0000000000..4becdae791 --- /dev/null +++ b/test/data/v1beta1/build_kaniko_cr_target_stage.yaml @@ -0,0 +1,23 @@ +--- +apiVersion: shipwright.io/v1beta1 +kind: Build +metadata: + name: kaniko-target-stage +spec: + source: + type: Git + git: + url: https://github.com/shipwright-io/sample-go + contextDir: docker-build-with-broken-final-stage + strategy: + name: kaniko + kind: ClusterBuildStrategy + paramValues: + - name: dockerfile + value: Dockerfile + - name: target + value: working-final + retention: + atBuildDeletion: false + output: + image: image-registry.openshift-image-registry.svc:5000/build-examples/advanced-dockerfile diff --git a/test/data/v1beta1/buildrun_buildah_cr_target_stage.yaml b/test/data/v1beta1/buildrun_buildah_cr_target_stage.yaml new file mode 100644 index 0000000000..48009232fb --- /dev/null +++ b/test/data/v1beta1/buildrun_buildah_cr_target_stage.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: shipwright.io/v1beta1 +kind: BuildRun +metadata: + name: buildah-target-stage +spec: + build: + name: buildah-target-stage diff --git a/test/data/v1beta1/buildrun_buildkit_cr_target_stage.yaml b/test/data/v1beta1/buildrun_buildkit_cr_target_stage.yaml new file mode 100644 index 0000000000..84a752019a --- /dev/null +++ b/test/data/v1beta1/buildrun_buildkit_cr_target_stage.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: shipwright.io/v1beta1 +kind: BuildRun +metadata: + name: buildkit-target-stage +spec: + build: + name: buildkit-target-stage diff --git a/test/data/v1beta1/buildrun_kaniko_cr_target_stage.yaml b/test/data/v1beta1/buildrun_kaniko_cr_target_stage.yaml new file mode 100644 index 0000000000..1438d10578 --- /dev/null +++ b/test/data/v1beta1/buildrun_kaniko_cr_target_stage.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: shipwright.io/v1beta1 +kind: BuildRun +metadata: + name: kaniko-target-stage +spec: + build: + name: kaniko-target-stage diff --git a/test/e2e/v1beta1/e2e_test.go b/test/e2e/v1beta1/e2e_test.go index 490df8c961..7ea6befc39 100644 --- a/test/e2e/v1beta1/e2e_test.go +++ b/test/e2e/v1beta1/e2e_test.go @@ -116,6 +116,28 @@ var _ = Describe("For a Kubernetes cluster with Tekton and build installed", fun }) }) + Context("when a BuildAh build runs with a custom target stage", func() { + + BeforeEach(func() { + testID = generateTestID("buildah-custom-target-stage") + + // create the build definition + build = createBuild( + testBuild, + testID, + "test/data/v1beta1/build_buildah_cr_target_stage.yaml", + ) + }) + + It("successfully runs a build", func() { + buildRun, err = buildRunTestData(testBuild.Namespace, testID, "test/data/v1beta1/buildrun_buildah_cr_target_stage.yaml") + Expect(err).ToNot(HaveOccurred()) + + buildRun = validateBuildRunToSucceed(testBuild, buildRun) + testBuild.ValidateImageDigest(buildRun) + }) + }) + Context("when a heroku Buildpacks build is defined using a cluster strategy", func() { BeforeEach(func() { @@ -426,6 +448,28 @@ var _ = Describe("For a Kubernetes cluster with Tekton and build installed", fun }) }) + Context("when a Kaniko build runs with a custom target stage", func() { + + BeforeEach(func() { + testID = generateTestID("kaniko-custom-target-stage") + + // create the build definition + build = createBuild( + testBuild, + testID, + "test/data/v1beta1/build_kaniko_cr_target_stage.yaml", + ) + }) + + It("successfully runs a build", func() { + buildRun, err = buildRunTestData(testBuild.Namespace, testID, "test/data/v1beta1/buildrun_kaniko_cr_target_stage.yaml") + Expect(err).ToNot(HaveOccurred()) + + buildRun = validateBuildRunToSucceed(testBuild, buildRun) + testBuild.ValidateImageDigest(buildRun) + }) + }) + Context("when a Buildkit build with a contextDir and a path to a Dockerfile is defined", func() { BeforeEach(func() { @@ -458,6 +502,28 @@ var _ = Describe("For a Kubernetes cluster with Tekton and build installed", fun }) }) + Context("when a BuildKit build runs with a custom target stage", func() { + + BeforeEach(func() { + testID = generateTestID("buildkit-custom-target-stage") + + // create the build definition + build = createBuild( + testBuild, + testID, + "test/data/v1beta1/build_buildkit_cr_target_stage.yaml", + ) + }) + + It("successfully runs a build", func() { + buildRun, err = buildRunTestData(testBuild.Namespace, testID, "test/data/v1beta1/buildrun_buildkit_cr_target_stage.yaml") + Expect(err).ToNot(HaveOccurred()) + + buildRun = validateBuildRunToSucceed(testBuild, buildRun) + testBuild.ValidateImageDigest(buildRun) + }) + }) + Context("when a Multiarch Native Buildah build is defined", func() { BeforeEach(func() {