diff options
author | Brent Baude <bbaude@redhat.com> | 2020-03-31 14:45:19 -0500 |
---|---|---|
committer | Brent Baude <bbaude@redhat.com> | 2020-04-01 15:56:26 -0500 |
commit | 043308198337941a8086113619d6341528c10cd0 (patch) | |
tree | 0d8ce52e6178e464ce5689c4695c42223aeeeae3 | |
parent | 0f357be5aeaa5dc651659cf0945a58780641e77d (diff) | |
download | podman-043308198337941a8086113619d6341528c10cd0.tar.gz podman-043308198337941a8086113619d6341528c10cd0.tar.bz2 podman-043308198337941a8086113619d6341528c10cd0.zip |
podmanv2 import
add the ability to import a container image from a container export
Signed-off-by: Brent Baude <bbaude@redhat.com>
-rw-r--r-- | cmd/podmanV2/images/import.go | 87 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/images.go | 2 | ||||
-rw-r--r-- | pkg/api/handlers/swagger.go | 2 | ||||
-rw-r--r-- | pkg/api/handlers/types.go | 4 | ||||
-rw-r--r-- | pkg/bindings/images/images.go | 12 | ||||
-rw-r--r-- | pkg/domain/entities/engine_image.go | 1 | ||||
-rw-r--r-- | pkg/domain/entities/images.go | 13 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images.go | 9 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/images.go | 17 |
9 files changed, 135 insertions, 12 deletions
diff --git a/cmd/podmanV2/images/import.go b/cmd/podmanV2/images/import.go new file mode 100644 index 000000000..09a15585f --- /dev/null +++ b/cmd/podmanV2/images/import.go @@ -0,0 +1,87 @@ +package images + +import ( + "context" + "fmt" + + "github.com/containers/libpod/cmd/podmanV2/parse" + "github.com/containers/libpod/cmd/podmanV2/registry" + "github.com/containers/libpod/pkg/domain/entities" + "github.com/hashicorp/go-multierror" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +var ( + importDescription = `Create a container image from the contents of the specified tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz). + + Note remote tar balls can be specified, via web address. + Optionally tag the image. You can specify the instructions using the --change option.` + importCommand = &cobra.Command{ + Use: "import [flags] PATH [REFERENCE]", + Short: "Import a tarball to create a filesystem image", + Long: importDescription, + RunE: importCon, + PersistentPreRunE: preRunE, + Example: `podman import http://example.com/ctr.tar url-image + cat ctr.tar | podman -q import --message "importing the ctr.tar tarball" - image-imported + cat ctr.tar | podman import -`, + } +) + +var ( + importOpts entities.ImageImportOptions +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: importCommand, + }) + + importCommand.SetHelpTemplate(registry.HelpTemplate()) + importCommand.SetUsageTemplate(registry.UsageTemplate()) + flags := importCommand.Flags() + flags.StringArrayVarP(&importOpts.Changes, "change", "c", []string{}, "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR") + flags.StringVarP(&importOpts.Message, "message", "m", "", "Set commit message for imported image") + flags.BoolVarP(&importOpts.Quiet, "quiet", "q", false, "Suppress output") +} + +func importCon(cmd *cobra.Command, args []string) error { + var ( + source string + reference string + ) + switch len(args) { + case 0: + return errors.Errorf("need to give the path to the tarball, or must specify a tarball of '-' for stdin") + case 1: + source = args[0] + case 2: + source = args[0] + // TODO when save is merged, we need to process reference + // like it is done in there or we end up with docker.io prepends + // instead of the localhost ones + reference = args[1] + default: + return errors.Errorf("too many arguments. Usage TARBALL [REFERENCE]") + } + errFileName := parse.ValidateFileName(source) + errURL := parse.ValidURL(source) + if errURL == nil { + importOpts.SourceIsURL = true + } + if errFileName != nil && errURL != nil { + return multierror.Append(errFileName, errURL) + } + + importOpts.Source = source + importOpts.Reference = reference + + response, err := registry.ImageEngine().Import(context.Background(), importOpts) + if err != nil { + return err + } + fmt.Println(response.Id) + return nil +} diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index 19c6102be..d4fd77cd7 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -300,7 +300,7 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) { return } - utils.WriteResponse(w, http.StatusOK, handlers.LibpodImagesImportReport{ID: importedImage}) + utils.WriteResponse(w, http.StatusOK, entities.ImageImportReport{Id: importedImage}) } // ImagesPull is the v2 libpod endpoint for pulling images. Note that the diff --git a/pkg/api/handlers/swagger.go b/pkg/api/handlers/swagger.go index 12de3a3bd..33a9fdd58 100644 --- a/pkg/api/handlers/swagger.go +++ b/pkg/api/handlers/swagger.go @@ -38,7 +38,7 @@ type swagLibpodImagesLoadResponse struct { // swagger:response DocsLibpodImagesImportResponse type swagLibpodImagesImportResponse struct { // in:body - Body LibpodImagesImportReport + Body entities.ImageImportReport } // Pull response diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index 89a571e67..496512f2e 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -38,10 +38,6 @@ type LibpodImagesLoadReport struct { ID string `json:"id"` } -type LibpodImagesImportReport struct { - ID string `json:"id"` -} - type LibpodImagesPullReport struct { ID string `json:"id"` } diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go index 6c739494b..470ce546c 100644 --- a/pkg/bindings/images/images.go +++ b/pkg/bindings/images/images.go @@ -217,14 +217,14 @@ func Build(nameOrId string) {} // Imports adds the given image to the local image store. This can be done by file and the given reader // or via the url parameter. Additional metadata can be associated with the image by using the changes and // message parameters. The image can also be tagged given a reference. One of url OR r must be provided. -func Import(ctx context.Context, changes []string, message, reference, u *string, r io.Reader) (string, error) { - var id handlers.IDResponse +func Import(ctx context.Context, changes []string, message, reference, u *string, r io.Reader) (*entities.ImageImportReport, error) { + var report entities.ImageImportReport if r != nil && u != nil { - return "", errors.New("url and r parameters cannot be used together") + return nil, errors.New("url and r parameters cannot be used together") } conn, err := bindings.GetClient(ctx) if err != nil { - return "", err + return nil, err } params := url.Values{} for _, change := range changes { @@ -241,9 +241,9 @@ func Import(ctx context.Context, changes []string, message, reference, u *string } response, err := conn.DoRequest(r, http.MethodPost, "/images/import", params) if err != nil { - return "", err + return nil, err } - return id.ID, response.Process(&id) + return &report, response.Process(&report) } // Pull is the binding for libpod's v2 endpoints for pulling images. Note that diff --git a/pkg/domain/entities/engine_image.go b/pkg/domain/entities/engine_image.go index 4cc2a67b9..ac856c05f 100644 --- a/pkg/domain/entities/engine_image.go +++ b/pkg/domain/entities/engine_image.go @@ -15,4 +15,5 @@ type ImageEngine interface { Tag(ctx context.Context, nameOrId string, tags []string, options ImageTagOptions) error Untag(ctx context.Context, nameOrId string, tags []string, options ImageUntagOptions) error Load(ctx context.Context, opts ImageLoadOptions) (*ImageLoadReport, error) + Import(ctx context.Context, opts ImageImportOptions) (*ImageImportReport, error) } diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index a6c7baebd..d136f42fd 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -184,3 +184,16 @@ type ImageLoadOptions struct { type ImageLoadReport struct { Name string } + +type ImageImportOptions struct { + Changes []string + Message string + Quiet bool + Reference string + Source string + SourceIsURL bool +} + +type ImageImportReport struct { + Id string +} diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index c3a2bb288..f8c63730c 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -303,6 +303,7 @@ func (ir *ImageEngine) Tag(ctx context.Context, nameOrId string, tags []string, } return nil } + func (ir *ImageEngine) Untag(ctx context.Context, nameOrId string, tags []string, options entities.ImageUntagOptions) error { newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId) if err != nil { @@ -336,3 +337,11 @@ func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions) } return &entities.ImageLoadReport{Name: name}, nil } + +func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOptions) (*entities.ImageImportReport, error) { + id, err := ir.Libpod.Import(ctx, opts.Source, opts.Reference, opts.Changes, opts.Message, opts.Quiet) + if err != nil { + return nil, err + } + return &entities.ImageImportReport{Id: id}, nil +} diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index a4a0fccaf..155f5e4bd 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -167,3 +167,20 @@ func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions) defer f.Close() return images.Load(ir.ClientCxt, f, &opts.Name) } + +func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOptions) (*entities.ImageImportReport, error) { + var ( + err error + sourceURL *string + f *os.File + ) + if opts.SourceIsURL { + sourceURL = &opts.Source + } else { + f, err = os.Open(opts.Source) + if err != nil { + return nil, err + } + } + return images.Import(ir.ClientCxt, opts.Changes, &opts.Message, &opts.Reference, sourceURL, f) +} |