Repository: redhat-openshift-ecosystem/openshift-preflight
Pull request #1046 (2023-08-07 23:01:11)

Bump github.com/operator-framework/api from 0.17.6 to 0.17.7
Bumps [github.com/operator-framework/api](https://github.com/operator-framework/api) from 0.17.6 to 0.17.7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/operator-framework/api/releases">github.com/operator-framework/api's releases</a>.</em></p>
<blockquote>
<h2>v0.17.7</h2>
<h2>What's Changed</h2>
<ul>
<li>updating dependencies by <a href="https://github.com/acornett21"><code>@​acornett21</code></a> in <a href="https://redirect.github.com/operator-framework/api/pull/284">operator-framework/api#284</a></li>
<li>Adds codecov integration by <a href="https://github.com/m1kola"><code>@​m1kola</code></a> in <a href="https://redirect.github.com/operator-framework/api/pull/285">operator-framework/api#285</a></li>
<li>Fix min kube version validation by <a href="https://github.com/kutluhanmetin"><code>@​kutluhanmetin</code></a> in <a href="https://redirect.github.com/operator-framework/api/pull/286">operator-framework/api#286</a></li>
<li>Makes codecov-action optional by <a href="https://github.com/m1kola"><code>@​m1kola</code></a> in <a href="https://redirect.github.com/operator-framework/api/pull/287">operator-framework/api#287</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/acornett21"><code>@​acornett21</code></a> made their first contribution in <a href="https://redirect.github.com/operator-framework/api/pull/284">operator-framework/api#284</a></li>
<li><a href="https://github.com/kutluhanmetin"><code>@​kutluhanmetin</code></a> made their first contribution in <a href="https://redirect.github.com/operator-framework/api/pull/286">operator-framework/api#286</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/operator-framework/api/compare/v0.17.6...v0.17.7">https://github.com/operator-framework/api/compare/v0.17.6...v0.17.7</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/operator-framework/api/commit/92e43415eb8799b2733cc2a98e667e0e7e8d39b8"><code>92e4341</code></a> Makes codecov-action optional</li>
<li><a href="https://github.com/operator-framework/api/commit/fdfcb35e6d330fca94841b113c8140cf58930e35"><code>fdfcb35</code></a> Fix min kube version validation (<a href="https://redirect.github.com/operator-framework/api/issues/286">#286</a>)</li>
<li><a href="https://github.com/operator-framework/api/commit/bbac5028af81cc0cb4604f4a4b2283d225828cbe"><code>bbac502</code></a> Adds codecov integration (<a href="https://redirect.github.com/operator-framework/api/issues/285">#285</a>)</li>
<li><a href="https://github.com/operator-framework/api/commit/aa3e49803e7bc8fa723077988abad399159abb22"><code>aa3e498</code></a> updating dependencies (<a href="https://redirect.github.com/operator-framework/api/issues/284">#284</a>)</li>
<li>See full diff in <a href="https://github.com/operator-framework/api/compare/v0.17.6...v0.17.7">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/operator-framework/api&package-manager=go_modules&previous-version=0.17.6&new-version=0.17.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

openshift-ci[bot]: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/1046#" title="Author self-approved">dependabot[bot]</a>*
**Once this PR has been reviewed and has the lgtm label**, please assign [bcrochet](https://github.com/bcrochet) for approval. For more information see [the Kubernetes Code Review Process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process).

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=redhat-openshift-ecosystem%2Fopenshift-preflight).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/redhat-openshift-ecosystem/openshift-preflight/blob/main/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["bcrochet"]} -->
openshift-ci[bot]: Hi @dependabot[bot]. Thanks for your PR.

I'm waiting for a [redhat-openshift-ecosystem](https://github.com/orgs/redhat-openshift-ecosystem/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://github.com/orgs/redhat-openshift-ecosystem/people) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=redhat-openshift-ecosystem%2Fopenshift-preflight).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

dcibot: - SUCCESS https://www.distributed-ci.io/jobs/14e1a252-718f-4c71-b45c-65072768791d/jobStates
 from https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/1046
bcrochet: /ok-to-test
openshift-ci[bot]: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/1046#pullrequestreview-1569874257" title="Approved">acornett21</a>*, *<a href="https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/1046#" title="Author self-approved">dependabot[bot]</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=redhat-openshift-ecosystem%2Fopenshift-preflight).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/redhat-openshift-ecosystem/openshift-preflight/blob/main/OWNERS)~~ [acornett21]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->

Patch:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 7b80839..ce5ea38 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -6,7 +6,13 @@ updates:
     directory: "/"
     schedule:
       interval: "weekly"
+    groups:
+      dev-dependencies:
+        dependency-type: "development"
+      prod-dependencies:
+        dependency-type: "production"
   - package-ecosystem: github-actions
-    directory: /
+    directory: "/"
     schedule:
-      interval: weekly
+      interval: "weekly"
+
diff --git a/cmd/preflight/cmd/check_container.go b/cmd/preflight/cmd/check_container.go
index e13d4d3..7d42117 100644
--- a/cmd/preflight/cmd/check_container.go
+++ b/cmd/preflight/cmd/check_container.go
@@ -18,11 +18,16 @@ import (
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/cli"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/formatters"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/lib"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/log"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/option"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/runtime"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/viper"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/version"
 
 	"github.com/go-logr/logr"
+	"github.com/google/go-containerregistry/pkg/crane"
+	"github.com/google/go-containerregistry/pkg/name"
+	"github.com/google/go-containerregistry/pkg/v1/remote"
 	"github.com/spf13/cobra"
 	"github.com/spf13/pflag"
 )
@@ -80,8 +85,8 @@ func checkContainerCmd(runpreflight runPreflight) *cobra.Command {
 		"URL paramater. This value may differ from the PID on the overview page. (env: PFLT_CERTIFICATION_PROJECT_ID)"))
 	_ = viper.BindPFlag("certification_project_id", flags.Lookup("certification-project-id"))
 
-	checkContainerCmd.Flags().String("platform", rt.GOARCH, "Architecture of image to pull. Defaults to current platform.")
-	_ = viper.BindPFlag("platform", checkContainerCmd.Flags().Lookup("platform"))
+	flags.String("platform", rt.GOARCH, "Architecture of image to pull. Defaults to runtime platform.")
+	_ = viper.BindPFlag("platform", flags.Lookup("platform"))
 
 	return checkContainerCmd
 }
@@ -103,80 +108,89 @@ func checkContainerRunE(cmd *cobra.Command, args []string, runpreflight runPrefl
 		return fmt.Errorf("invalid configuration: %w", err)
 	}
 
-	artifactsWriter, err := artifacts.NewFilesystemWriter(artifacts.WithDirectory(cfg.Artifacts))
-	if err != nil {
-		return err
-	}
-
-	// Add the artifact writer to the context for use by checks.
-	ctx = artifacts.ContextWithWriter(ctx, artifactsWriter)
+	cfg.Image = containerImage
 
-	formatter, err := formatters.NewByName(formatters.DefaultFormat)
+	containerImagePlatforms, err := platformsToBeProcessed(cmd, cfg)
 	if err != nil {
 		return err
 	}
 
-	opts := generateContainerCheckOptions(cfg)
-
-	checkcontainer := container.NewCheck(
-		containerImage,
-		opts...,
-	)
+	for _, platform := range containerImagePlatforms {
+		logger.Info(fmt.Sprintf("running checks for %s for platform %s", containerImage, platform))
+		artifactsWriter, err := artifacts.NewFilesystemWriter(artifacts.WithDirectory(filepath.Join(cfg.Artifacts, platform)))
+		if err != nil {
+			return err
+		}
 
-	pc := lib.NewPyxisClient(ctx, cfg.CertificationProjectID, cfg.PyxisAPIToken, cfg.PyxisHost)
-	resultSubmitter := lib.ResolveSubmitter(pc, cfg.CertificationProjectID, cfg.DockerConfig, cfg.LogFile)
+		// Add the artifact writer to the context for use by checks.
+		ctx := artifacts.ContextWithWriter(ctx, artifactsWriter)
 
-	// Run the  container check.
-	cmd.SilenceUsage = true
+		formatter, err := formatters.NewByName(formatters.DefaultFormat)
+		if err != nil {
+			return err
+		}
 
-	err = runpreflight(
-		ctx,
-		checkcontainer.Run,
-		cli.CheckConfig{
-			IncludeJUnitResults: cfg.WriteJUnit,
-			SubmitResults:       cfg.Submit,
-		},
-		formatter,
-		&runtime.ResultWriterFile{},
-		resultSubmitter,
-	)
+		opts := generateContainerCheckOptions(cfg)
+		opts = append(opts, container.WithPlatform(platform))
+
+		checkcontainer := container.NewCheck(
+			containerImage,
+			opts...,
+		)
+
+		pc := lib.NewPyxisClient(ctx, cfg.CertificationProjectID, cfg.PyxisAPIToken, cfg.PyxisHost)
+		resultSubmitter := lib.ResolveSubmitter(pc, cfg.CertificationProjectID, cfg.DockerConfig, cfg.LogFile)
+
+		// Run the  container check.
+		cmd.SilenceUsage = true
+
+		if err := runpreflight(
+			ctx,
+			checkcontainer.Run,
+			cli.CheckConfig{
+				IncludeJUnitResults: cfg.WriteJUnit,
+				SubmitResults:       cfg.Submit,
+			},
+			formatter,
+			&runtime.ResultWriterFile{},
+			resultSubmitter,
+		); err != nil {
+			return err
+		}
 
-	if err != nil {
-		return err
-	}
+		// checking for offline flag, if present tar up the contents of the artifacts directory
+		if cfg.Offline {
+			src := artifactsWriter.Path()
+			var buf bytes.Buffer
 
-	// checking for offline flag, if present tar up the contents of the artifacts directory
-	if cfg.Offline {
-		src := artifactsWriter.Path()
-		var buf bytes.Buffer
+			// check to see if a tar file already exist to account for someone re-running
+			exists, err := artifactsWriter.Exists(check.DefaultArtifactsTarFileName)
+			if err != nil {
+				return fmt.Errorf("unable to check if tar already exists: %v", err)
+			}
 
-		// check to see if a tar file already exist to account for someone re-running
-		exists, err := artifactsWriter.Exists(check.DefaultArtifactsTarFileName)
-		if err != nil {
-			return fmt.Errorf("unable to check if tar already exists: %v", err)
-		}
+			// remove the tar file if it exists
+			if exists {
+				err = artifactsWriter.Remove(check.DefaultArtifactsTarFileName)
+				if err != nil {
+					return fmt.Errorf("unable to remove existing tar: %v", err)
+				}
+			}
 
-		// remove the tar file if it exists
-		if exists {
-			err = artifactsWriter.Remove(check.DefaultArtifactsTarFileName)
+			// tar the directory
+			err = artifactsTar(ctx, src, &buf)
 			if err != nil {
-				return fmt.Errorf("unable to remove existing tar: %v", err)
+				return fmt.Errorf("unable to tar up artifacts directory: %v", err)
 			}
-		}
 
-		// tar the directory
-		err = artifactsTar(ctx, src, &buf)
-		if err != nil {
-			return fmt.Errorf("unable to tar up artifacts directory: %v", err)
-		}
+			// writing the tar file to disk
+			_, err = artifactsWriter.WriteFile(check.DefaultArtifactsTarFileName, &buf)
+			if err != nil {
+				return fmt.Errorf("could not artifacts tar to artifacts dir: %w", err)
+			}
 
-		// writing the tar file to disk
-		_, err = artifactsWriter.WriteFile(check.DefaultArtifactsTarFileName, &buf)
-		if err != nil {
-			return fmt.Errorf("could not artifacts tar to artifacts dir: %w", err)
+			logger.Info("artifact tar written to disk", "filename", check.DefaultArtifactsTarFileName)
 		}
-
-		logger.Info("artifact tar written to disk", "filename", check.DefaultArtifactsTarFileName)
 	}
 
 	return nil
@@ -251,6 +265,7 @@ func generateContainerCheckOptions(cfg *runtime.Config) []container.Option {
 		// Always add PyxisHost, since the value is always set in viper config parsing.
 		container.WithPyxisHost(cfg.PyxisHost),
 		container.WithPlatform(cfg.Platform),
+		container.WithManifestListDigest(cfg.ManifestListDigest),
 	}
 
 	// set auth information if both are present in config.
@@ -339,3 +354,90 @@ func artifactsTar(ctx context.Context, src string, w io.Writer) error {
 
 	return nil
 }
+
+func platformsToBeProcessed(cmd *cobra.Command, cfg *runtime.Config) ([]string, error) {
+	ctx := cmd.Context()
+	logger := logr.FromContextOrDiscard(ctx)
+
+	// flag.Changed is not set if the env is all that is set.
+	_, platformEnvPresent := os.LookupEnv("PFLT_PLATFORM")
+	platformChanged := cmd.Flags().Lookup("platform").Changed || platformEnvPresent
+
+	containerImagePlatforms := []string{cfg.Platform}
+
+	options := crane.GetOptions(option.GenerateCraneOptions(ctx, cfg)...)
+	ref, err := name.ParseReference(cfg.Image, options.Name...)
+	if err != nil {
+		return nil, fmt.Errorf("invalid image reference: %w", err)
+	}
+
+	desc, err := remote.Get(ref, options.Remote...)
+	if err != nil {
+		return nil, fmt.Errorf("invalid manifest?: %w", err)
+	}
+
+	if !desc.MediaType.IsIndex() {
+		// This means the passed image is just an image, and not a manifest list
+		// So, let's get the config to find out if the image matches the
+		// given platform.
+		img, err := desc.Image()
+		if err != nil {
+			return nil, fmt.Errorf("could not convert descriptor to image: %w", err)
+		}
+		cfgFile, err := img.ConfigFile()
+		if err != nil {
+			return nil, fmt.Errorf("could not retrieve image config: %w", err)
+		}
+
+		// A specific arch was specified. This image does not contain that arch.
+		if cfgFile.Architecture != cfg.Platform && !platformChanged {
+			return nil, fmt.Errorf("cannot process image manifest of different arch without platform override")
+		}
+
+		// At this point, we know that the original containerImagePlatform is correct, so
+		// we can just return it and skip the below.
+		// While we could just let this fall through to the end, I'd rather short-circuit
+		// here, in case any further changes disrupt that logic flow.
+		return containerImagePlatforms, nil
+	}
+
+	// If platform param is not changed, it means that a platform was not specified on the
+	// command line. Therefore, we should process all platforms in the manifest list.
+	// As long as what is poinged to is a manifest list. Otherwise, it will just be the
+	// currnt runtime platform.
+	if desc.MediaType.IsIndex() {
+		logger.V(log.DBG).Info("manifest list detected, checking all platforms in manifest")
+
+		idx, err := desc.ImageIndex()
+		if err != nil {
+			return nil, fmt.Errorf("could not convert descriptor to index: %w", err)
+		}
+		manifestListDigest, err := idx.Digest()
+		if err != nil {
+			return nil, fmt.Errorf("could not retrieve index digest: %w", err)
+		}
+		cfg.ManifestListDigest = manifestListDigest.String()
+
+		manifest, err := idx.IndexManifest()
+		if err != nil {
+			return nil, fmt.Errorf("could not retrieve index manifest: %w", err)
+		}
+
+		// Preflight was given a manifest list. --platform was not specified.
+		// Therefore, all platforms in the manifest list should be processed.
+		// Create a new slice since the original was for a single platform.
+		containerImagePlatforms = make([]string, 0, len(manifest.Manifests))
+		for _, img := range manifest.Manifests {
+			if platformChanged && cfg.Platform != img.Platform.Architecture {
+				// The user selected a platform. If this isn't it, continue.
+				continue
+			}
+			containerImagePlatforms = append(containerImagePlatforms, img.Platform.Architecture)
+		}
+		if platformChanged && len(containerImagePlatforms) == 0 {
+			return nil, fmt.Errorf("invalid platform specified")
+		}
+	}
+
+	return containerImagePlatforms, nil
+}
diff --git a/cmd/preflight/cmd/support.go b/cmd/preflight/cmd/support.go
index 91d50b3..22ddc16 100644
--- a/cmd/preflight/cmd/support.go
+++ b/cmd/preflight/cmd/support.go
@@ -10,21 +10,21 @@ import (
 )
 
 const (
-	baseURL              = "https://connect.redhat.com/support/technology-partner/#/case/new?"
-	typeParam            = "type"
-	typeValue            = "CERT"
-	sourceParam          = "source"
-	sourceValue          = "preflight"
-	certProjectTypeParam = "cert_project_type"
-	certProjectIDParam   = "cert_project_id"
-	pullRequestURLParam  = "pull_request_url"
-	operatorBundleImage  = "Operator Bundle Image"
-	containerImage       = "Container Image"
+	baseURL                 = "https://connect.redhat.com/support/technology-partner/#/case/new?"
+	typeParam               = "type"
+	typeValue               = "CERT"
+	sourceParam             = "source"
+	sourceValue             = "preflight"
+	certProjectTypeParam    = "cert_project_type"
+	certProjectIDParam      = "cert_project_id"
+	pullRequestURLParam     = "pull_request_url"
+	operatorBundleImageText = "Operator Bundle Image"
+	containerImageText      = "Container Image"
 )
 
 var projectTypeMapping = map[string]string{
-	"container": containerImage,
-	"operator":  operatorBundleImage,
+	"container": containerImageText,
+	"operator":  operatorBundleImageText,
 }
 
 func supportCmd() *cobra.Command {
diff --git a/container/check_container.go b/container/check_container.go
index c697483..88d57f6 100644
--- a/container/check_container.go
+++ b/container/check_container.go
@@ -71,12 +71,13 @@ func (c *containerCheck) Run(ctx context.Context) (certification.Results, error)
 	}
 
 	cfg := runtime.Config{
-		Image:        c.image,
-		DockerConfig: c.dockerconfigjson,
-		Scratch:      pol == policy.PolicyScratch,
-		Bundle:       false,
-		Insecure:     c.insecure,
-		Platform:     c.platform,
+		Image:              c.image,
+		DockerConfig:       c.dockerconfigjson,
+		Scratch:            pol == policy.PolicyScratch,
+		Bundle:             false,
+		Insecure:           c.insecure,
+		Platform:           c.platform,
+		ManifestListDigest: c.manifestListDigest,
 	}
 	eng, err := engine.New(ctx, checks, nil, cfg)
 	if err != nil {
@@ -151,6 +152,15 @@ func WithInsecureConnection() Option {
 	}
 }
 
+// WithManifestListDigest signifies that we have a manifest list and should add
+// this digest to any Pyxis calls.
+// This is only valid when submitting to Pyxis. Otherwise, it will be ignored.
+func WithManifestListDigest(manifestListDigest string) Option {
+	return func(cc *containerCheck) {
+		cc.manifestListDigest = manifestListDigest
+	}
+}
+
 type containerCheck struct {
 	image                  string
 	dockerconfigjson       string
@@ -159,4 +169,5 @@ type containerCheck struct {
 	pyxisHost              string
 	platform               string
 	insecure               bool
+	manifestListDigest     string
 }
diff --git a/go.mod b/go.mod
index 50e83fa..e3d0ca6 100644
--- a/go.mod
+++ b/go.mod
@@ -14,7 +14,7 @@ require (
 	github.com/onsi/gomega v1.27.10
 	github.com/openshift/api v0.0.0-20230223193310-d964c7a58d75
 	github.com/openshift/client-go v0.0.0-20230120202327-72f107311084
-	github.com/operator-framework/api v0.17.6
+	github.com/operator-framework/api v0.17.7
 	github.com/operator-framework/operator-manifest-tools v0.3.0
 	github.com/redhat-certification/chart-verifier v0.0.0-20230601213937-5c17fa99cd1f
 	github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29
@@ -41,7 +41,7 @@ require (
 	github.com/Masterminds/sprig v2.22.0+incompatible // indirect
 	github.com/Masterminds/sprig/v3 v3.2.2 // indirect
 	github.com/Masterminds/squirrel v1.5.3 // indirect
-	github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
+	github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
 	github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/blang/semver/v4 v4.0.0 // indirect
@@ -79,7 +79,7 @@ require (
 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/google/btree v1.0.1 // indirect
-	github.com/google/cel-go v0.12.6 // indirect
+	github.com/google/cel-go v0.15.3 // indirect
 	github.com/google/gnostic v0.5.7-v3refs // indirect
 	github.com/google/go-cmp v0.5.9 // indirect
 	github.com/google/gofuzz v1.2.0 // indirect
@@ -163,6 +163,7 @@ require (
 	go.opentelemetry.io/proto/otlp v0.19.0 // indirect
 	go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
 	golang.org/x/crypto v0.11.0 // indirect
+	golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
 	golang.org/x/mod v0.10.0 // indirect
 	golang.org/x/net v0.12.0 // indirect
 	golang.org/x/oauth2 v0.7.0 // indirect
@@ -175,7 +176,7 @@ require (
 	golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
 	gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
-	google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
+	google.golang.org/genproto v0.0.0-20230525154841-bd750badd5c6 // indirect
 	google.golang.org/grpc v1.55.0 // indirect
 	google.golang.org/protobuf v1.30.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
diff --git a/go.sum b/go.sum
index 65b6537..829823a 100644
--- a/go.sum
+++ b/go.sum
@@ -130,8 +130,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
 github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves=
-github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
+github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18=
+github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM=
 github.com/apex/log v1.9.0/go.mod h1:m82fZlWIuiWzWP04XCTXmnX0xRkYYbCdYn8jbJeLBEA=
 github.com/apex/logs v1.0.0/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo=
 github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE=
@@ -407,8 +407,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
 github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
-github.com/google/cel-go v0.12.6 h1:kjeKudqV0OygrAqA9fX6J55S8gj+Jre2tckIm5RoG4M=
-github.com/google/cel-go v0.12.6/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw=
+github.com/google/cel-go v0.15.3 h1:W1wIeGuEs81+lBVU+cQRg1hkRT58Q6bNxvM5yn008S8=
+github.com/google/cel-go v0.15.3/go.mod h1:YzWEoI07MC/a/wj9in8GeVatqfypkldgBlwXh9bCwqY=
 github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
 github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -735,8 +735,8 @@ github.com/openshift/api v0.0.0-20230223193310-d964c7a58d75 h1:OQJsfiach1cKBI1xU
 github.com/openshift/api v0.0.0-20230223193310-d964c7a58d75/go.mod h1:ctXNyWanKEjGj8sss1KjjHQ3ENKFm33FFnS5BKaIPh4=
 github.com/openshift/client-go v0.0.0-20230120202327-72f107311084 h1:66uaqNwA+qYyQDwsMWUfjjau8ezmg1dzCqub13KZOcE=
 github.com/openshift/client-go v0.0.0-20230120202327-72f107311084/go.mod h1:M3h9m001PWac3eAudGG3isUud6yBjr5XpzLYLLTlHKo=
-github.com/operator-framework/api v0.17.6 h1:E6+vlvYUKafvoXYtCuHlDZrXX4vl8AT+r93OxNlzjpU=
-github.com/operator-framework/api v0.17.6/go.mod h1:l/cuwtPxkVUY7fzYgdust2m9tlmb8I4pOvbsUufRb24=
+github.com/operator-framework/api v0.17.7 h1:NLn+Ieg+HaPrw75KbX4efllN21ofFArQzS3q8TDbQY0=
+github.com/operator-framework/api v0.17.7/go.mod h1:lnurXgadLnoZ7pufKMHkErr2BVOIZSpHtvEkHBcKvdk=
 github.com/operator-framework/operator-manifest-tools v0.3.0 h1:iKxHA1dKWs22QwUQZhPJAHwRASmI0mnsMVNay0LnCpU=
 github.com/operator-framework/operator-manifest-tools v0.3.0/go.mod h1:PT1D+dEbD9TCoo62TkRP4BHYXA+h+zC0i3Ql7WZW9os=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@@ -1022,6 +1022,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
+golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -1414,8 +1416,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE
 google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
 google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
+google.golang.org/genproto v0.0.0-20230525154841-bd750badd5c6 h1:62QuyPXKEkZpjZesyj5K5jABl6MnSnWl+vNuT5oz90E=
+google.golang.org/genproto v0.0.0-20230525154841-bd750badd5c6/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
diff --git a/internal/engine/engine.go b/internal/engine/engine.go
index 47ed4e9..4398502 100644
--- a/internal/engine/engine.go
+++ b/internal/engine/engine.go
@@ -50,14 +50,15 @@ func New(ctx context.Context,
 	cfg runtime.Config,
 ) (craneEngine, error) {
 	return craneEngine{
-		kubeconfig:   kubeconfig,
-		dockerConfig: cfg.DockerConfig,
-		image:        cfg.Image,
-		checks:       checks,
-		isBundle:     cfg.Bundle,
-		isScratch:    cfg.Scratch,
-		platform:     cfg.Platform,
-		insecure:     cfg.Insecure,
+		kubeconfig:         kubeconfig,
+		dockerConfig:       cfg.DockerConfig,
+		image:              cfg.Image,
+		checks:             checks,
+		isBundle:           cfg.Bundle,
+		isScratch:          cfg.Scratch,
+		platform:           cfg.Platform,
+		insecure:           cfg.Insecure,
+		manifestListDigest: cfg.ManifestListDigest,
 	}, nil
 }
 
@@ -88,6 +89,9 @@ type craneEngine struct {
 	// the registry crane connects with.
 	insecure bool
 
+	// ManifestListDigest is the sha256 digest for the manifest list
+	manifestListDigest string
+
 	imageRef image.ImageReference
 	results  certification.Results
 }
@@ -179,12 +183,13 @@ func (c *craneEngine) ExecuteChecks(ctx context.Context) error {
 
 	// store the image internals in the engine image reference to pass to validations.
 	c.imageRef = image.ImageReference{
-		ImageURI:        c.image,
-		ImageFSPath:     containerFSPath,
-		ImageInfo:       img,
-		ImageRegistry:   reference.Context().RegistryStr(),
-		ImageRepository: reference.Context().RepositoryStr(),
-		ImageTagOrSha:   reference.Identifier(),
+		ImageURI:           c.image,
+		ImageFSPath:        containerFSPath,
+		ImageInfo:          img,
+		ImageRegistry:      reference.Context().RegistryStr(),
+		ImageRepository:    reference.Context().RepositoryStr(),
+		ImageTagOrSha:      reference.Identifier(),
+		ManifestListDigest: c.manifestListDigest,
 	}
 
 	if err := writeCertImage(ctx, c.imageRef); err != nil {
@@ -498,10 +503,11 @@ func writeCertImage(ctx context.Context, imageRef image.ImageReference) error {
 
 	repositories := make([]pyxis.Repository, 0, 1)
 	repositories = append(repositories, pyxis.Repository{
-		PushDate:   addedDate,
-		Registry:   imageRef.ImageRegistry,
-		Repository: imageRef.ImageRepository,
-		Tags:       tags,
+		PushDate:           addedDate,
+		Registry:           imageRef.ImageRegistry,
+		Repository:         imageRef.ImageRepository,
+		Tags:               tags,
+		ManifestListDigest: imageRef.ManifestListDigest,
 	})
 
 	certImage := pyxis.CertImage{
diff --git a/internal/image/types.go b/internal/image/types.go
index 8f7476a..39a3b49 100644
--- a/internal/image/types.go
+++ b/internal/image/types.go
@@ -4,10 +4,11 @@ import v1 "github.com/google/go-containerregistry/pkg/v1"
 
 // ImageReference holds all things image-related
 type ImageReference struct {
-	ImageURI        string
-	ImageFSPath     string
-	ImageInfo       v1.Image
-	ImageRepository string
-	ImageRegistry   string
-	ImageTagOrSha   string
+	ImageURI           string
+	ImageFSPath        string
+	ImageInfo          v1.Image
+	ImageRepository    string
+	ImageRegistry      string
+	ImageTagOrSha      string
+	ManifestListDigest string
 }
diff --git a/internal/pyxis/types.go b/internal/pyxis/types.go
index 9d8351b..d274505 100644
--- a/internal/pyxis/types.go
+++ b/internal/pyxis/types.go
@@ -60,11 +60,12 @@ type ParsedData struct {
 }
 
 type Repository struct {
-	Published  bool   `json:"published" default:"false"`
-	PushDate   string `json:"push_date,omitempty"` // time.Now
-	Registry   string `json:"registry,omitempty"`
-	Repository string `json:"repository,omitempty"`
-	Tags       []Tag  `json:"tags,omitempty"`
+	Published          bool   `json:"published" default:"false"`
+	PushDate           string `json:"push_date,omitempty"` // time.Now
+	Registry           string `json:"registry,omitempty"`
+	Repository         string `json:"repository,omitempty"`
+	Tags               []Tag  `json:"tags,omitempty"`
+	ManifestListDigest string `json:"manifest_list_digest,omitempty"`
 }
 
 type Label struct {
diff --git a/internal/runtime/config.go b/internal/runtime/config.go
index 719cc5a..9fa991c 100644
--- a/internal/runtime/config.go
+++ b/internal/runtime/config.go
@@ -28,6 +28,7 @@ type Config struct {
 	Platform               string
 	Insecure               bool
 	Offline                bool
+	ManifestListDigest     string
 	// Operator-Specific Fields
 	Namespace         string
 	ServiceAccount    string


Test patch:
diff --git a/cmd/preflight/cmd/check_container_test.go b/cmd/preflight/cmd/check_container_test.go
index 0c60d46..25c7de0 100644
--- a/cmd/preflight/cmd/check_container_test.go
+++ b/cmd/preflight/cmd/check_container_test.go
@@ -4,8 +4,14 @@ import (
 	"bytes"
 	"context"
 	"errors"
+	"fmt"
+	"io"
+	"log"
+	"net/http/httptest"
+	"net/url"
 	"os"
 	"path/filepath"
+	"runtime"
 
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/artifacts"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
@@ -16,22 +22,125 @@ import (
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/viper"
 
 	"github.com/go-logr/logr"
+	"github.com/google/go-containerregistry/pkg/crane"
+	"github.com/google/go-containerregistry/pkg/name"
+	"github.com/google/go-containerregistry/pkg/registry"
+	cranev1 "github.com/google/go-containerregistry/pkg/v1"
+	"github.com/google/go-containerregistry/pkg/v1/mutate"
+	"github.com/google/go-containerregistry/pkg/v1/random"
+	"github.com/google/go-containerregistry/pkg/v1/remote"
+	cranev1types "github.com/google/go-containerregistry/pkg/v1/types"
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
+	"github.com/onsi/gomega/types"
 )
 
 var _ = Describe("Check Container Command", func() {
+	var src string
+	var manifestListSrc string
+	var srcppc string
+	var manifests map[string]string
+	var s *httptest.Server
+	var u *url.URL
+	BeforeEach(func() {
+		manifests = make(map[string]string, 2)
+		// Set up a fake registry.
+		registryLogger := log.New(io.Discard, "", log.Ldate)
+		s = httptest.NewServer(registry.New(registry.Logger(registryLogger)))
+		DeferCleanup(s.Close)
+
+		var err error
+		u, err = url.Parse(s.URL)
+		Expect(err).ToNot(HaveOccurred())
+
+		src = fmt.Sprintf("%s/test/crane", u.Host)
+		manifests["image"] = src
+
+		// Expected values.
+		img, err := random.Image(1024, 5)
+		Expect(err).ToNot(HaveOccurred())
+
+		cfgFile, err := img.ConfigFile()
+		Expect(err).ToNot(HaveOccurred())
+
+		cfgFile.Architecture = "amd64"
+
+		cfgImg, err := mutate.ConfigFile(img, cfgFile)
+		Expect(err).ToNot(HaveOccurred())
+
+		err = crane.Push(cfgImg, src)
+		Expect(err).ToNot(HaveOccurred())
+
+		srcppc = fmt.Sprintf("%s/test/craneppc", u.Host)
+		manifests["imageppc"] = srcppc
+
+		newLayer, err := random.Layer(1024, cranev1types.OCILayer)
+		Expect(err).ToNot(HaveOccurred())
+
+		ppcImg, err := mutate.AppendLayers(img, newLayer)
+		Expect(err).ToNot(HaveOccurred())
+
+		ppcCfgFile, err := ppcImg.ConfigFile()
+		Expect(err).ToNot(HaveOccurred())
+
+		ppcCfgFile.Architecture = "ppc64le"
+
+		ppcCfgImg, err := mutate.ConfigFile(ppcImg, ppcCfgFile)
+		Expect(err).ToNot(HaveOccurred())
+
+		Expect(crane.Push(ppcCfgImg, srcppc)).To(Succeed())
+
+		platforms := [4]string{"amd64", "arm64", "ppc64le", "s390x"}
+		manifestListSrc = fmt.Sprintf("%s/test/cranelist", u.Host)
+		manifests["index"] = manifestListSrc
+		lst, err := random.Index(1024, 5, int64(len(platforms)))
+		Expect(err).ToNot(HaveOccurred())
+
+		ref, err := name.ParseReference(manifestListSrc)
+		Expect(err).ToNot(HaveOccurred())
+
+		m, err := lst.IndexManifest()
+		Expect(err).ToNot(HaveOccurred())
+
+		for i, manifest := range m.Manifests {
+			switch {
+			case manifest.MediaType.IsImage():
+				m.Manifests[i].Platform = &cranev1.Platform{
+					Architecture: platforms[i],
+					OS:           "linux",
+				}
+			}
+		}
+		err = remote.WriteIndex(ref, lst)
+		Expect(err).ToNot(HaveOccurred())
+	})
 	BeforeEach(createAndCleanupDirForArtifactsAndLogs)
 
-	Context("when running the check container subcommand", func() {
-		Context("With all of the required parameters", func() {
-			It("should reach the core logic, but throw an error because of the placeholder values for the container image", func() {
-				_, err := executeCommand(checkContainerCmd(mockRunPreflightReturnNil), "example.com/example/image:mytag")
-				Expect(err).To(HaveOccurred())
+	When("a manifest list is passed", func() {
+		When("default params otherwise", func() {
+			It("should not error", func() {
+				_, err := executeCommandWithLogger(checkContainerCmd(mockRunPreflightReturnNil), logr.Discard(), manifestListSrc)
+				Expect(err).ToNot(HaveOccurred())
 			})
 		})
 	})
 
+	DescribeTable("--platform tests",
+		func(manifestKey string, platform string, match types.GomegaMatcher, includePlatformArg bool) {
+			args := []string{manifests[manifestKey]}
+			if includePlatformArg {
+				args = append(args, "--platform", platform)
+			}
+			_, err := executeCommandWithLogger(checkContainerCmd(mockRunPreflightReturnNil), logr.Discard(), args...)
+			Expect(err).To(match)
+		},
+		Entry("image manifest, valid platform", "image", "amd64", Not(HaveOccurred()), true),
+		Entry("image manifest, different platform, modifier", "image", "none", Not(HaveOccurred()), true),
+		Entry("image manifest, different platform, no modifier", "imageppc", "none", HaveOccurred(), false),
+		Entry("index manifest, valid platform", "index", "amd64", Not(HaveOccurred()), true),
+		Entry("index manifest, invalid platform", "index", "none", HaveOccurred(), true),
+	)
+
 	Context("When validating check container arguments and flags", func() {
 		Context("and the user provided more than 1 positional arg", func() {
 			It("should fail to run", func() {
@@ -153,13 +262,13 @@ certification_project_id: mycertid`
 	Context("when running the check container subcommand with a logger provided", func() {
 		Context("with all of the required parameters", func() {
 			It("should reach the core logic, and execute the mocked RunPreflight", func() {
-				_, err := executeCommandWithLogger(checkContainerCmd(mockRunPreflightReturnNil), logr.Discard(), "example.com/example/image:mytag")
+				_, err := executeCommandWithLogger(checkContainerCmd(mockRunPreflightReturnNil), logr.Discard(), src)
 				Expect(err).ToNot(HaveOccurred())
 			})
 		})
 		Context("with all of the required parameters with error mocked", func() {
 			It("should reach the core logic, and execute the mocked RunPreflight and return error", func() {
-				_, err := executeCommandWithLogger(checkContainerCmd(mockRunPreflightReturnErr), logr.Discard(), "example.com/example/image:mytag")
+				_, err := executeCommandWithLogger(checkContainerCmd(mockRunPreflightReturnErr), logr.Discard(), src)
 				Expect(err).To(HaveOccurred())
 			})
 		})
@@ -172,12 +281,15 @@ certification_project_id: mycertid`
 				Expect(err).ToNot(HaveOccurred())
 				DeferCleanup(os.RemoveAll, tmpDir)
 
+				platformDir := filepath.Join(tmpDir, runtime.GOARCH)
+				Expect(os.Mkdir(platformDir, 0o755)).Should(Succeed())
+
 				// creating test files on in the tmpDir so the tar function has files to tar
-				f1, err := os.Create(filepath.Join(tmpDir, "test-file-1.json"))
+				f1, err := os.Create(filepath.Join(platformDir, "test-file-1.json"))
 				Expect(err).ToNot(HaveOccurred())
 				defer f1.Close()
 
-				f2, err := os.Create(filepath.Join(tmpDir, "test-file-1.json"))
+				f2, err := os.Create(filepath.Join(platformDir, "test-file-1.json"))
 				Expect(err).ToNot(HaveOccurred())
 				defer f2.Close()
 
@@ -188,7 +300,7 @@ certification_project_id: mycertid`
 				DeferCleanup(viper.Instance().Set, "offline", false)
 			})
 			It("should reach core logic, and the additional offline logic", func() {
-				out, err := executeCommandWithLogger(checkContainerCmd(mockRunPreflightReturnNil), logr.Discard(), "example.com/example/image:mytag")
+				out, err := executeCommandWithLogger(checkContainerCmd(mockRunPreflightReturnNil), logr.Discard(), src)
 				Expect(err).ToNot(HaveOccurred())
 				Expect(out).ToNot(BeNil())
 			})
@@ -199,12 +311,15 @@ certification_project_id: mycertid`
 				Expect(err).ToNot(HaveOccurred())
 				DeferCleanup(os.RemoveAll, tmpDir)
 
+				platformDir := filepath.Join(tmpDir, runtime.GOARCH)
+				Expect(os.Mkdir(platformDir, 0o755)).Should(Succeed())
+
 				// creating test files on in the tmpDir so the tar function has files to tar
-				f1, err := os.Create(filepath.Join(tmpDir, "test-file-1.json"))
+				f1, err := os.Create(filepath.Join(platformDir, "test-file-1.json"))
 				Expect(err).ToNot(HaveOccurred())
 				defer f1.Close()
 
-				f2, err := os.Create(filepath.Join(tmpDir, "test-file-1.json"))
+				f2, err := os.Create(filepath.Join(platformDir, "test-file-1.json"))
 				Expect(err).ToNot(HaveOccurred())
 				defer f2.Close()
 
@@ -220,7 +335,7 @@ certification_project_id: mycertid`
 				DeferCleanup(viper.Instance().Set, "offline", false)
 			})
 			It("should reach the additional offline logic, and remove existing tar file", func() {
-				out, err := executeCommandWithLogger(checkContainerCmd(mockRunPreflightReturnNil), logr.Discard(), "example.com/example/image:mytag")
+				out, err := executeCommandWithLogger(checkContainerCmd(mockRunPreflightReturnNil), logr.Discard(), src)
 				Expect(err).ToNot(HaveOccurred())
 				Expect(out).ToNot(BeNil())
 			})
diff --git a/internal/runtime/config_test.go b/internal/runtime/config_test.go
index fd432a8..4593cc3 100644
--- a/internal/runtime/config_test.go
+++ b/internal/runtime/config_test.go
@@ -64,12 +64,12 @@ var _ = Describe("Viper to Runtime Config", func() {
 		})
 	})
 
-	It("should only have 23 struct keys for tests to be valid", func() {
+	It("should only have 24 struct keys for tests to be valid", func() {
 		// If this test fails, it means a developer has added or removed
 		// keys from runtime.Config, and so these tests may no longer be
 		// accurate in confirming that the derived configuration from viper
 		// matches.
 		keys := reflect.TypeOf(Config{}).NumField()
-		Expect(keys).To(Equal(23))
+		Expect(keys).To(Equal(24))
 	})
 })