From d7a1fcee5dca010806d66bfae3bd29a487f2e1cb Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Fri, 2 Jun 2023 15:41:22 -0400 Subject: [PATCH 1/8] add test case for specific digest Signed-off-by: Will Murphy --- test/integration/platform_test.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/integration/platform_test.go b/test/integration/platform_test.go index 91e2d503..4fc05650 100644 --- a/test/integration/platform_test.go +++ b/test/integration/platform_test.go @@ -89,3 +89,31 @@ func TestPlatformSelection(t *testing.T) { }) } } + +func TestDigestThatNarrowsToOnePlatform(t *testing.T) { + // busybox:1.31 on linux/s390x + // Test assumes that the host running these tests _isn't_ linux/s390x, but the behavior + // should be the same regardless. + imageStrWithDigest := "busybox:1.31@sha256:91c15b1ba6f408a648be60f8c047ef79058f26fa640025f374281f31c8704387" + tests := []struct { + name string + source image.Source + }{ + { + name: "docker", + source: image.DockerDaemonSource, + }, + { + name: "registry", + source: image.OciRegistrySource, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + img, err := stereoscope.GetImageFromSource(context.TODO(), imageStrWithDigest, tt.source, stereoscope.WithPlatform("linux/s390x")) + assert.NoError(t, err) + assert.Equal(t, "s390x", img.Metadata.Architecture) + assert.Equal(t, "linux", img.Metadata.OS) + }) + } +} From 05de0469bbbdcda406b5a2dfe797362f50d3c465 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Fri, 2 Jun 2023 15:43:36 -0400 Subject: [PATCH 2/8] Revert "Set the default platform for select sources based on host arch (#152)" This reverts commit d7551b7f46f53179922d6229709d3d1602881080. Signed-off-by: Will Murphy --- client.go | 44 ++++------- client_test.go | 193 ------------------------------------------------- 2 files changed, 13 insertions(+), 224 deletions(-) delete mode 100644 client_test.go diff --git a/client.go b/client.go index ce0f4d16..778a93ea 100644 --- a/client.go +++ b/client.go @@ -3,7 +3,6 @@ package stereoscope import ( "context" "fmt" - "runtime" "github.com/wagoodman/go-partybus" @@ -102,13 +101,13 @@ func GetImageFromSource(ctx context.Context, imgStr string, source image.Source, func selectImageProvider(imgStr string, source image.Source, cfg config) (image.Provider, error) { var provider image.Provider tempDirGenerator := rootTempDirGenerator.NewGenerator() - - if err := setPlatform(source, &cfg, runtime.GOARCH); err != nil { - return nil, err - } + platformSelectionUnsupported := fmt.Errorf("specified platform=%q however image source=%q does not support selecting platform", cfg.Platform.String(), source.String()) switch source { case image.DockerTarballSource: + if cfg.Platform != nil { + return nil, platformSelectionUnsupported + } // note: the imgStr is the path on disk to the tar file provider = docker.NewProviderFromTarball(imgStr, tempDirGenerator) case image.DockerDaemonSource: @@ -130,12 +129,21 @@ func selectImageProvider(imgStr string, source image.Source, cfg config) (image. return nil, err } case image.OciDirectorySource: + if cfg.Platform != nil { + return nil, platformSelectionUnsupported + } provider = oci.NewProviderFromPath(imgStr, tempDirGenerator) case image.OciTarballSource: + if cfg.Platform != nil { + return nil, platformSelectionUnsupported + } provider = oci.NewProviderFromTarball(imgStr, tempDirGenerator) case image.OciRegistrySource: provider = oci.NewProviderFromRegistry(imgStr, tempDirGenerator, cfg.Registry, cfg.Platform) case image.SingularitySource: + if cfg.Platform != nil { + return nil, platformSelectionUnsupported + } provider = sif.NewProviderFromPath(imgStr, tempDirGenerator) default: return nil, fmt.Errorf("unable to determine image source") @@ -143,32 +151,6 @@ func selectImageProvider(imgStr string, source image.Source, cfg config) (image. return provider, nil } -func setPlatform(source image.Source, cfg *config, defaultArch string) error { - // we should override the platform based on the host architecture if the user did not specify a platform - // see https://github.com/anchore/stereoscope/issues/149 for more details - defaultPlatform, err := image.NewPlatform(defaultArch) - if err != nil { - log.WithFields("error", err).Warnf("unable to set default platform to %q", runtime.GOARCH) - defaultPlatform = nil - } - - switch source { - case image.DockerTarballSource, image.OciDirectorySource, image.OciTarballSource, image.SingularitySource: - if cfg.Platform != nil { - return fmt.Errorf("specified platform=%q however image source=%q does not support selecting platform", cfg.Platform.String(), source.String()) - } - - case image.DockerDaemonSource, image.PodmanDaemonSource, image.OciRegistrySource: - if cfg.Platform == nil { - cfg.Platform = defaultPlatform - } - - default: - return fmt.Errorf("unable to determine image source to select platform") - } - return nil -} - // GetImage parses the user provided image string and provides an image object; // note: the source where the image should be referenced from is automatically inferred. func GetImage(ctx context.Context, userStr string, options ...Option) (*image.Image, error) { diff --git a/client_test.go b/client_test.go deleted file mode 100644 index 82a420e5..00000000 --- a/client_test.go +++ /dev/null @@ -1,193 +0,0 @@ -package stereoscope - -import ( - "testing" - - "github.com/scylladb/go-set/i8set" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/anchore/stereoscope/pkg/image" -) - -func Test_setPlatform(t *testing.T) { - - expectedSources := i8set.New() - for _, s := range image.AllSources { - expectedSources.Add(int8(s)) - } - actualSources := i8set.New() - - tests := []struct { - name string - source image.Source - defaultArch string - initialPlatform *image.Platform - wantPlatform *image.Platform - wantErr require.ErrorAssertionFunc - }{ - // allow defaults --------------------------------------------------------- - { - name: "docker daemon", - source: image.DockerDaemonSource, - defaultArch: "amd64", - initialPlatform: nil, - wantPlatform: &image.Platform{ - Architecture: "amd64", - OS: "linux", - }, - }, - { - name: "docker daemon (do not override)", - source: image.DockerDaemonSource, - defaultArch: "amd64", - initialPlatform: &image.Platform{ - Architecture: "arm64", // not different than default arch - OS: "linux", - }, - wantPlatform: &image.Platform{ - Architecture: "arm64", // note: did not change - OS: "linux", - }, - }, - { - name: "podman daemon", - source: image.PodmanDaemonSource, - defaultArch: "amd64", - initialPlatform: nil, - wantPlatform: &image.Platform{ - Architecture: "amd64", - OS: "linux", - }, - }, - { - name: "podman daemon (do not override)", - source: image.PodmanDaemonSource, - defaultArch: "amd64", - initialPlatform: &image.Platform{ - Architecture: "arm64", // not different than default arch - OS: "linux", - }, - wantPlatform: &image.Platform{ - Architecture: "arm64", // note: did not change - OS: "linux", - }, - }, - { - name: "OCI registry", - source: image.OciRegistrySource, - defaultArch: "amd64", - initialPlatform: nil, - wantPlatform: &image.Platform{ - Architecture: "amd64", - OS: "linux", - }, - }, - { - name: "OCI registry (do not override)", - source: image.OciRegistrySource, - defaultArch: "amd64", - initialPlatform: &image.Platform{ - Architecture: "arm64", // not different than default arch - OS: "linux", - }, - wantPlatform: &image.Platform{ - Architecture: "arm64", // note: did not change - OS: "linux", - }, - }, - // disallow defaults --------------------------------------------------------- - { - name: "docker tarball", - source: image.DockerTarballSource, - defaultArch: "amd64", - initialPlatform: nil, - wantPlatform: nil, - }, - { - name: "docker tarball (override fails)", - source: image.DockerTarballSource, - defaultArch: "amd64", - initialPlatform: &image.Platform{ - Architecture: "amd64", - OS: "linux", - }, - wantErr: require.Error, - }, - { - name: "OCI dir", - source: image.OciDirectorySource, - defaultArch: "amd64", - initialPlatform: nil, - wantPlatform: nil, - }, - { - name: "OCI dir (override fails)", - source: image.OciDirectorySource, - defaultArch: "amd64", - initialPlatform: &image.Platform{ - Architecture: "amd64", - OS: "linux", - }, - wantErr: require.Error, - }, - { - name: "OCI tarball", - source: image.OciTarballSource, - defaultArch: "amd64", - initialPlatform: nil, - wantPlatform: nil, - }, - { - name: "OCI tarball (override fails)", - source: image.OciTarballSource, - defaultArch: "amd64", - initialPlatform: &image.Platform{ - Architecture: "amd64", - OS: "linux", - }, - wantErr: require.Error, - }, - { - name: "singularity", - source: image.SingularitySource, - defaultArch: "amd64", - initialPlatform: nil, - wantPlatform: nil, - }, - { - name: "singularity (override fails)", - source: image.SingularitySource, - defaultArch: "amd64", - initialPlatform: &image.Platform{ - Architecture: "amd64", - OS: "linux", - }, - wantErr: require.Error, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.wantErr == nil { - tt.wantErr = require.NoError - } - - actualSources.Add(int8(tt.source)) - cfg := config{ - Platform: tt.initialPlatform, - } - err := setPlatform(tt.source, &cfg, tt.defaultArch) - tt.wantErr(t, err) - if err != nil { - return - } - - assert.Equal(t, tt.wantPlatform, cfg.Platform) - }) - } - - diff := i8set.Difference(expectedSources, actualSources) - if !diff.IsEmpty() { - t.Errorf("missing test cases for sources: %v", diff.List()) - } -} From d8945815d66ace315c83a63a8717d8baa7c1a95d Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Fri, 2 Jun 2023 19:25:13 -0400 Subject: [PATCH 3/8] passes old and new tests Signed-off-by: Will Murphy --- test/integration/platform_test.go | 37 ++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/test/integration/platform_test.go b/test/integration/platform_test.go index 4fc05650..e4f28d50 100644 --- a/test/integration/platform_test.go +++ b/test/integration/platform_test.go @@ -2,6 +2,7 @@ package integration import ( "context" + "encoding/json" "fmt" "strings" "testing" @@ -28,6 +29,12 @@ func TestPlatformSelection(t *testing.T) { os: "linux", expectedDigest: "sha256:1ee006886991ad4689838d3a288e0dd3fd29b70e276622f16b67a8922831a853", // direct from repo manifest }, + { + source: image.OciRegistrySource, + architecture: "s390x", + os: "linux", + expectedDigest: "sha256:91c15b1ba6f408a648be60f8c047ef79058f26fa640025f374281f31c8704387", // from generated manifest + }, { source: image.OciRegistrySource, architecture: "amd64", @@ -46,6 +53,12 @@ func TestPlatformSelection(t *testing.T) { os: "linux", expectedDigest: "sha256:79d3cb76a5a8ba402af164ace87bd0f3e0759979f94caf7247745126359711da", // from generated manifest }, + { + source: image.DockerDaemonSource, + architecture: "s390x", + os: "linux", + expectedDigest: "sha256:91c15b1ba6f408a648be60f8c047ef79058f26fa640025f374281f31c8704387", // from generated manifest + }, { source: image.PodmanDaemonSource, architecture: "arm64", @@ -71,8 +84,10 @@ func TestPlatformSelection(t *testing.T) { tt.expectedErr(t, err) require.NotNil(t, img) - assert.Equal(t, tt.os, img.Metadata.OS) - assert.Equal(t, tt.architecture, img.Metadata.Architecture) + // TODO: decode image config and test + // assert.Equal(t, tt.os, img.Metadata.OS) + // assert.Equal(t, tt.architecture, img.Metadata.Architecture) + assertArchAndOs(t, img, tt.architecture, tt.os) found := false if img.Metadata.ManifestDigest == tt.expectedDigest { found = true @@ -110,10 +125,22 @@ func TestDigestThatNarrowsToOnePlatform(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - img, err := stereoscope.GetImageFromSource(context.TODO(), imageStrWithDigest, tt.source, stereoscope.WithPlatform("linux/s390x")) + img, err := stereoscope.GetImageFromSource(context.TODO(), imageStrWithDigest, tt.source) assert.NoError(t, err) - assert.Equal(t, "s390x", img.Metadata.Architecture) - assert.Equal(t, "linux", img.Metadata.OS) + // TODO: these tests are wrong + assertArchAndOs(t, img, "s390x", "linux") }) } } + +func assertArchAndOs(t *testing.T, img *image.Image, architecture string, os string) { + type platform struct { + Architecture string `json:"architecture"` + Os string `json:"os"` + } + var got platform + err := json.Unmarshal(img.Metadata.RawConfig, &got) + require.NoError(t, err) + assert.Equal(t, os, got.Os) + assert.Equal(t, architecture, got.Architecture) +} From 0d737635e7aac209393c48c9e156058a490e725b Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Fri, 9 Jun 2023 10:53:20 -0400 Subject: [PATCH 4/8] Make OCI provider default to current arch This was previously fixed by PR 152, but that PR introduced another bug. Re-implement platform defaulting after the revert of PR 152. Signed-off-by: Will Murphy --- client.go | 11 +++++++++++ test/integration/platform_test.go | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/client.go b/client.go index 778a93ea..ee3588fb 100644 --- a/client.go +++ b/client.go @@ -3,6 +3,7 @@ package stereoscope import ( "context" "fmt" + "runtime" "github.com/wagoodman/go-partybus" @@ -139,6 +140,7 @@ func selectImageProvider(imgStr string, source image.Source, cfg config) (image. } provider = oci.NewProviderFromTarball(imgStr, tempDirGenerator) case image.OciRegistrySource: + defaultPlatformIfNil(&cfg) provider = oci.NewProviderFromRegistry(imgStr, tempDirGenerator, cfg.Registry, cfg.Platform) case image.SingularitySource: if cfg.Platform != nil { @@ -151,6 +153,15 @@ func selectImageProvider(imgStr string, source image.Source, cfg config) (image. return provider, nil } +func defaultPlatformIfNil(cfg *config) { + if cfg.Platform == nil { + p, err := image.NewPlatform(fmt.Sprintf("linux/%s", runtime.GOARCH)) + if err == nil { + cfg.Platform = p + } + } +} + // GetImage parses the user provided image string and provides an image object; // note: the source where the image should be referenced from is automatically inferred. func GetImage(ctx context.Context, userStr string, options ...Option) (*image.Image, error) { diff --git a/test/integration/platform_test.go b/test/integration/platform_test.go index e4f28d50..c4e74c7c 100644 --- a/test/integration/platform_test.go +++ b/test/integration/platform_test.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "runtime" "strings" "testing" @@ -133,6 +134,12 @@ func TestDigestThatNarrowsToOnePlatform(t *testing.T) { } } +func TestDefaultPlatformWithOciRegistry(t *testing.T) { + img, err := stereoscope.GetImageFromSource(context.TODO(), "busybox:1.31", image.OciRegistrySource) + require.NoError(t, err) + assertArchAndOs(t, img, runtime.GOARCH, "linux") +} + func assertArchAndOs(t *testing.T, img *image.Image, architecture string, os string) { type platform struct { Architecture string `json:"architecture"` From c0270c3b3e0498987bfd1ab2a4af348dccb3a6e2 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Fri, 9 Jun 2023 11:04:26 -0400 Subject: [PATCH 5/8] Clean up; switch os and arch in helper Signed-off-by: Will Murphy --- test/integration/platform_test.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/test/integration/platform_test.go b/test/integration/platform_test.go index c4e74c7c..429613ff 100644 --- a/test/integration/platform_test.go +++ b/test/integration/platform_test.go @@ -85,10 +85,7 @@ func TestPlatformSelection(t *testing.T) { tt.expectedErr(t, err) require.NotNil(t, img) - // TODO: decode image config and test - // assert.Equal(t, tt.os, img.Metadata.OS) - // assert.Equal(t, tt.architecture, img.Metadata.Architecture) - assertArchAndOs(t, img, tt.architecture, tt.os) + assertArchAndOs(t, img, tt.os, tt.architecture) found := false if img.Metadata.ManifestDigest == tt.expectedDigest { found = true @@ -107,7 +104,7 @@ func TestPlatformSelection(t *testing.T) { } func TestDigestThatNarrowsToOnePlatform(t *testing.T) { - // busybox:1.31 on linux/s390x + // This digest is busybox:1.31 on linux/s390x // Test assumes that the host running these tests _isn't_ linux/s390x, but the behavior // should be the same regardless. imageStrWithDigest := "busybox:1.31@sha256:91c15b1ba6f408a648be60f8c047ef79058f26fa640025f374281f31c8704387" @@ -128,8 +125,7 @@ func TestDigestThatNarrowsToOnePlatform(t *testing.T) { t.Run(tt.name, func(t *testing.T) { img, err := stereoscope.GetImageFromSource(context.TODO(), imageStrWithDigest, tt.source) assert.NoError(t, err) - // TODO: these tests are wrong - assertArchAndOs(t, img, "s390x", "linux") + assertArchAndOs(t, img, "linux", "s390x") }) } } @@ -137,10 +133,10 @@ func TestDigestThatNarrowsToOnePlatform(t *testing.T) { func TestDefaultPlatformWithOciRegistry(t *testing.T) { img, err := stereoscope.GetImageFromSource(context.TODO(), "busybox:1.31", image.OciRegistrySource) require.NoError(t, err) - assertArchAndOs(t, img, runtime.GOARCH, "linux") + assertArchAndOs(t, img, "linux", runtime.GOARCH) } -func assertArchAndOs(t *testing.T, img *image.Image, architecture string, os string) { +func assertArchAndOs(t *testing.T, img *image.Image, os string, architecture string) { type platform struct { Architecture string `json:"architecture"` Os string `json:"os"` From 98af961d7f9f0ccebb0a298acf024dbbb7cf4670 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Fri, 9 Jun 2023 14:18:21 -0400 Subject: [PATCH 6/8] Update digests to use image ID Previously, the test would loop over the RepoDigest field in the image manifest to prove that the expect digest was present. However, in some cases, the RepoDigests field can be empty. Therefore, just use the ID from the manfiest, since this seems consisent across image sources, and is always present. Signed-off-by: Will Murphy --- test/integration/platform_test.go | 36 ++++++++++++------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/test/integration/platform_test.go b/test/integration/platform_test.go index 429613ff..1206e62e 100644 --- a/test/integration/platform_test.go +++ b/test/integration/platform_test.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "runtime" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -16,6 +15,11 @@ import ( ) func TestPlatformSelection(t *testing.T) { + /* + All digests were obtained by: + $ docker image pull --platform $PLATFORM busybox:1.31 + $ docker image inspect busybox:1.31 | jq -r '.[0].Id' + */ imageName := "busybox:1.31" tests := []struct { source image.Source @@ -28,49 +32,49 @@ func TestPlatformSelection(t *testing.T) { source: image.OciRegistrySource, architecture: "arm64", os: "linux", - expectedDigest: "sha256:1ee006886991ad4689838d3a288e0dd3fd29b70e276622f16b67a8922831a853", // direct from repo manifest + expectedDigest: "sha256:19d689bc58fd64da6a46d46512ea965a12b6bfb5b030400e21bc0a04c4ff155e", }, { source: image.OciRegistrySource, architecture: "s390x", os: "linux", - expectedDigest: "sha256:91c15b1ba6f408a648be60f8c047ef79058f26fa640025f374281f31c8704387", // from generated manifest + expectedDigest: "sha256:5bf065699d2e6ddb8b5f7e30f02edc3cfe15d7400e7101b5b505d61fde01f84c", }, { source: image.OciRegistrySource, architecture: "amd64", os: "linux", - expectedDigest: "sha256:95cf004f559831017cdf4628aaf1bb30133677be8702a8c5f2994629f637a209", // direct from repo manifest + expectedDigest: "sha256:1c35c441208254cb7c3844ba95a96485388cef9ccc0646d562c7fc026e04c807", }, { source: image.DockerDaemonSource, architecture: "arm64", os: "linux", - expectedDigest: "sha256:dcd4bbdd7ea2360002c684968429a2105997c3ce5821e84bfc2703c5ec984971", // from generated manifest + expectedDigest: "sha256:19d689bc58fd64da6a46d46512ea965a12b6bfb5b030400e21bc0a04c4ff155e", }, { source: image.DockerDaemonSource, architecture: "amd64", os: "linux", - expectedDigest: "sha256:79d3cb76a5a8ba402af164ace87bd0f3e0759979f94caf7247745126359711da", // from generated manifest + expectedDigest: "sha256:1c35c441208254cb7c3844ba95a96485388cef9ccc0646d562c7fc026e04c807", }, { source: image.DockerDaemonSource, architecture: "s390x", os: "linux", - expectedDigest: "sha256:91c15b1ba6f408a648be60f8c047ef79058f26fa640025f374281f31c8704387", // from generated manifest + expectedDigest: "sha256:5bf065699d2e6ddb8b5f7e30f02edc3cfe15d7400e7101b5b505d61fde01f84c", }, { source: image.PodmanDaemonSource, architecture: "arm64", os: "linux", - expectedDigest: "sha256:dcd4bbdd7ea2360002c684968429a2105997c3ce5821e84bfc2703c5ec984971", // from generated manifest + expectedDigest: "sha256:19d689bc58fd64da6a46d46512ea965a12b6bfb5b030400e21bc0a04c4ff155e", }, { source: image.PodmanDaemonSource, architecture: "amd64", os: "linux", - expectedDigest: "sha256:79d3cb76a5a8ba402af164ace87bd0f3e0759979f94caf7247745126359711da", // from generated manifest + expectedDigest: "sha256:1c35c441208254cb7c3844ba95a96485388cef9ccc0646d562c7fc026e04c807", }, } @@ -86,19 +90,7 @@ func TestPlatformSelection(t *testing.T) { require.NotNil(t, img) assertArchAndOs(t, img, tt.os, tt.architecture) - found := false - if img.Metadata.ManifestDigest == tt.expectedDigest { - found = true - } - for _, d := range img.Metadata.RepoDigests { - if found { - break - } - if strings.Contains(d, tt.expectedDigest) { - found = true - } - } - assert.True(t, found, "could not find repo digest that matches the expected digest:\nfound manifest digest: %+v\nfound repo digests: %+v\nexpected digest: %+v", img.Metadata.ManifestDigest, img.Metadata.RepoDigests, tt.expectedDigest) + assert.Equal(t, tt.expectedDigest, img.Metadata.ID) }) } } From c84b09856409b2cbfe97ddd32dd5892a09a7e459 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Fri, 9 Jun 2023 14:31:05 -0400 Subject: [PATCH 7/8] Add comment to explain defaultPlatformIfNil Signed-off-by: Will Murphy --- client.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client.go b/client.go index ee3588fb..b184f530 100644 --- a/client.go +++ b/client.go @@ -153,6 +153,12 @@ func selectImageProvider(imgStr string, source image.Source, cfg config) (image. return provider, nil } +// defaultPlatformIfNil sets the platfrom to use the host's architecture +// if no platform was specified. The OCI registry provider uses "linux/amd64" +// as a hard-coded default platform, which has surprised customers +// running stereoscope on non-amd64 hosts. If platform is already +// set on the config, or the code can't generate a matching platform, +// do nothing. func defaultPlatformIfNil(cfg *config) { if cfg.Platform == nil { p, err := image.NewPlatform(fmt.Sprintf("linux/%s", runtime.GOARCH)) From fe7061c91050a7e05483af60143755324deb70d2 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Fri, 9 Jun 2023 14:34:29 -0400 Subject: [PATCH 8/8] Typo fix Signed-off-by: Will Murphy --- client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client.go b/client.go index b184f530..ea8ee736 100644 --- a/client.go +++ b/client.go @@ -153,7 +153,7 @@ func selectImageProvider(imgStr string, source image.Source, cfg config) (image. return provider, nil } -// defaultPlatformIfNil sets the platfrom to use the host's architecture +// defaultPlatformIfNil sets the platform to use the host's architecture // if no platform was specified. The OCI registry provider uses "linux/amd64" // as a hard-coded default platform, which has surprised customers // running stereoscope on non-amd64 hosts. If platform is already