From 0cd30a401b184f7aeab9aec8cf969a4b1859ab3f Mon Sep 17 00:00:00 2001 From: arewm Date: Thu, 24 Oct 2024 18:21:16 -0400 Subject: [PATCH] Combine all FBC validation tasks into one This change combines the inspect-image, fbc-validate, and fbc-related-image-check into a single task. It depends on functionality that needs to be added to EC to parse the produced trusted artifact in order to assess whether the related images are valid. All of the old tasks will be deprecated and the required tasks need to be updated to require only ``` - [fbc-related-image-check, validate-fbc] ``` This will ensure that users can still be guaranteed to have a valid FBC fragment and appropriate related images. Signed-off-by: arewm --- hack/missing-ta-tasks.sh | 2 + pipelines/fbc-builder/README.md | 49 +- pipelines/fbc-builder/patch.yaml | 46 +- .../0.1/fbc-related-image-check.yaml | 1 + .../0.1/kustomization.yaml | 5 + task/fbc-related-image-check/0.2/MIGRATION.md | 48 ++ task/fbc-related-image-check/0.2/README.md | 18 + .../0.2/kustomization.yaml | 15 + task/fbc-validation/0.1/fbc-validation.yaml | 1 + task/fbc-validation/0.1/kustomization.yaml | 5 + task/fbc-validation/0.2/MIGRATION.md | 51 ++ task/fbc-validation/0.2/README.md | 0 task/fbc-validation/0.2/kustomization.yaml | 15 + task/inspect-image/0.1/inspect-image.yaml | 1 + task/inspect-image/0.1/kustomization.yaml | 0 task/inspect-image/0.2/MIGRATION.md | 65 +++ task/inspect-image/0.2/README.md | 28 ++ task/inspect-image/0.2/kustomization.yaml | 15 + task/validate-fbc/0.1/README.md | 29 ++ task/validate-fbc/0.1/TROUBLESHOOTING.md | 21 + task/validate-fbc/0.1/USAGE.md | 29 ++ task/validate-fbc/0.1/validate-fbc.yaml | 462 ++++++++++++++++++ task/validate-fbc/OWNERS | 5 + 23 files changed, 829 insertions(+), 82 deletions(-) create mode 100644 task/fbc-related-image-check/0.1/kustomization.yaml create mode 100644 task/fbc-related-image-check/0.2/MIGRATION.md create mode 100644 task/fbc-related-image-check/0.2/README.md create mode 100644 task/fbc-related-image-check/0.2/kustomization.yaml create mode 100644 task/fbc-validation/0.1/kustomization.yaml create mode 100644 task/fbc-validation/0.2/MIGRATION.md create mode 100644 task/fbc-validation/0.2/README.md create mode 100644 task/fbc-validation/0.2/kustomization.yaml create mode 100644 task/inspect-image/0.1/kustomization.yaml create mode 100644 task/inspect-image/0.2/MIGRATION.md create mode 100644 task/inspect-image/0.2/README.md create mode 100644 task/inspect-image/0.2/kustomization.yaml create mode 100644 task/validate-fbc/0.1/README.md create mode 100644 task/validate-fbc/0.1/TROUBLESHOOTING.md create mode 100644 task/validate-fbc/0.1/USAGE.md create mode 100644 task/validate-fbc/0.1/validate-fbc.yaml create mode 100644 task/validate-fbc/OWNERS diff --git a/hack/missing-ta-tasks.sh b/hack/missing-ta-tasks.sh index f53967abb..d7a8f5587 100755 --- a/hack/missing-ta-tasks.sh +++ b/hack/missing-ta-tasks.sh @@ -22,7 +22,9 @@ todo=( task/buildah-rhtap/0.1/buildah-rhtap.yaml task/download-sbom-from-url-in-attestation/0.1/download-sbom-from-url-in-attestation.yaml task/fbc-related-image-check/0.1/fbc-related-image-check.yaml + task/fbc-related-image-check/0.2/fbc-related-image-check.yaml task/fbc-validation/0.1/fbc-validation.yaml + task/fbc-validation/0.2/fbc-validation.yaml task/gather-deploy-images/0.1/gather-deploy-images.yaml task/generate-odcs-compose/0.2/generate-odcs-compose.yaml task/generate-odcs-compose/0.2/kustomization.yaml diff --git a/pipelines/fbc-builder/README.md b/pipelines/fbc-builder/README.md index 492877390..f1681e7cf 100644 --- a/pipelines/fbc-builder/README.md +++ b/pipelines/fbc-builder/README.md @@ -75,12 +75,6 @@ This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/reposito |IMAGE_URL| Fully qualified image name.| None| '$(tasks.build-image-index.results.IMAGE_URL)'| |POLICY_DIR| Path to directory containing Conftest policies.| /project/repository/| | |POLICY_NAMESPACE| Namespace for Conftest policy.| required_checks| | -### fbc-validation:0.1 task parameters -|name|description|default value|already set by| -|---|---|---|---| -|BASE_IMAGE| Fully qualified base image name.| None| '$(tasks.inspect-image.results.BASE_IMAGE)'| -|IMAGE_DIGEST| Image digest.| None| '$(tasks.build-image-index.results.IMAGE_DIGEST)'| -|IMAGE_URL| Fully qualified image name.| None| '$(tasks.build-image-index.results.IMAGE_URL)'| ### git-clone:0.1 task parameters |name|description|default value|already set by| |---|---|---|---| @@ -110,12 +104,6 @@ This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/reposito |image-url| Image URL for build by PipelineRun| None| '$(params.output-image)'| |rebuild| Rebuild the image if exists| false| '$(params.rebuild)'| |skip-checks| Skip checks against built image| false| '$(params.skip-checks)'| -### inspect-image:0.1 task parameters -|name|description|default value|already set by| -|---|---|---|---| -|DOCKER_AUTH| unused, should be removed in next task version| | | -|IMAGE_DIGEST| Image digest.| None| '$(tasks.build-image-index.results.IMAGE_DIGEST)'| -|IMAGE_URL| Fully qualified image name.| None| '$(tasks.build-image-index.results.IMAGE_URL)'| ### show-sbom:0.1 task parameters |name|description|default value|already set by| |---|---|---|---| @@ -130,6 +118,11 @@ This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/reposito |git-url| Git URL| None| '$(tasks.clone-repository.results.url)?rev=$(tasks.clone-repository.results.commit)'| |image-url| Image URL| None| '$(params.output-image)'| |pipelinerun-name| pipeline-run to annotate| None| '$(context.pipelineRun.name)'| +### validate-fbc:0.1 task parameters +|name|description|default value|already set by| +|---|---|---|---| +|IMAGE_DIGEST| Image digest.| None| '$(tasks.build-image-index.results.IMAGE_DIGEST)'| +|IMAGE_URL| Fully qualified image name.| None| '$(tasks.build-image-index.results.IMAGE_URL)'| ## Results |name|description|value| @@ -143,9 +136,9 @@ This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/reposito |name|description|used in params (taskname:taskrefversion:taskparam) |---|---|---| |IMAGES| List of all referenced image manifests| | -|IMAGE_DIGEST| Digest of the image just built| deprecated-base-image-check:0.4:IMAGE_DIGEST ; inspect-image:0.1:IMAGE_DIGEST ; fbc-validate:0.1:IMAGE_DIGEST| +|IMAGE_DIGEST| Digest of the image just built| deprecated-base-image-check:0.4:IMAGE_DIGEST ; validate-fbc:0.1:IMAGE_DIGEST| |IMAGE_REF| Image reference of the built image containing both the repository and the digest| | -|IMAGE_URL| Image repository and tag where the built image was pushed| show-sbom:0.1:IMAGE_URL ; deprecated-base-image-check:0.4:IMAGE_URL ; apply-tags:0.1:IMAGE ; inspect-image:0.1:IMAGE_URL ; fbc-validate:0.1:IMAGE_URL| +|IMAGE_URL| Image repository and tag where the built image was pushed| show-sbom:0.1:IMAGE_URL ; deprecated-base-image-check:0.4:IMAGE_URL ; apply-tags:0.1:IMAGE ; validate-fbc:0.1:IMAGE_URL| |SBOM_BLOB_URL| Reference of SBOM blob digest to enable digest-based verification from provenance| | ### buildah:0.2 task results |name|description|used in params (taskname:taskrefversion:taskparam) @@ -161,14 +154,6 @@ This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/reposito |---|---|---| |IMAGES_PROCESSED| Images processed in the task.| | |TEST_OUTPUT| Tekton task test output.| | -### fbc-related-image-check:0.1 task results -|name|description|used in params (taskname:taskrefversion:taskparam) -|---|---|---| -|TEST_OUTPUT| Tekton task test output.| | -### fbc-validation:0.1 task results -|name|description|used in params (taskname:taskrefversion:taskparam) -|---|---|---| -|TEST_OUTPUT| Tekton task test output.| | ### git-clone:0.1 task results |name|description|used in params (taskname:taskrefversion:taskparam) |---|---|---| @@ -180,42 +165,30 @@ This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/reposito |name|description|used in params (taskname:taskrefversion:taskparam) |---|---|---| |build| Defines if the image in param image-url should be built| | -### inspect-image:0.1 task results +### validate-fbc:0.1 task results |name|description|used in params (taskname:taskrefversion:taskparam) |---|---|---| -|BASE_IMAGE| Base image source image is built from.| fbc-validate:0.1:BASE_IMAGE| -|BASE_IMAGE_REPOSITORY| Base image repository URL.| | +|RELATED_IMAGE_ARTIFACT| The Trusted Artifact URI pointing to the artifact with the related images for the FBC fragment.| | |TEST_OUTPUT| Tekton task test output.| | +|TEST_OUTPUT_ARTIFACT| The Trusted Artifact URI pointing to the artifact with the related images for the FBC fragment.| | ## Workspaces |name|description|optional|used in tasks |---|---|---|---| |git-auth| |True| clone-repository:0.1:basic-auth| |netrc| |True| | -|workspace| |False| show-summary:0.2:workspace ; clone-repository:0.1:output ; build-container:0.2:source ; inspect-image:0.1:source ; fbc-validate:0.1:workspace ; fbc-related-image-check:0.1:workspace| +|workspace| |False| show-summary:0.2:workspace ; clone-repository:0.1:output ; build-container:0.2:source| ## Available workspaces from tasks ### buildah:0.2 task workspaces |name|description|optional|workspace from pipeline |---|---|---|---| |source| Workspace containing the source code to build.| False| workspace| -### fbc-related-image-check:0.1 task workspaces -|name|description|optional|workspace from pipeline -|---|---|---|---| -|workspace| | False| workspace| -### fbc-validation:0.1 task workspaces -|name|description|optional|workspace from pipeline -|---|---|---|---| -|workspace| | False| workspace| ### git-clone:0.1 task workspaces |name|description|optional|workspace from pipeline |---|---|---|---| |basic-auth| A Workspace containing a .gitconfig and .git-credentials file or username and password. These will be copied to the user's home before any git commands are run. Any other files in this Workspace are ignored. It is strongly recommended to use ssh-directory over basic-auth whenever possible and to bind a Secret to this Workspace over other volume types. | True| git-auth| |output| The git repo will be cloned onto the volume backing this Workspace.| False| workspace| |ssh-directory| A .ssh directory with private key, known_hosts, config, etc. Copied to the user's home before git commands are executed. Used to authenticate with the git remote when performing the clone. Binding a Secret to this Workspace is strongly recommended over other volume types. | True| | -### inspect-image:0.1 task workspaces -|name|description|optional|workspace from pipeline -|---|---|---|---| -|source| | False| workspace| ### summary:0.2 task workspaces |name|description|optional|workspace from pipeline |---|---|---|---| diff --git a/pipelines/fbc-builder/patch.yaml b/pipelines/fbc-builder/patch.yaml index 149a0a252..68935df8d 100644 --- a/pipelines/fbc-builder/patch.yaml +++ b/pipelines/fbc-builder/patch.yaml @@ -76,7 +76,7 @@ - op: add path: /spec/tasks/- value: - name: inspect-image + name: validate-fbc when: - input: $(params.skip-checks) operator: in @@ -84,52 +84,10 @@ runAfter: - build-image-index taskRef: - name: inspect-image + name: validate-fbc version: "0.1" params: - name: IMAGE_URL value: $(tasks.build-image-index.results.IMAGE_URL) - name: IMAGE_DIGEST value: $(tasks.build-image-index.results.IMAGE_DIGEST) - workspaces: - - name: source - workspace: workspace -- op: add - path: /spec/tasks/- - value: - name: fbc-validate - when: - - input: $(params.skip-checks) - operator: in - values: ["false"] - runAfter: - - inspect-image - taskRef: - name: fbc-validation - version: "0.1" - params: - - name: IMAGE_URL - value: $(tasks.build-image-index.results.IMAGE_URL) - - name: IMAGE_DIGEST - value: $(tasks.build-image-index.results.IMAGE_DIGEST) - - name: BASE_IMAGE - value: $(tasks.inspect-image.results.BASE_IMAGE) - workspaces: - - name: workspace - workspace: workspace -- op: add - path: /spec/tasks/- - value: - name: fbc-related-image-check - when: - - input: $(params.skip-checks) - operator: in - values: ["false"] - runAfter: - - fbc-validate - taskRef: - name: fbc-related-image-check - version: "0.1" - workspaces: - - name: workspace - workspace: workspace diff --git a/task/fbc-related-image-check/0.1/fbc-related-image-check.yaml b/task/fbc-related-image-check/0.1/fbc-related-image-check.yaml index 7e004b00d..77a4792ad 100644 --- a/task/fbc-related-image-check/0.1/fbc-related-image-check.yaml +++ b/task/fbc-related-image-check/0.1/fbc-related-image-check.yaml @@ -6,6 +6,7 @@ metadata: annotations: tekton.dev/pipelines.minVersion: "0.12.1" tekton.dev/tags: "konflux" + build.appstudio.redhat.com/expires-on: "2024-12-31T00:00:00Z" name: fbc-related-image-check spec: description: >- diff --git a/task/fbc-related-image-check/0.1/kustomization.yaml b/task/fbc-related-image-check/0.1/kustomization.yaml new file mode 100644 index 000000000..f37016832 --- /dev/null +++ b/task/fbc-related-image-check/0.1/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- fbc-related-image-check.yaml diff --git a/task/fbc-related-image-check/0.2/MIGRATION.md b/task/fbc-related-image-check/0.2/MIGRATION.md new file mode 100644 index 000000000..a6eee6a2f --- /dev/null +++ b/task/fbc-related-image-check/0.2/MIGRATION.md @@ -0,0 +1,48 @@ +## Deprecation notice + +This task is deprecated, please remove it from your pipeline. +Deprecation date: 2024-12-31 + +# Migration from 0.1 to 0.2 + +Version 0.2: + +No changes within this version, its only purpose is to provide information on how to remove this task from your pipeline. + +## Action from users + +To remove this task from your pipeline please follow these steps: + +1. Remove the fbc-related-image-check task definition from your FBC pipelines similar to this change: + +```diff +--- a/.tekton/original-pipelinerun.yaml ++++ b/.tekton/new-pipelinerun.yaml +@@ -323,26 +323,6 @@ spec: + workspaces: + - name: workspace + workspace: workspace +- - name: fbc-related-image-check +- runAfter: +- - fbc-validate +- taskRef: +- params: +- - name: name +- value: fbc-related-image-check +- - name: bundle +- value: quay.io/konflux-ci/tekton-catalog/task-fbc-related-image-check:0.1@sha256:0fae84cc832d21c250334ab1d285db92e7e22e916ea342d044e46136c502d2f8 +- - name: kind +- value: task +- resolver: bundles +- when: +- - input: $(params.skip-checks) +- operator: in +- values: +- - "false" +- workspaces: +- - name: workspace +- workspace: workspace + workspaces: + - name: workspace + - name: git-auth +``` diff --git a/task/fbc-related-image-check/0.2/README.md b/task/fbc-related-image-check/0.2/README.md new file mode 100644 index 000000000..b9b54556e --- /dev/null +++ b/task/fbc-related-image-check/0.2/README.md @@ -0,0 +1,18 @@ +# fbc-related-image-check task + +## Description: +The fbc-related-image-check task checks whether all images referenced in file-based catalog (FBC) are valid by using +Skopeo to inspect manifest content. + +## Results: + +| name | description | +|-------------------|---------------------------| +| TEST_OUTPUT | Tekton task test output. | + +## Source repository for image: +https://github.com/konflux-ci/konflux-test + +## Additional links: +https://www.redhat.com/en/topics/containers/what-is-skopeo +https://olm.operatorframework.io/docs/reference/file-based-catalogs/ diff --git a/task/fbc-related-image-check/0.2/kustomization.yaml b/task/fbc-related-image-check/0.2/kustomization.yaml new file mode 100644 index 000000000..d25d213e2 --- /dev/null +++ b/task/fbc-related-image-check/0.2/kustomization.yaml @@ -0,0 +1,15 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ../0.1 + +patches: +- patch: |- + - op: replace + path: /metadata/labels + value: + app.kubernetes.io/version: "0.2" + target: + kind: Task + name: fbc-related-image-check diff --git a/task/fbc-validation/0.1/fbc-validation.yaml b/task/fbc-validation/0.1/fbc-validation.yaml index 815eab7db..9622b14b5 100644 --- a/task/fbc-validation/0.1/fbc-validation.yaml +++ b/task/fbc-validation/0.1/fbc-validation.yaml @@ -6,6 +6,7 @@ metadata: annotations: tekton.dev/pipelines.minVersion: "0.12.1" tekton.dev/tags: "konflux" + build.appstudio.redhat.com/expires-on: "2024-12-31T00:00:00Z" name: fbc-validation spec: description: >- diff --git a/task/fbc-validation/0.1/kustomization.yaml b/task/fbc-validation/0.1/kustomization.yaml new file mode 100644 index 000000000..8acf9b308 --- /dev/null +++ b/task/fbc-validation/0.1/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- fbc-validation.yaml diff --git a/task/fbc-validation/0.2/MIGRATION.md b/task/fbc-validation/0.2/MIGRATION.md new file mode 100644 index 000000000..81de96b97 --- /dev/null +++ b/task/fbc-validation/0.2/MIGRATION.md @@ -0,0 +1,51 @@ +## Deprecation notice + +This task is deprecated, please remove it from your pipeline and replace it with the new validate-fbc task. +Deprecation date: 2024-12-31 + +# Migration from 0.1 to 0.2 + +Version 0.2: + +No changes within this version, its only purpose is to provide information on how to remove this task from your pipeline. + +## Action from users + +To remove this task from your pipeline please follow these steps: + +1. Remove the fbc-validation task definition from your FBC pipelines similar to this change: + +```diff +--- a/.tekton/original-pipelinerun.yaml ++++ b/.tekton/new-pipelinerun.yaml +@@ -323,26 +323,6 @@ spec: + workspaces: + - name: workspace + workspace: workspace +- - name: fbc-validation ++ - name: validate-fbc +- runAfter: +- - inspect-image ++ - build-image-index + taskRef: + params: + - name: name +- value: fbc-validation ++ value: validate-fbc +- - name: bundle +- value: quay.io/konflux-ci/tekton-catalog/task-validate-fbc:0.1 + - name: kind + value: task + resolver: bundles + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" +- workspaces: +- - name: workspace +- workspace: workspace + workspaces: + - name: workspace + - name: git-auth +``` diff --git a/task/fbc-validation/0.2/README.md b/task/fbc-validation/0.2/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/task/fbc-validation/0.2/kustomization.yaml b/task/fbc-validation/0.2/kustomization.yaml new file mode 100644 index 000000000..6b668d0da --- /dev/null +++ b/task/fbc-validation/0.2/kustomization.yaml @@ -0,0 +1,15 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ../0.1 + +patches: +- patch: |- + - op: replace + path: /metadata/labels + value: + app.kubernetes.io/version: "0.2" + target: + kind: Task + name: fbc-validation diff --git a/task/inspect-image/0.1/inspect-image.yaml b/task/inspect-image/0.1/inspect-image.yaml index 923fc51c2..56e49fd81 100644 --- a/task/inspect-image/0.1/inspect-image.yaml +++ b/task/inspect-image/0.1/inspect-image.yaml @@ -5,6 +5,7 @@ metadata: labels: app.kubernetes.io/version: "0.1" annotations: + build.appstudio.redhat.com/expires-on: "2024-12-31T00:00:00Z" tekton.dev/pipelines.minVersion: "0.12.1" tekton.dev/tags: "konflux" name: inspect-image diff --git a/task/inspect-image/0.1/kustomization.yaml b/task/inspect-image/0.1/kustomization.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/task/inspect-image/0.2/MIGRATION.md b/task/inspect-image/0.2/MIGRATION.md new file mode 100644 index 000000000..3825423d4 --- /dev/null +++ b/task/inspect-image/0.2/MIGRATION.md @@ -0,0 +1,65 @@ +## Deprecation notice + +This task is deprecated, please remove it from your pipeline. +Deprecation date: 2024-12-31 + +# Migration from 0.1 to 0.2 + +Version 0.2: + +No changes within this version, its only purpose is to provide information on how to remove this task from your pipeline. + +## Action from users + +To remove this task from your pipeline please follow these steps: + +1. Remove the inspect-image task definition from your FBC pipelines similar to this change: + +```diff +--- a/.tekton/original-pipelinerun.yaml ++++ b/.tekton/new-pipelinerun.yaml +@@ -271,31 +271,6 @@ spec: + - name: kind + value: task + resolver: bundles +- - name: inspect-image +- params: +- - name: IMAGE_URL +- value: $(tasks.build-image-index.results.IMAGE_URL) +- - name: IMAGE_DIGEST +- value: $(tasks.build-image-index.results.IMAGE_DIGEST) +- runAfter: +- - build-image-index +- taskRef: +- params: +- - name: name +- value: inspect-image +- - name: bundle +- value: quay.io/konflux-ci/tekton-catalog/task-inspect-image:0.1@sha256:c8d7616fba1533637547eccd598314721a106ec0d108dcb5162e234d5d90c755 +- - name: kind +- value: task +- resolver: bundles +- when: +- - input: $(params.skip-checks) +- operator: in +- values: +- - "false" +- workspaces: +- - name: source +- workspace: workspace + - name: fbc-validate + params: + - name: IMAGE_URL +@@ -302,10 +302,8 @@ spec: + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) +- - name: BASE_IMAGE +- value: $(tasks.inspect-image.results.BASE_IMAGE) + runAfter: +- - inspect-image ++ - build-image-index + taskRef: + params: + - name: name +``` diff --git a/task/inspect-image/0.2/README.md b/task/inspect-image/0.2/README.md new file mode 100644 index 000000000..bd2149141 --- /dev/null +++ b/task/inspect-image/0.2/README.md @@ -0,0 +1,28 @@ +# inspect-image task + +## Description: +The inspect-image task uses Skopeo to inspect and analyze manifest data from the target source image of a +container if it is built from scratch. If the target image has a direct base image, the task will also use Skopeo to inspect +that base image. + +## Params: + +| name | description | +|--------------|-------------------------------------------------| +| IMAGE_URL | Fully qualified image name. | +| IMAGE_DIGEST | Image digest. | +| DOCKER_AUTH | unused, should be removed in next task version. | + +## Results: + +| name | description | +|-----------------------|----------------------------------------| +| BASE_IMAGE | Base image source image is built from. | +| BASE_IMAGE_REPOSITORY | Base image repository URL. | +| TEST_OUTPUT | Tekton task test output. | + +## Source repository for image: +https://github.com/konflux-ci/konflux-test + +## Additional links: +https://www.redhat.com/en/topics/containers/what-is-skopeo diff --git a/task/inspect-image/0.2/kustomization.yaml b/task/inspect-image/0.2/kustomization.yaml new file mode 100644 index 000000000..f3fc1a7c1 --- /dev/null +++ b/task/inspect-image/0.2/kustomization.yaml @@ -0,0 +1,15 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ../0.1 + +patches: +- patch: |- + - op: replace + path: /metadata/labels + value: + app.kubernetes.io/version: "0.2" + target: + kind: Task + name: inspect-image diff --git a/task/validate-fbc/0.1/README.md b/task/validate-fbc/0.1/README.md new file mode 100644 index 000000000..a8069d47c --- /dev/null +++ b/task/validate-fbc/0.1/README.md @@ -0,0 +1,29 @@ +# validate-fbc task + +## Description: +Ensures file-based catalog (FBC) components are uniquely linted for proper construction as part of build pipeline. + +For further information on how to use the task, see the USAGE.md file. + +For troubleshooting assistance, see the TROUBLESHOOTING.md file. + +## Params: + +| name | description | +|--------------|----------------------------------| +| IMAGE_DIGEST | Image digest. | +| IMAGE_URL | Fully qualified image name. | + +## Results: + +| name | description | +|--------------------|---------------------------| +| TEST_OUTPUT | Tekton task test output. | + +## Source repository for image: +https://github.com/konflux-ci/konflux-test + +## Additional links: +https://olm.operatorframework.io/docs/reference/file-based-catalogs/ +https://github.com/containers/skopeo +https://docs.openshift.com/container-platform/4.12/cli_reference/opm/cli-opm-install.html \ No newline at end of file diff --git a/task/validate-fbc/0.1/TROUBLESHOOTING.md b/task/validate-fbc/0.1/TROUBLESHOOTING.md new file mode 100644 index 000000000..72674b4ea --- /dev/null +++ b/task/validate-fbc/0.1/TROUBLESHOOTING.md @@ -0,0 +1,21 @@ + +## Bundle properties are not permitted in a FBC fragment for OCP version + +Tasks may fail with an error message containing the string `bundle properties are not permitted in a FBC fragment for OCP version`. This means that your fragment needs to utilize the appropriate FBC bundle metadata format which aligns with your target catalog. Failure to do so will result in your package not being displayed in the OpenShift Console. + +For OCP versions: +- _4.16 or earlier_, bundle metadata must use the `olm.bundle.object` format +- _4.17 or later_, bundle metadata must use the `olm.csv.metadata` format + +### If you use `opm` tooling to generate your fragment + +Note: This assumes that opm is version v1.46.0 or later. + +If you generate your FBC using catalog template expansion or migration of existing catalogs, then by default, the tool will output `olm.bundle.object` metadata format. +You can choose to produce `olm.csv.metadata` format by using the `--migrate-level=bundle-object-to-csv-metadata` flag. + +### If you use other tooling to generate your fragment + +Bundle data in `olm.csv.metadata` format contains only information that the OpenShift Console needs which is derived from the package's Cluster Standard Version(CSV). Since the previous `olm.bundle.object` format would include bundle CSV metadata as well as other properties it is possible to convert from `olm.bundle.object` to `olm.csv.metadata`, but not the reverse. + +If you rely on other tooling/processes to produce your fragment and currently use the `olm.bundle.object` bundle metadata format, then you may either adjust your tooling to generate `olm.csv.metadata` format or you may use `opm` to migrate your fragment's bundle metadata by using `opm render --migrate-level=bundle-object-to-csv-metadata [fragment-ref]` (where `fragment-ref` is a pullspec to the fragment or a path to a directory containing the fragment). \ No newline at end of file diff --git a/task/validate-fbc/0.1/USAGE.md b/task/validate-fbc/0.1/USAGE.md new file mode 100644 index 000000000..1a806b5e9 --- /dev/null +++ b/task/validate-fbc/0.1/USAGE.md @@ -0,0 +1,29 @@ +# validate-fbc task + +## Checks +### Valid base image +To validate the image in build pipeline, Skopeo is used to extract +information from the image itself and then contents are checked using the OpenShift Operator Framework. The binary +used to run the validation is extracted from the base image for the component being tested. Because of this, the +base image must come from a trusted source. Trusted sources are declared in `ALLOWED_BASE_IMAGES` in fbc-validation.yaml. + +### Valid FBC schema +To validate the schema format of the FBC fragment, the test +1. validates that the `operators.operatoframework.io.index.configs.v1` label is present on the image to identify the fragment path +2. extracts the `opm` binary from the base image for the fragment +3. executes `opm validate` over the fragment + +### At least one package in fragment +To validate that at least one package is included in the fragment, the test renders the FBC using `opm` and uses `jq` to count instances of `olm.package` and fails if there are none. + +### Bundle metadata in the appropriate format +To validate bundle metadata, the test evaluates bundle metadata usage against the target OCP version: +- for 4.16 and earlier, fragments must use `olm.bundle.object` (and not use `olm.csv.metadata`) +- for 4.17 and later, fragments must use `olm.csv.metadata` (and not use `olm.bundle.object`) + +## Data output +### Related images + +OPM will be used to render the catalog in order to identify the set of related images for the fragment. +These images will then be saved as an output artifact so that EC can verify that the pullspecs are valid +before releasing the fragment. \ No newline at end of file diff --git a/task/validate-fbc/0.1/validate-fbc.yaml b/task/validate-fbc/0.1/validate-fbc.yaml new file mode 100644 index 000000000..1ca42fa9e --- /dev/null +++ b/task/validate-fbc/0.1/validate-fbc.yaml @@ -0,0 +1,462 @@ +# TODO: +# make this task multi-arch aware. +# make this task fail if a bundle is an image index reference +# change the related-image check to be done in EC by exporting the set of related images +apiVersion: tekton.dev/v1 +kind: Task +metadata: + labels: + app.kubernetes.io/version: "0.1" + annotations: + tekton.dev/pipelines.minVersion: "0.12.1" + tekton.dev/tags: "konflux" + name: validate-fbc +spec: + description: >- + Ensures file-based catalog (FBC) components are uniquely linted for proper construction as part of build pipeline. + The manifest data of container images is checked using OpenShift Operator Framework's opm CLI tool. + The opm binary is extracted from the container's base image, which must come from a trusted source. + params: + - name: IMAGE_URL + description: Fully qualified image name. + - name: IMAGE_DIGEST + description: Image digest. + results: + - name: RELATED_IMAGE_ARTIFACT + description: The Trusted Artifact URI pointing to the artifact with + the related images for the FBC fragment. + - name: TEST_OUTPUT_ARTIFACT + description: The Trusted Artifact URI pointing to the artifact with + the related images for the FBC fragment. + - name: TEST_OUTPUT + description: Tekton task test output. + volumes: + - name: shared + emptyDir: {} + - name: workdir + emptyDir: {} + stepTemplate: + env: + - name: IMAGE_URL + value: $(params.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(params.IMAGE_DIGEST) + volumeMounts: + - mountPath: /shared + name: shared + - mountPath: /var/workdir + name: workdir + steps: + - name: inspect-image + image: quay.io/redhat-appstudio/konflux-test:v1.4.7@sha256:cf6808a3bd605630a5d9f20595ff7c43f8645c00381219d32f5a11e88fe37072 + # per https://kubernetes.io/docs/concepts/containers/images/#imagepullpolicy-defaulting + # the cluster will set imagePullPolicy to IfNotPresent + workingDir: /var/workdir/inspect-image + securityContext: + runAsUser: 0 + capabilities: + add: + - SETFCAP + script: | + #!/usr/bin/env bash + set -euo pipefail + # shellcheck source=/dev/null + source /utils.sh + trap 'handle_error "$(results.TEST_OUTPUT.path)"' EXIT + + IMAGE_INSPECT=image_inspect.json + BASE_IMAGE_INSPECT=base_image_inspect.json + RAW_IMAGE_INSPECT=raw_image_inspect.json + + IMAGE_URL="${IMAGE_URL}@${IMAGE_DIGEST}" + # Given a tag and a the digest in the IMAGE_URL we opt to use the digest alone + # this is because containers/image currently doesn't support image references + # that contain both. See https://github.com/containers/image/issues/1736 + if [[ "${IMAGE_URL}" == *":"*"@"* ]]; then + IMAGE_URL="${IMAGE_URL/:*@/@}" + fi + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec # skip last sleep + echo "Inspecting manifest for source image ${IMAGE_URL} (try $run/$max_run)." + skopeo inspect --no-tags docker://"${IMAGE_URL}" > $IMAGE_INSPECT && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to inspect image ${IMAGE_URL}" + note="Step inspect-image failed: Encountered errors while inspecting image. For details, check Tekton task log." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + echo "Image ${IMAGE_URL} metadata:" + cat "$IMAGE_INSPECT" + + run=1 + while [ "$run" -le "$max_run" ]; do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec # skip last sleep + echo "Inspecting raw image manifest ${IMAGE_URL} (try $run/$max_run)." + skopeo inspect --no-tags --raw docker://"${IMAGE_URL}" > $RAW_IMAGE_INSPECT || status=$? + + if [ "$status" -eq 0 ] && [ "$(jq 'has("manifests")' ${RAW_IMAGE_INSPECT})" = "true" ]; then + echo "Found an image index, lookup for amd64 manifest" + INDEX_IMAGE_MANIFESTS=$(jq ' .manifests | map ( {(.platform.architecture|tostring|ascii_downcase): .digest} ) | add' "${RAW_IMAGE_INSPECT}" || true) + + AMD64_MANIFEST_DIGEST=$(jq -r '.amd64' <<< "${INDEX_IMAGE_MANIFESTS}" || true ) + if [ -z "$AMD64_MANIFEST_DIGEST" ]; then + # we didn't find amd64 platform, fail horribly as it's the required platform currently for all checks + echo "[ERROR] Could not find amd64 image manifest for image $IMAGE_URL" + note="Step inspect-image failed: Couldn't find amd64 image manifest" + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + # Replace image URL with new digest + IMAGE_URL="${IMAGE_URL/[@:]*/@$AMD64_MANIFEST_DIGEST}" + echo "Setting AMD64 specific image: $IMAGE_URL" + run=1 # reset runs, we are looking another image; new image, new life + else + break + fi + done + + if [ "$status" -ne 0 ]; then + echo "Failed to get raw metadata of image ${IMAGE_URL}" + note="Step inspect-image failed: Encountered errors while inspecting image. For details, check Tekton task log." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + echo "Image ${IMAGE_URL} raw metadata:" + jq < "$RAW_IMAGE_INSPECT" # jq for readable formatting + + echo "Getting base image manifest for source image ${IMAGE_URL}." + BASE_IMAGE_NAME="$(jq -r ".annotations.\"org.opencontainers.image.base.name\"" $RAW_IMAGE_INSPECT)" + BASE_IMAGE_DIGEST="$(jq -r ".annotations.\"org.opencontainers.image.base.digest\"" $RAW_IMAGE_INSPECT)" + if [ "$BASE_IMAGE_NAME" == 'null' ]; then + echo "Cannot get base image info from annotations." + BASE_IMAGE_NAME="$(jq -r ".Labels.\"org.opencontainers.image.base.name\"" $IMAGE_INSPECT)" + BASE_IMAGE_DIGEST="$(jq -r ".annotations.\"org.opencontainers.image.base.digest\"" $IMAGE_INSPECT)" + if [ "$BASE_IMAGE_NAME" == 'null' ]; then + echo "Cannot get base image info from Labels. For details, check source image ${IMAGE_URL}." + exit 0 + fi + fi + if [ -z "$BASE_IMAGE_NAME" ]; then + echo "Source image ${IMAGE_URL} is built from scratch, so there is no base image." + exit 0 + fi + + BASE_IMAGE="${BASE_IMAGE_NAME%:*}@$BASE_IMAGE_DIGEST" + echo "Detected base image: $BASE_IMAGE" + echo -n "$BASE_IMAGE" > /shared/BASE_IMAGE + + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec # skip last sleep + echo "Inspecting base image ${BASE_IMAGE} (try $run/$max_run)." + skopeo inspect --no-tags "docker://$BASE_IMAGE" > $BASE_IMAGE_INSPECT && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to inspect base image ${BASE_IMAGE}" + note="Step inspect-image failed: Encountered errors while inspecting image. For details, check Tekton task log." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + BASE_IMAGE_REPOSITORY="$(jq -r '.Name | sub("[^/]+/"; "") | sub("[:@].*"; "")' "$BASE_IMAGE_INSPECT")" + echo "Detected base image repository: $BASE_IMAGE_REPOSITORY" + echo -n "$BASE_IMAGE_REPOSITORY" > /shared/BASE_IMAGE_REPOSITORY + + note="Step inspect-image completed: Check inspected JSON files under /var/workdir/inspect-image." + - name: extract-and-validate + image: quay.io/redhat-appstudio/konflux-test:v1.4.5@sha256:801a105ba0f9c7f58f5ba5cde1a3b4404009fbebb1028779ca2c5de211e94940 + # per https://kubernetes.io/docs/concepts/containers/images/#imagepullpolicy-defaulting + # the cluster will set imagePullPolicy to IfNotPresent + workingDir: /var/workdir/extract-and-validate + securityContext: + runAsUser: 0 + capabilities: + add: + - SETFCAP + computeResources: + limits: + memory: 4Gi + requests: + memory: 512Mi + cpu: 10m + script: | + #!/usr/bin/env bash + set -euo pipefail + source /utils.sh + trap 'handle_error "$(results.TEST_OUTPUT.path)"' EXIT + + BASE_IMAGE=$(cat /shared/BASE_IMAGE) + + declare -a ALLOWED_BASE_IMAGES=( + "registry.redhat.io/openshift4/ose-operator-registry" + "registry.redhat.io/openshift4/ose-operator-registry-rhel9" + "brew.registry.redhat.io/rh-osbs/openshift-ose-operator-registry-rhel9" + ) + + ### FBC base image check + if [ -z "${BASE_IMAGE}" ]; then + echo "Base image is unknown. The file-based catalog must have base image defined. Check inspect-image task log." + note="Step extract-and-validate failed: The file-based catalog must have base image defined. For details, check Tekton task result TEST_OUTPUT in task inspect-image." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + IMAGE_WITHOUT_TAG=$(echo "${BASE_IMAGE}" | sed "s/:.*$//" | sed "s/@.*$//") + + allowed=false + for value in "${ALLOWED_BASE_IMAGES[@]}" + do + if [[ "${IMAGE_WITHOUT_TAG}" == "${value}" ]]; then + allowed=true + break + fi + done + + if [[ "${allowed}" == false ]]; then + echo "Base image ${BASE_IMAGE} is not allowed for the file based catalog image. Allowed images: ${ALLOWED_BASE_IMAGES}" + note="Step extract-and-validate failed: Base image ${BASE_IMAGE} is not allowed for the file based catalog image. For details, check Tekton task logs" + TEST_OUTPUT=$(make_result_json -r FAILURE -f 1 -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + ### Try to extract binaries with configs > check binaries functionality > check opm validate ### + if [ ! -s ../inspect-image/image_inspect.json ]; then + echo "File /var/workdir/inspect-image/image_inspect.json did not generate correctly. Check inspect-image task log." + note="Step extract-and-validate failed: /var/workdir/inspect-image/image_inspect.json did not generate correctly. For details, check Tekton task result TEST_OUTPUT in task inspect-image." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + if [ ! -s ../inspect-image/raw_image_inspect.json ]; then + echo "File /var/workdir/inspect-image/raw_image_inspect.json did not generate correctly. Check inspect-image task log." + note="Step extract-and-validate failed: /var/workdir/inspect-image/raw_image_inspect.json did not generate correctly. For details, check Tekton task result TEST_OUTPUT in task inspect-image." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + echo "Getting base image for source image ${IMAGE_URL}." + base_image_name="$(jq -r ".annotations.\"org.opencontainers.image.base.name\"" ../inspect-image/raw_image_inspect.json)" || status=$? + if [ "$base_image_name" == 'null' ]; then + echo "Could not get annotations from inspect-image/raw_image_inspect.json. Make sure file exists and it contains this annotation: org.opencontainers.image.base.name" + echo "Try to get base image from label..." + base_image_name="$(jq -r ".Labels.\"org.opencontainers.image.base.name\"" ../inspect-image/image_inspect.json)" || status=$? + if [ "$base_image_name" == 'null' ]; then + echo "Cannot get base image info from Labels. For details, check source image ../inspect-image/image_inspect.json." + TEST_OUTPUT="$(make_result_json -r ERROR)" + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + fi + if [ -z "$base_image_name" ]; then + echo "Source image ${IMAGE_URL} is built from scratch, so there is no base image." + TEST_OUTPUT="$(make_result_json -r ERROR)" + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + status=0 + conffolder=$(jq -r '.Labels ."operators.operatorframework.io.index.configs.v1"' ../inspect-image/image_inspect.json) || status=$? + if [ $status -ne 0 ]; then + echo "Could not get labels from inspect-image/image_inspect.json. Make sure file exists and it contains this label: operators.operatorframework.io.index.configs.v1." + TEST_OUTPUT="$(make_result_json -r ERROR)" + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + mkdir -p /tmp/image-content confdir + pushd /tmp/image-content + image_with_digest="${IMAGE_URL}@${IMAGE_DIGEST}" + + if ! oc image extract --registry-config ~/.docker/config.json "${image_with_digest}" ; then + echo "Unable to extract or validate extracted binaries." + note="Step extract-and-validate failed: Failed to extract image with oc extract command, so it cannot validate extracted binaries. For details, check Tekton task log." + ERROR_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + popd + exit 0 + fi + + if [ -z "$(ls -A .$conffolder)" ]; then + echo "$conffolder is missing catalog file." + TEST_OUTPUT="$(make_result_json -r ERROR)" + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + popd + exit 0 + fi + + EXTRACT_DIR="/extracted_base_img" + mkdir "${EXTRACT_DIR}" + if ! oc image extract ${BASE_IMAGE} --path /:"${EXTRACT_DIR}"; then + echo "Unable to extract opm binary" + note="Step extract-and-validate failed: Failed to extract base image with oc extract command, so it cannot validate extracted binaries. For details, check Tekton task log." + ERROR_OUTPUT=$(make_result_json -r ERROR -t "$note") + exit 0 + fi + + OPM_BINARIES="$(find "${EXTRACT_DIR}" -type f -name opm)" + BINARIES_COUNT=$(wc -l <<< "${OPM_BINARIES}") + if [[ $BINARIES_COUNT -ne "1" ]]; then + note="Step extract-and-validate failed: Expected exactly one opm binary in base image. For details, check Tekton task log" + ERROR_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${ERROR_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + echo "found $BINARIES_COUNT opm binaries:" + echo "${OPM_BINARIES}" + exit 0 + fi + OPM_BINARY=$(echo "${OPM_BINARIES}" | head -n 1) + echo "OPM_BINARY: '${OPM_BINARY}'" + chmod 775 "$OPM_BINARY" + + # We have 9 total checks + check_num=9 + failure_num=0 + TESTPASSED=true + + if [[ ! $(find . -name "grpc_health_probe") ]]; then + echo "!FAILURE! - grpc_health_probe binary presence check failed." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + + if ! ${OPM_BINARY} validate ."${conffolder}"; then + echo "!FAILURE! - opm validate check failed." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + + OPM_RENDERED_CATALOG=/tmp/catalog.json + ${OPM_BINARY} render ."${conffolder}" > ${OPM_RENDERED_CATALOG} + if [ ! -f ${OPM_RENDERED_CATALOG} ]; then + echo "!FAILURE! - unable to render the fragment FBC." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + + if jq -en 'reduce (inputs | select(.schema == "olm.package")) as $obj (0; .+1) < 1' ${OPM_RENDERED_CATALOG}; then + echo "!FAILURE! - There are no olm package entries defined in this FBC fragment." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + + # examines the base_image_name tag to derive the target OCP version + # assumes this is in the form + # image-path:[v]major-digits.minor-digits[@sha...] + OCP_VER_FROM_BASE=$(echo "${base_image_name}" | sed -e "s/@.*$//" -e "s/^.*://") # strips hash first due to greedy match + # extracts major digits and filters out any leading alphabetic characters, for e.g. 'v4' --> '4' + OCP_VER_MAJOR=$(echo "${OCP_VER_FROM_BASE}" | cut -d '.' -f 1 | sed "s/^[a-zA-Z]*//") + OCP_VER_MINOR=$(echo "${OCP_VER_FROM_BASE}" | cut -d '.' -f 2) + + RUN_OCP_VERSION_VALIDATION="false" + digits_regex='^[0-9]*$' + if [[ ${OCP_VER_MAJOR} =~ $digits_regex ]] && [[ ${OCP_VER_MINOR} =~ $digits_regex ]] ; then + RUN_OCP_VERSION_VALIDATION="true" + fi + + if [ "${RUN_OCP_VERSION_VALIDATION}" == "false" ] ; then + echo "!WARNING! - unable to assess bundle metadata alignment with OCP version because we cannot extract version info from base_image_name: ${base_image_name}" + else + OCP_BUNDLE_METADATA_THRESHOLD_MAJOR=4 + OCP_BUNDLE_METADATA_THRESHOLD_MINOR=17 + OCP_BUNDLE_METADATA_FORMAT="olm.bundle.object" + + if [[ "${OCP_VER_MAJOR}" -ge "${OCP_BUNDLE_METADATA_THRESHOLD_MAJOR}" ]] && [[ "${OCP_VER_MINOR}" -ge "${OCP_BUNDLE_METADATA_THRESHOLD_MINOR}" ]]; then + OCP_BUNDLE_METADATA_FORMAT="olm.csv.metadata" + fi + + # enforce the presence of either olm.csv.metadata or olm.bundle.object based on OCP version + if [[ "${OCP_BUNDLE_METADATA_FORMAT}" = "olm.csv.metadata" ]]; then + if ! jq -en 'reduce( inputs | select(.schema == "olm.bundle" and .properties[].type == "olm.bundle.object")) as $_ (0;.+1) == 0' ${OPM_RENDERED_CATALOG}; then + echo "!FAILURE! - olm.bundle.object bundle properties are not permitted in a FBC fragment for OCP version ${OCP_VER_MAJOR}.${OCP_VER_MINOR}. Fragments must move to olm.csv.metadata bundle metadata." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + else + if ! jq -en 'reduce( inputs | select(.schema == "olm.bundle" and .properties[].type == "olm.csv.metadata")) as $_ (0;.+1) == 0' ${OPM_RENDERED_CATALOG}; then + echo "!FAILURE! - olm.csv.metadata bundle properties are not permitted in a FBC fragment for OCP version ${OCP_VER_MAJOR}.${OCP_VER_MINOR}. Fragments must only use olm.bundle.object bundle metadata." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + fi + + # enforce that each bundle has the OCP-version-appropriate bundle metadata. + BUNDLE_COUNT=$(jq -en 'def count(stream): reduce stream as $i (0; .+1); count(inputs|select(.schema=="olm.bundle"))' ${OPM_RENDERED_CATALOG}) + BUNDLE_BO_COUNT=$(jq -en 'def count(stream): reduce stream as $i (0; .+1); count(inputs|select(.schema == "olm.bundle" and .properties[].type == "olm.bundle.object"))' ${OPM_RENDERED_CATALOG}) + BUNDLE_CM_COUNT=$(jq -en 'def count(stream): reduce stream as $i (0; .+1); count(inputs|select(.schema == "olm.bundle" and .properties[].type == "olm.csv.metadata"))' ${OPM_RENDERED_CATALOG}) + + if [[ "${OCP_BUNDLE_METADATA_FORMAT}" = "olm.csv.metadata" ]]; then + if [[ "${BUNDLE_COUNT}" -ne "${BUNDLE_CM_COUNT}" ]]; then + echo "!FAILURE! - every olm.bundle object in the fragment must have a corresponding olm.csv.metadata bundle property" + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + else + if [[ "${BUNDLE_BO_COUNT}" -lt "${BUNDLE_COUNT}" ]]; then + echo "!FAILURE! - every olm.bundle object in the fragment must have at least one olm.bundle.object bundle property" + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + fi + fi + + FAILEDIMAGES="" + catalog="$(opm render ".$conffolder/")" + + # OPM generates catalog file in a way that yaml file could contain stream of JSON objects + # thats why we need jq in for this situation, because yq can't parse this file + # however there is also possibility that catalog.yaml has yaml data in it + + status=0 + echo "Related images detected:" + # We need to see if the images exist first then we can slurp them to format properly + jq '.relatedImages[]? | .image ' <<< "${catalog}" || status=$? + if [ $status -ne 0 ]; then + echo "!FAILURE! - Could not get related images. Make sure catalog.yaml exists in FBC fragment image and it is valid .yaml or .json format." + note="Task $(context.task.name) failed: Could not fetch related images. Make sure you have catalog.yaml or catalog.json formatted correctly in your file-based catalog (FBC) fragment image." + failure_num=$((failure_num + 1)) + TESTPASSED=false + else + jq '.relatedImages[]? | .image ' <<< "${catalog}" | jq --slurp > /shared/related-images.json + fi + + echo -e "These are related images:\n$(cat /shared/related-images.json)." + # cycle through those related images and show outputs + # for i in $(cat /shared/related-images.json) + while IFS= read -r image + do + if ! skopeo inspect --no-tags "docker://${image}"; then + echo "Skopeo inspect failed on related image: $image." + FAILEDIMAGES+="$image, " + fi + done < /shared/related-images.json + if [ -n "$FAILEDIMAGES" ]; then + echo "These images failed inspection: $FAILEDIMAGES." + note="Task $(context.task.name) failed: Command skopeo inspect could not inspect images. For details, check Tekton task log." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + + note="Step extract-and-validate completed: Check result for task result." + if [ $TESTPASSED == false ]; then + ERROR_OUTPUT=$(make_result_json -r FAILURE -f $failure_num -s $((check_num - failure_num)) -t "$note") + echo "${ERROR_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + else + TEST_OUTPUT=$(make_result_json -r SUCCESS -s $check_num -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + fi + popd diff --git a/task/validate-fbc/OWNERS b/task/validate-fbc/OWNERS new file mode 100644 index 000000000..5b9e03d96 --- /dev/null +++ b/task/validate-fbc/OWNERS @@ -0,0 +1,5 @@ +# See the OWNERS docs: https://go.k8s.io/owners +approvers: + - integration-team +reviewers: + - integration-team \ No newline at end of file