diff options
Diffstat (limited to 'pkg/domain')
-rw-r--r-- | pkg/domain/entities/engine_image.go | 1 | ||||
-rw-r--r-- | pkg/domain/entities/images.go | 4 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images.go | 65 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/images.go | 5 |
4 files changed, 75 insertions, 0 deletions
diff --git a/pkg/domain/entities/engine_image.go b/pkg/domain/entities/engine_image.go index b0f9ae408..d72f64b5e 100644 --- a/pkg/domain/entities/engine_image.go +++ b/pkg/domain/entities/engine_image.go @@ -27,6 +27,7 @@ type ImageEngine interface { ShowTrust(ctx context.Context, args []string, options ShowTrustOptions) (*ShowTrustReport, error) Shutdown(ctx context.Context) Tag(ctx context.Context, nameOrID string, tags []string, options ImageTagOptions) error + Transfer(ctx context.Context, scpOpts ImageScpOptions) error Tree(ctx context.Context, nameOrID string, options ImageTreeOptions) (*ImageTreeReport, error) Unmount(ctx context.Context, images []string, options ImageUnmountOptions) ([]*ImageUnmountReport, error) Untag(ctx context.Context, nameOrID string, tags []string, options ImageUntagOptions) error diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index 38cdc8f2f..7583ce442 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -329,6 +329,10 @@ type ImageScpOptions struct { Save ImageSaveOptions // Load options used for the second half of the scp operation Load ImageLoadOptions + // Rootless determines whether we are loading locally from root storage to rootless storage + Rootless bool + // User is used in conjunction with Rootless to determine which user to use to obtain the uid + User string } // ImageTreeOptions provides options for ImageEngine.Tree() diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 7aa202334..5c0227986 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -6,9 +6,12 @@ import ( "io/ioutil" "net/url" "os" + "os/exec" + "os/user" "path" "path/filepath" "strconv" + "strings" "github.com/containers/common/libimage" "github.com/containers/common/pkg/config" @@ -18,6 +21,7 @@ import ( "github.com/containers/image/v5/signature" "github.com/containers/image/v5/transports" "github.com/containers/image/v5/transports/alltransports" + "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/domain/entities/reports" domainUtils "github.com/containers/podman/v3/pkg/domain/utils" @@ -330,6 +334,67 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri return pushError } +// Transfer moves images from root to rootless storage so the user specified in the scp call can access and use the image modified by root +func (ir *ImageEngine) Transfer(ctx context.Context, scpOpts entities.ImageScpOptions) error { + if scpOpts.User == "" { + return errors.Wrapf(define.ErrInvalidArg, "you must define a user when transferring from root to rootless storage") + } + var u *user.User + scpOpts.User = strings.Split(scpOpts.User, ":")[0] // split in case provided with uid:gid + _, err := strconv.Atoi(scpOpts.User) + if err != nil { + u, err = user.Lookup(scpOpts.User) + if err != nil { + return err + } + } else { + u, err = user.LookupId(scpOpts.User) + if err != nil { + return err + } + } + uid, err := strconv.Atoi(u.Uid) + if err != nil { + return err + } + gid, err := strconv.Atoi(u.Gid) + if err != nil { + return err + } + err = os.Chown(scpOpts.Save.Output, uid, gid) // chown the output because was created by root so we need to give th euser read access + if err != nil { + return err + } + + podman, err := os.Executable() + if err != nil { + return err + } + machinectl, err := exec.LookPath("machinectl") + if err != nil { + logrus.Warn("defaulting to su since machinectl is not available, su will fail if no user session is available") + cmd := exec.Command("su", "-l", u.Username, "--command", podman+" --log-level="+logrus.GetLevel().String()+" --cgroup-manager=cgroupfs load --input="+scpOpts.Save.Output) // load the new image to the rootless storage + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + logrus.Debug("Executing load command su") + err = cmd.Run() + if err != nil { + return err + } + } else { + cmd := exec.Command(machinectl, "shell", "-q", u.Username+"@.host", podman, "--log-level="+logrus.GetLevel().String(), "--cgroup-manager=cgroupfs", "load", "--input", scpOpts.Save.Output) // load the new image to the rootless storage + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + logrus.Debug("Executing load command machinectl") + err = cmd.Run() + if err != nil { + return err + } + } + + return nil +} + func (ir *ImageEngine) Tag(ctx context.Context, nameOrID string, tags []string, options entities.ImageTagOptions) error { // Allow tagging manifest list instead of resolving instances from manifest lookupOptions := &libimage.LookupImageOptions{ManifestList: true} diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index e17f746a5..fde57972f 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -12,6 +12,7 @@ import ( "github.com/containers/common/pkg/config" "github.com/containers/image/v5/docker/reference" "github.com/containers/image/v5/types" + "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/bindings/images" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/domain/entities/reports" @@ -122,6 +123,10 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, opts entities. return &entities.ImagePullReport{Images: pulledImages}, nil } +func (ir *ImageEngine) Transfer(ctx context.Context, scpOpts entities.ImageScpOptions) error { + return errors.Wrapf(define.ErrNotImplemented, "cannot use the remote client to transfer images between root and rootless storage") +} + func (ir *ImageEngine) Tag(ctx context.Context, nameOrID string, tags []string, opt entities.ImageTagOptions) error { options := new(images.TagOptions) for _, newTag := range tags { |