mirror of
https://github.com/containers/podman.git
synced 2025-09-10 12:32:21 +08:00
@ -1,2 +1,2 @@
|
|||||||
all:
|
all:
|
||||||
GO111MODULE=off go build -tags 'ABISupport'
|
GO111MODULE=off go build -tags 'ABISupport systemd'
|
||||||
|
61
cmd/podmanV2/images/load.go
Normal file
61
cmd/podmanV2/images/load.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package images
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/containers/libpod/cmd/podmanV2/registry"
|
||||||
|
"github.com/containers/libpod/libpod/image"
|
||||||
|
"github.com/containers/libpod/pkg/domain/entities"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
loadDescription = "Loads an image from a locally stored archive (tar file) into container storage."
|
||||||
|
loadCommand = &cobra.Command{
|
||||||
|
Use: "load [flags] [NAME[:TAG]]",
|
||||||
|
Short: "Load an image from container archive",
|
||||||
|
Long: loadDescription,
|
||||||
|
RunE: load,
|
||||||
|
Args: cobra.MaximumNArgs(1),
|
||||||
|
PersistentPreRunE: preRunE,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
loadOpts entities.ImageLoadOptions
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||||
|
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
||||||
|
Command: loadCommand,
|
||||||
|
})
|
||||||
|
|
||||||
|
loadCommand.SetHelpTemplate(registry.HelpTemplate())
|
||||||
|
loadCommand.SetUsageTemplate(registry.UsageTemplate())
|
||||||
|
flags := loadCommand.Flags()
|
||||||
|
flags.StringVarP(&loadOpts.Input, "input", "i", "", "Read from specified archive file (default: stdin)")
|
||||||
|
flags.BoolVarP(&loadOpts.Quiet, "quiet", "q", false, "Suppress the output")
|
||||||
|
flags.StringVar(&loadOpts.SignaturePolicy, "signature-policy", "", "Pathname of signature policy file")
|
||||||
|
if registry.IsRemote() {
|
||||||
|
_ = flags.MarkHidden("signature-policy")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func load(cmd *cobra.Command, args []string) error {
|
||||||
|
if len(args) > 0 {
|
||||||
|
repo, err := image.NormalizedTag(args[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
loadOpts.Name = repo.Name()
|
||||||
|
}
|
||||||
|
response, err := registry.ImageEngine().Load(context.Background(), loadOpts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println("Loaded image: " + response.Name)
|
||||||
|
return nil
|
||||||
|
}
|
@ -15,6 +15,7 @@ import (
|
|||||||
_ "github.com/containers/libpod/cmd/podmanV2/volumes"
|
_ "github.com/containers/libpod/cmd/podmanV2/volumes"
|
||||||
"github.com/containers/libpod/libpod"
|
"github.com/containers/libpod/libpod"
|
||||||
"github.com/containers/libpod/pkg/domain/entities"
|
"github.com/containers/libpod/pkg/domain/entities"
|
||||||
|
"github.com/containers/storage/pkg/reexec"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -45,6 +46,11 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
if reexec.Init() {
|
||||||
|
// We were invoked with a different argv[0] indicating that we
|
||||||
|
// had a specific job to do as a subprocess, and it's done.
|
||||||
|
return
|
||||||
|
}
|
||||||
for _, c := range registry.Commands {
|
for _, c := range registry.Commands {
|
||||||
if Contains(registry.EngineOptions.EngineMode, c.Mode) {
|
if Contains(registry.EngineOptions.EngineMode, c.Mode) {
|
||||||
parent := rootCmd
|
parent := rootCmd
|
||||||
|
@ -512,8 +512,8 @@ func getImageDigest(ctx context.Context, src types.ImageReference, sc *types.Sys
|
|||||||
return "@" + imageDigest.Hex(), nil
|
return "@" + imageDigest.Hex(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalizedTag returns the canonical version of tag for use in Image.Names()
|
// NormalizedTag returns the canonical version of tag for use in Image.Names()
|
||||||
func normalizedTag(tag string) (reference.Named, error) {
|
func NormalizedTag(tag string) (reference.Named, error) {
|
||||||
decomposedTag, err := decompose(tag)
|
decomposedTag, err := decompose(tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -541,7 +541,7 @@ func (i *Image) TagImage(tag string) error {
|
|||||||
if err := i.reloadImage(); err != nil {
|
if err := i.reloadImage(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ref, err := normalizedTag(tag)
|
ref, err := NormalizedTag(tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -292,7 +292,7 @@ func TestNormalizedTag(t *testing.T) {
|
|||||||
{"ns/busybox:latest", "localhost/ns/busybox:latest"}, // Unqualified with a dot-less namespace
|
{"ns/busybox:latest", "localhost/ns/busybox:latest"}, // Unqualified with a dot-less namespace
|
||||||
{"docker.io/busybox:latest", "docker.io/library/busybox:latest"}, // docker.io without /library/
|
{"docker.io/busybox:latest", "docker.io/library/busybox:latest"}, // docker.io without /library/
|
||||||
} {
|
} {
|
||||||
res, err := normalizedTag(c.input)
|
res, err := NormalizedTag(c.input)
|
||||||
if c.expected == "" {
|
if c.expected == "" {
|
||||||
assert.Error(t, err, c.input)
|
assert.Error(t, err, c.input)
|
||||||
} else {
|
} else {
|
||||||
|
@ -254,7 +254,7 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
utils.WriteResponse(w, http.StatusOK, handlers.LibpodImagesLoadReport{ID: loadedImage})
|
utils.WriteResponse(w, http.StatusOK, entities.ImageLoadReport{Name: loadedImage})
|
||||||
}
|
}
|
||||||
|
|
||||||
func ImagesImport(w http.ResponseWriter, r *http.Request) {
|
func ImagesImport(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -31,7 +31,7 @@ type swagImageInspect struct {
|
|||||||
// swagger:response DocsLibpodImagesLoadResponse
|
// swagger:response DocsLibpodImagesLoadResponse
|
||||||
type swagLibpodImagesLoadResponse struct {
|
type swagLibpodImagesLoadResponse struct {
|
||||||
// in:body
|
// in:body
|
||||||
Body []LibpodImagesLoadReport
|
Body entities.ImageLoadReport
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import response
|
// Import response
|
||||||
|
@ -91,11 +91,11 @@ func History(ctx context.Context, nameOrID string) ([]*handlers.HistoryResponse,
|
|||||||
return history, response.Process(&history)
|
return history, response.Process(&history)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Load(ctx context.Context, r io.Reader, name *string) (string, error) {
|
func Load(ctx context.Context, r io.Reader, name *string) (*entities.ImageLoadReport, error) {
|
||||||
var id handlers.IDResponse
|
var report entities.ImageLoadReport
|
||||||
conn, err := bindings.GetClient(ctx)
|
conn, err := bindings.GetClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
if name != nil {
|
if name != nil {
|
||||||
@ -103,9 +103,9 @@ func Load(ctx context.Context, r io.Reader, name *string) (string, error) {
|
|||||||
}
|
}
|
||||||
response, err := conn.DoRequest(r, http.MethodPost, "/images/load", params)
|
response, err := conn.DoRequest(r, http.MethodPost, "/images/load", params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
return id.ID, response.Process(&id)
|
return &report, response.Process(&report)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove deletes an image from local storage. The optional force parameter will forcibly remove
|
// Remove deletes an image from local storage. The optional force parameter will forcibly remove
|
||||||
|
@ -219,7 +219,7 @@ var _ = Describe("Podman images", func() {
|
|||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
names, err := images.Load(bt.conn, f, nil)
|
names, err := images.Load(bt.conn, f, nil)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(names).To(Equal(alpine.name))
|
Expect(names.Name).To(Equal(alpine.name))
|
||||||
exists, err = images.Exists(bt.conn, alpine.name)
|
exists, err = images.Exists(bt.conn, alpine.name)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(exists).To(BeTrue())
|
Expect(exists).To(BeTrue())
|
||||||
@ -235,7 +235,7 @@ var _ = Describe("Podman images", func() {
|
|||||||
newName := "quay.io/newname:fizzle"
|
newName := "quay.io/newname:fizzle"
|
||||||
names, err = images.Load(bt.conn, f, &newName)
|
names, err = images.Load(bt.conn, f, &newName)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(names).To(Equal(alpine.name))
|
Expect(names.Name).To(Equal(alpine.name))
|
||||||
exists, err = images.Exists(bt.conn, newName)
|
exists, err = images.Exists(bt.conn, newName)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(exists).To(BeTrue())
|
Expect(exists).To(BeTrue())
|
||||||
|
@ -14,4 +14,5 @@ type ImageEngine interface {
|
|||||||
Pull(ctx context.Context, rawImage string, opts ImagePullOptions) (*ImagePullReport, error)
|
Pull(ctx context.Context, rawImage string, opts ImagePullOptions) (*ImagePullReport, error)
|
||||||
Tag(ctx context.Context, nameOrId string, tags []string, options ImageTagOptions) error
|
Tag(ctx context.Context, nameOrId string, tags []string, options ImageTagOptions) error
|
||||||
Untag(ctx context.Context, nameOrId string, tags []string, options ImageUntagOptions) error
|
Untag(ctx context.Context, nameOrId string, tags []string, options ImageUntagOptions) error
|
||||||
|
Load(ctx context.Context, opts ImageLoadOptions) (*ImageLoadReport, error)
|
||||||
}
|
}
|
||||||
|
@ -172,3 +172,15 @@ type ImageInspectReport struct {
|
|||||||
Images []*ImageData
|
Images []*ImageData
|
||||||
Errors map[string]error
|
Errors map[string]error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ImageLoadOptions struct {
|
||||||
|
Name string
|
||||||
|
Tag string
|
||||||
|
Input string
|
||||||
|
Quiet bool
|
||||||
|
SignaturePolicy string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageLoadReport struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
@ -315,3 +315,24 @@ func (ir *ImageEngine) Untag(ctx context.Context, nameOrId string, tags []string
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions) (*entities.ImageLoadReport, error) {
|
||||||
|
var (
|
||||||
|
writer io.Writer
|
||||||
|
)
|
||||||
|
if !opts.Quiet {
|
||||||
|
writer = os.Stderr
|
||||||
|
}
|
||||||
|
name, err := ir.Libpod.LoadImage(ctx, opts.Name, opts.Input, writer, opts.SignaturePolicy)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "image loaded but no additional tags were created")
|
||||||
|
}
|
||||||
|
if err := newImage.TagImage(opts.Name); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error adding %q to image %q", opts.Name, newImage.InputName)
|
||||||
|
}
|
||||||
|
return &entities.ImageLoadReport{Name: name}, nil
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ package tunnel
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/containers/image/v5/docker/reference"
|
"github.com/containers/image/v5/docker/reference"
|
||||||
images "github.com/containers/libpod/pkg/bindings/images"
|
images "github.com/containers/libpod/pkg/bindings/images"
|
||||||
@ -157,3 +158,12 @@ func (ir *ImageEngine) Inspect(_ context.Context, names []string, opts entities.
|
|||||||
}
|
}
|
||||||
return &report, nil
|
return &report, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions) (*entities.ImageLoadReport, error) {
|
||||||
|
f, err := os.Open(opts.Input)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
return images.Load(ir.ClientCxt, f, &opts.Name)
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user