summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrent Baude <bbaude@redhat.com>2020-03-31 14:45:19 -0500
committerBrent Baude <bbaude@redhat.com>2020-04-01 15:56:26 -0500
commit043308198337941a8086113619d6341528c10cd0 (patch)
tree0d8ce52e6178e464ce5689c4695c42223aeeeae3
parent0f357be5aeaa5dc651659cf0945a58780641e77d (diff)
downloadpodman-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.go87
-rw-r--r--pkg/api/handlers/libpod/images.go2
-rw-r--r--pkg/api/handlers/swagger.go2
-rw-r--r--pkg/api/handlers/types.go4
-rw-r--r--pkg/bindings/images/images.go12
-rw-r--r--pkg/domain/entities/engine_image.go1
-rw-r--r--pkg/domain/entities/images.go13
-rw-r--r--pkg/domain/infra/abi/images.go9
-rw-r--r--pkg/domain/infra/tunnel/images.go17
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)
+}