podmanv2 load

enable podman load for v2

add reexec into main

add systemd build flag to v2 makefile

Signed-off-by: Brent Baude <bbaude@redhat.com>
This commit is contained in:
Brent Baude 2020-03-31 12:59:08 -05:00
parent d534e52427
commit 8500ce6b9a
13 changed files with 125 additions and 14 deletions

View file

@ -1,2 +1,2 @@
all:
GO111MODULE=off go build -tags 'ABISupport'
GO111MODULE=off go build -tags 'ABISupport systemd'

View 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
}

View file

@ -15,6 +15,7 @@ import (
_ "github.com/containers/libpod/cmd/podmanV2/volumes"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/storage/pkg/reexec"
"github.com/sirupsen/logrus"
)
@ -45,6 +46,11 @@ func init() {
}
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 {
if Contains(registry.EngineOptions.EngineMode, c.Mode) {
parent := rootCmd

View file

@ -512,8 +512,8 @@ func getImageDigest(ctx context.Context, src types.ImageReference, sc *types.Sys
return "@" + imageDigest.Hex(), nil
}
// normalizedTag returns the canonical version of tag for use in Image.Names()
func normalizedTag(tag string) (reference.Named, error) {
// NormalizedTag returns the canonical version of tag for use in Image.Names()
func NormalizedTag(tag string) (reference.Named, error) {
decomposedTag, err := decompose(tag)
if err != nil {
return nil, err
@ -541,7 +541,7 @@ func (i *Image) TagImage(tag string) error {
if err := i.reloadImage(); err != nil {
return err
}
ref, err := normalizedTag(tag)
ref, err := NormalizedTag(tag)
if err != nil {
return err
}

View file

@ -292,7 +292,7 @@ func TestNormalizedTag(t *testing.T) {
{"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/
} {
res, err := normalizedTag(c.input)
res, err := NormalizedTag(c.input)
if c.expected == "" {
assert.Error(t, err, c.input)
} else {

View file

@ -254,7 +254,7 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) {
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) {

View file

@ -31,7 +31,7 @@ type swagImageInspect struct {
// swagger:response DocsLibpodImagesLoadResponse
type swagLibpodImagesLoadResponse struct {
// in:body
Body []LibpodImagesLoadReport
Body entities.ImageLoadReport
}
// Import response

View file

@ -91,11 +91,11 @@ func History(ctx context.Context, nameOrID string) ([]*handlers.HistoryResponse,
return history, response.Process(&history)
}
func Load(ctx context.Context, r io.Reader, name *string) (string, error) {
var id handlers.IDResponse
func Load(ctx context.Context, r io.Reader, name *string) (*entities.ImageLoadReport, error) {
var report entities.ImageLoadReport
conn, err := bindings.GetClient(ctx)
if err != nil {
return "", err
return nil, err
}
params := url.Values{}
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)
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

View file

@ -219,7 +219,7 @@ var _ = Describe("Podman images", func() {
Expect(err).To(BeNil())
names, err := images.Load(bt.conn, f, nil)
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)
Expect(err).To(BeNil())
Expect(exists).To(BeTrue())
@ -235,7 +235,7 @@ var _ = Describe("Podman images", func() {
newName := "quay.io/newname:fizzle"
names, err = images.Load(bt.conn, f, &newName)
Expect(err).To(BeNil())
Expect(names).To(Equal(alpine.name))
Expect(names.Name).To(Equal(alpine.name))
exists, err = images.Exists(bt.conn, newName)
Expect(err).To(BeNil())
Expect(exists).To(BeTrue())

View file

@ -14,4 +14,5 @@ type ImageEngine interface {
Pull(ctx context.Context, rawImage string, opts ImagePullOptions) (*ImagePullReport, error)
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)
}

View file

@ -172,3 +172,15 @@ type ImageInspectReport struct {
Images []*ImageData
Errors map[string]error
}
type ImageLoadOptions struct {
Name string
Tag string
Input string
Quiet bool
SignaturePolicy string
}
type ImageLoadReport struct {
Name string
}

View file

@ -315,3 +315,24 @@ func (ir *ImageEngine) Untag(ctx context.Context, nameOrId string, tags []string
}
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
}

View file

@ -2,6 +2,7 @@ package tunnel
import (
"context"
"os"
"github.com/containers/image/v5/docker/reference"
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
}
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)
}