From eedce31eb4aa8c0678c24cdf907ebd971ce02233 Mon Sep 17 00:00:00 2001 From: Aditya R Date: Tue, 22 Mar 2022 17:16:52 +0530 Subject: [PATCH] import: allow users to set os, arch and variant of imports Allows users to set `--os` , `--arch` and `--variant` of the image created from the custom import. Following is useful when user is already aware of the values which are correct for their generated rootfs Signed-off-by: Aditya R --- cmd/podman/images/import.go | 12 ++++++ docs/source/markdown/podman-import.1.md | 12 ++++++ pkg/api/handlers/libpod/images.go | 22 ++++++---- pkg/bindings/images/types.go | 6 +++ pkg/bindings/images/types_import_options.go | 45 +++++++++++++++++++++ pkg/domain/entities/images.go | 1 + pkg/domain/infra/abi/images.go | 3 +- pkg/domain/infra/tunnel/images.go | 1 + test/e2e/import_test.go | 20 +++++++++ 9 files changed, 113 insertions(+), 9 deletions(-) diff --git a/cmd/podman/images/import.go b/cmd/podman/images/import.go index a7416e298ca6..47f2a798d954 100644 --- a/cmd/podman/images/import.go +++ b/cmd/podman/images/import.go @@ -76,6 +76,18 @@ func importFlags(cmd *cobra.Command) { flags.StringVarP(&importOpts.Message, messageFlagName, "m", "", "Set commit message for imported image") _ = cmd.RegisterFlagCompletionFunc(messageFlagName, completion.AutocompleteNone) + osFlagName := "os" + flags.StringVar(&importOpts.OS, osFlagName, "", "Set the OS of the imported image") + _ = cmd.RegisterFlagCompletionFunc(osFlagName, completion.AutocompleteNone) + + archFlagName := "arch" + flags.StringVar(&importOpts.Architecture, archFlagName, "", "Set the architecture of the imported image") + _ = cmd.RegisterFlagCompletionFunc(archFlagName, completion.AutocompleteNone) + + variantFlagName := "variant" + flags.StringVar(&importOpts.Variant, variantFlagName, "", "Set the variant of the imported image") + _ = cmd.RegisterFlagCompletionFunc(variantFlagName, completion.AutocompleteNone) + flags.BoolVarP(&importOpts.Quiet, "quiet", "q", false, "Suppress output") if !registry.IsRemote() { flags.StringVar(&importOpts.SignaturePolicy, "signature-policy", "", "Path to a signature-policy file") diff --git a/docs/source/markdown/podman-import.1.md b/docs/source/markdown/podman-import.1.md index 462e9eacf4f0..a79b6cfdd229 100644 --- a/docs/source/markdown/podman-import.1.md +++ b/docs/source/markdown/podman-import.1.md @@ -19,6 +19,10 @@ Note: `:` is a restricted character and cannot be part of the file name. ## OPTIONS +#### **--arch** + +Set architecture of the imported image. + #### **--change**=*instruction*, **-c** Apply the following possible instructions to the created image: @@ -30,10 +34,18 @@ Can be set multiple times Set commit message for imported image +#### **--os** + +Set OS of the imported image. + #### **--quiet**, **-q** Shows progress on the import +#### **--variant** + +Set variant of the imported image. + **--verbose** Print additional debugging information diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index d59a8334226d..cddf4c205bb8 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -367,10 +367,13 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder) query := struct { - Changes []string `schema:"changes"` - Message string `schema:"message"` - Reference string `schema:"reference"` - URL string `schema:"URL"` + Changes []string `schema:"changes"` + Message string `schema:"message"` + Reference string `schema:"reference"` + URL string `schema:"URL"` + OS string `schema:"OS"` + Architecture string `schema:"Architecture"` + Variant string `schema:"Variant"` }{ // Add defaults here once needed. } @@ -402,10 +405,13 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) { imageEngine := abi.ImageEngine{Libpod: runtime} importOptions := entities.ImageImportOptions{ - Changes: query.Changes, - Message: query.Message, - Reference: query.Reference, - Source: source, + Changes: query.Changes, + Message: query.Message, + Reference: query.Reference, + OS: query.OS, + Architecture: query.Architecture, + Variant: query.Variant, + Source: source, } report, err := imageEngine.Import(r.Context(), importOptions) if err != nil { diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go index 163365924def..75cb38a0ad91 100644 --- a/pkg/bindings/images/types.go +++ b/pkg/bindings/images/types.go @@ -103,6 +103,12 @@ type ImportOptions struct { Reference *string // Url to option image to import. Cannot be used with the reader URL *string + // OS for the imported image + OS *string + // Architecture for the imported image + Architecture *string + // Variant for the imported image + Variant *string } //go:generate go run ../generator/generator.go PushOptions diff --git a/pkg/bindings/images/types_import_options.go b/pkg/bindings/images/types_import_options.go index ea66fa312f4f..f958fe8b480b 100644 --- a/pkg/bindings/images/types_import_options.go +++ b/pkg/bindings/images/types_import_options.go @@ -76,3 +76,48 @@ func (o *ImportOptions) GetURL() string { } return *o.URL } + +// WithOS set field OS to given value +func (o *ImportOptions) WithOS(value string) *ImportOptions { + o.OS = &value + return o +} + +// GetOS returns value of field OS +func (o *ImportOptions) GetOS() string { + if o.OS == nil { + var z string + return z + } + return *o.OS +} + +// WithArchitecture set field Architecture to given value +func (o *ImportOptions) WithArchitecture(value string) *ImportOptions { + o.Architecture = &value + return o +} + +// GetArchitecture returns value of field Architecture +func (o *ImportOptions) GetArchitecture() string { + if o.Architecture == nil { + var z string + return z + } + return *o.Architecture +} + +// WithVariant set field Variant to given value +func (o *ImportOptions) WithVariant(value string) *ImportOptions { + o.Variant = &value + return o +} + +// GetVariant returns value of field Variant +func (o *ImportOptions) GetVariant() string { + if o.Variant == nil { + var z string + return z + } + return *o.Variant +} diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index 93334fc6a1a4..7081c5d25a58 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -279,6 +279,7 @@ type ImageLoadReport struct { type ImageImportOptions struct { Architecture string + Variant string Changes []string Message string OS string diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 0b07901d46be..08d65225625a 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -445,7 +445,8 @@ func (ir *ImageEngine) Import(ctx context.Context, options entities.ImageImportO importOptions.Tag = options.Reference importOptions.SignaturePolicyPath = options.SignaturePolicy importOptions.OS = options.OS - importOptions.Architecture = options.Architecture + importOptions.Arch = options.Architecture + importOptions.Variant = options.Variant if !options.Quiet { importOptions.Writer = os.Stderr diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index 62eacb19f0f5..18e10e8dd645 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -230,6 +230,7 @@ func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOpti f *os.File ) options := new(images.ImportOptions).WithChanges(opts.Changes).WithMessage(opts.Message).WithReference(opts.Reference) + options.WithOS(opts.OS).WithArchitecture(opts.Architecture).WithVariant(opts.Variant) if opts.SourceIsURL { options.WithURL(opts.Source) } else { diff --git a/test/e2e/import_test.go b/test/e2e/import_test.go index 884eae18e1ec..f62df23d9d38 100644 --- a/test/e2e/import_test.go +++ b/test/e2e/import_test.go @@ -52,6 +52,26 @@ var _ = Describe("Podman import", func() { Expect(results).Should(Exit(0)) }) + It("podman import with custom os, arch and variant", func() { + outfile := filepath.Join(podmanTest.TempDir, "container.tar") + _, ec, cid := podmanTest.RunLsContainer("") + Expect(ec).To(Equal(0)) + + export := podmanTest.Podman([]string{"export", "-o", outfile, cid}) + export.WaitWithDefaultTimeout() + Expect(export).Should(Exit(0)) + + importImage := podmanTest.Podman([]string{"import", "--os", "testos", "--arch", "testarch", outfile, "foobar.com/imported-image:latest"}) + importImage.WaitWithDefaultTimeout() + Expect(importImage).Should(Exit(0)) + + results := podmanTest.Podman([]string{"inspect", "--type", "image", "foobar.com/imported-image:latest"}) + results.WaitWithDefaultTimeout() + Expect(results).Should(Exit(0)) + Expect(results.OutputToString()).To(ContainSubstring("testos")) + Expect(results.OutputToString()).To(ContainSubstring("testarch")) + }) + It("podman import without reference", func() { outfile := filepath.Join(podmanTest.TempDir, "container.tar") _, ec, cid := podmanTest.RunLsContainer("")