Add platform selection (#866)

This commit is contained in:
Alex Goodman
2022-03-04 22:41:38 +00:00
committed by GitHub
parent 4af32c5bee
commit a86dd3704e
16 changed files with 99 additions and 40 deletions
+6
View File
@@ -15,6 +15,9 @@ type ImageMetadata struct {
RawManifest []byte `json:"manifest"`
RawConfig []byte `json:"config"`
RepoDigests []string `json:"repoDigests"`
Architecture string `json:"architecture"`
Variant string `json:"architectureVariant,omitempty"`
OS string `json:"os"`
}
// LayerMetadata represents all static metadata that defines what a container image layer is.
@@ -42,6 +45,9 @@ func NewImageMetadata(img *image.Image, userInput string) ImageMetadata {
RawConfig: img.Metadata.RawConfig,
RawManifest: img.Metadata.RawManifest,
RepoDigests: img.Metadata.RepoDigests,
Architecture: img.Metadata.Architecture,
Variant: img.Metadata.Variant,
OS: img.Metadata.OS,
}
// populate image metadata
+22 -6
View File
@@ -40,12 +40,13 @@ type Input struct {
Scheme Scheme
ImageSource image.Source
Location string
Platform string
autoDetectAvailableImageSources bool
}
// ParseInput generates a source Input that can be used as an argument to generate a new source
// from specific providers including a registry.
func ParseInput(userInput string, detectAvailableImageSources bool) (*Input, error) {
func ParseInput(userInput string, platform string, detectAvailableImageSources bool) (*Input, error) {
fs := afero.NewOsFs()
scheme, source, location, err := DetectScheme(fs, image.DetectSource, userInput)
if err != nil {
@@ -71,12 +72,17 @@ func ParseInput(userInput string, detectAvailableImageSources bool) (*Input, err
}
}
if scheme != ImageScheme && platform != "" {
return nil, fmt.Errorf("cannot specify a platform for a non-image source")
}
// collect user input for downstream consumption
return &Input{
UserInput: userInput,
Scheme: scheme,
ImageSource: source,
Location: location,
Platform: platform,
autoDetectAvailableImageSources: detectAvailableImageSources,
}, nil
}
@@ -147,10 +153,19 @@ func getImageWithRetryStrategy(in Input, registryOptions *image.RegistryOptions)
opts = append(opts, stereoscope.WithRegistryOptions(*registryOptions))
}
if in.Platform != "" {
opts = append(opts, stereoscope.WithPlatform(in.Platform))
}
img, err := stereoscope.GetImageFromSource(ctx, in.Location, in.ImageSource, opts...)
cleanup := func() {
if err := img.Cleanup(); err != nil {
log.Warnf("unable to cleanup image=%q: %w", in.UserInput, err)
}
}
if err == nil {
// Success on the first try!
return img, stereoscope.Cleanup, nil
return img, cleanup, nil
}
scheme := parseScheme(in.UserInput)
@@ -180,11 +195,12 @@ func getImageWithRetryStrategy(in Input, registryOptions *image.RegistryOptions)
in.ImageSource = image.DetermineDefaultImagePullSource(in.UserInput)
}
img, err = stereoscope.GetImageFromSource(ctx, in.UserInput, in.ImageSource, opts...)
if err != nil {
return nil, nil, err
cleanup = func() {
if err := img.Cleanup(); err != nil {
log.Warnf("unable to cleanup image=%q: %w", in.UserInput, err)
}
}
return img, stereoscope.Cleanup, nil
return img, cleanup, err
}
func generateDirectorySource(fs afero.Fs, location string) (*Source, func(), error) {
+18 -6
View File
@@ -26,22 +26,34 @@ func TestParseInput(t *testing.T) {
tests := []struct {
name string
input string
platform string
expected Scheme
errFn require.ErrorAssertionFunc
}{
{
name: "ParseInput parses a file input",
input: "test-fixtures/image-simple/file-1.txt",
expected: FileScheme,
},
{
name: "errors out when using platform for non-image scheme",
input: "test-fixtures/image-simple/file-1.txt",
platform: "arm64",
errFn: require.Error,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
sourceInput, err := ParseInput(test.input, true)
if err != nil {
t.Errorf("failed to ParseInput")
if test.errFn == nil {
test.errFn = require.NoError
}
sourceInput, err := ParseInput(test.input, test.platform, true)
test.errFn(t, err)
if test.expected != "" {
require.NotNil(t, sourceInput)
assert.Equal(t, sourceInput.Scheme, test.expected)
}
assert.Equal(t, sourceInput.Scheme, test.expected)
})
}
}
@@ -452,7 +464,7 @@ func TestDirectoryExclusions(t *testing.T) {
registryOpts := &image.RegistryOptions{}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
sourceInput, err := ParseInput("dir:"+test.input, false)
sourceInput, err := ParseInput("dir:"+test.input, "", false)
require.NoError(t, err)
src, fn, err := New(*sourceInput, registryOpts, test.exclusions)
defer fn()
@@ -546,7 +558,7 @@ func TestImageExclusions(t *testing.T) {
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
archiveLocation := imagetest.PrepareFixtureImage(t, "docker-archive", test.input)
sourceInput, err := ParseInput(archiveLocation, false)
sourceInput, err := ParseInput(archiveLocation, "", false)
require.NoError(t, err)
src, fn, err := New(*sourceInput, registryOpts, test.exclusions)
defer fn()