summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/domain/entities/engine_image.go2
-rw-r--r--pkg/domain/entities/images.go30
-rw-r--r--pkg/domain/infra/abi/images.go126
-rw-r--r--pkg/domain/infra/tunnel/images.go8
-rw-r--r--pkg/rootless/rootless_linux.c3
5 files changed, 163 insertions, 6 deletions
diff --git a/pkg/domain/entities/engine_image.go b/pkg/domain/entities/engine_image.go
index 7ece24c60..594f9617f 100644
--- a/pkg/domain/entities/engine_image.go
+++ b/pkg/domain/entities/engine_image.go
@@ -16,6 +16,7 @@ type ImageEngine interface {
Inspect(ctx context.Context, namesOrIDs []string, opts InspectOptions) ([]*ImageInspectReport, []error, error)
List(ctx context.Context, opts ImageListOptions) ([]*ImageSummary, error)
Load(ctx context.Context, opts ImageLoadOptions) (*ImageLoadReport, error)
+ Mount(ctx context.Context, images []string, options ImageMountOptions) ([]*ImageMountReport, error)
Prune(ctx context.Context, opts ImagePruneOptions) (*ImagePruneReport, error)
Pull(ctx context.Context, rawImage string, opts ImagePullOptions) (*ImagePullReport, error)
Push(ctx context.Context, source string, destination string, opts ImagePushOptions) error
@@ -27,6 +28,7 @@ type ImageEngine interface {
Shutdown(ctx context.Context)
Tag(ctx context.Context, nameOrID string, tags []string, options ImageTagOptions) 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
ManifestCreate(ctx context.Context, names, images []string, opts ManifestCreateOptions) (string, error)
ManifestInspect(ctx context.Context, name string) ([]byte, error)
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index b38facfb5..cb970b09a 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -91,7 +91,7 @@ type ImageRemoveOptions struct {
}
// ImageRemoveResponse is the response for removing one or more image(s) from storage
-// and containers what was untagged vs actually removed.
+// and images what was untagged vs actually removed.
type ImageRemoveReport struct {
// Deleted images.
Deleted []string `json:",omitempty"`
@@ -318,3 +318,31 @@ type SignOptions struct {
// SignReport describes the result of signing
type SignReport struct{}
+
+// ImageMountOptions describes the input values for mounting images
+// in the CLI
+type ImageMountOptions struct {
+ All bool
+ Format string
+}
+
+// ImageUnmountOptions are the options from the cli for unmounting
+type ImageUnmountOptions struct {
+ All bool
+ Force bool
+}
+
+// ImageMountReport describes the response from image mount
+type ImageMountReport struct {
+ Err error
+ Id string //nolint
+ Name string
+ Repositories []string
+ Path string
+}
+
+// ImageUnmountReport describes the response from umounting an image
+type ImageUnmountReport struct {
+ Err error
+ Id string //nolint
+}
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index e2fe8a5e6..10ec7f8f3 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -11,8 +11,6 @@ import (
"strconv"
"strings"
- "github.com/containers/podman/v2/pkg/rootless"
-
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker"
dockerarchive "github.com/containers/image/v5/docker/archive"
@@ -27,6 +25,7 @@ import (
libpodImage "github.com/containers/podman/v2/libpod/image"
"github.com/containers/podman/v2/pkg/domain/entities"
domainUtils "github.com/containers/podman/v2/pkg/domain/utils"
+ "github.com/containers/podman/v2/pkg/rootless"
"github.com/containers/podman/v2/pkg/trust"
"github.com/containers/podman/v2/pkg/util"
"github.com/containers/storage"
@@ -85,6 +84,125 @@ func (ir *ImageEngine) History(ctx context.Context, nameOrID string, opts entiti
return &history, nil
}
+func (ir *ImageEngine) Mount(ctx context.Context, nameOrIDs []string, opts entities.ImageMountOptions) ([]*entities.ImageMountReport, error) {
+ var (
+ images []*image.Image
+ err error
+ )
+ if os.Geteuid() != 0 {
+ if driver := ir.Libpod.StorageConfig().GraphDriverName; driver != "vfs" {
+ // Do not allow to mount a graphdriver that is not vfs if we are creating the userns as part
+ // of the mount command.
+ return nil, errors.Errorf("cannot mount using driver %s in rootless mode", driver)
+ }
+
+ became, ret, err := rootless.BecomeRootInUserNS("")
+ if err != nil {
+ return nil, err
+ }
+ if became {
+ os.Exit(ret)
+ }
+ }
+ if opts.All {
+ allImages, err := ir.Libpod.ImageRuntime().GetImages()
+ if err != nil {
+ return nil, err
+ }
+ for _, img := range allImages {
+ if !img.IsReadOnly() {
+ images = append(images, img)
+ }
+ }
+ } else {
+ for _, i := range nameOrIDs {
+ img, err := ir.Libpod.ImageRuntime().NewFromLocal(i)
+ if err != nil {
+ return nil, err
+ }
+ images = append(images, img)
+ }
+ }
+ reports := make([]*entities.ImageMountReport, 0, len(images))
+ for _, img := range images {
+ report := entities.ImageMountReport{Id: img.ID()}
+ if img.IsReadOnly() {
+ report.Err = errors.Errorf("mounting readonly %s image not supported", img.ID())
+ } else {
+ report.Path, report.Err = img.Mount([]string{}, "")
+ }
+ reports = append(reports, &report)
+ }
+ if len(reports) > 0 {
+ return reports, nil
+ }
+
+ images, err = ir.Libpod.ImageRuntime().GetImages()
+ if err != nil {
+ return nil, err
+ }
+ for _, i := range images {
+ mounted, path, err := i.Mounted()
+ if err != nil {
+ if errors.Cause(err) == storage.ErrLayerUnknown {
+ continue
+ }
+ return nil, err
+ }
+ if mounted {
+ tags, err := i.RepoTags()
+ if err != nil {
+ return nil, err
+ }
+ reports = append(reports, &entities.ImageMountReport{
+ Id: i.ID(),
+ Name: string(i.Digest()),
+ Repositories: tags,
+ Path: path,
+ })
+ }
+ }
+ return reports, nil
+}
+
+func (ir *ImageEngine) Unmount(ctx context.Context, nameOrIDs []string, options entities.ImageUnmountOptions) ([]*entities.ImageUnmountReport, error) {
+ var images []*image.Image
+
+ if options.All {
+ allImages, err := ir.Libpod.ImageRuntime().GetImages()
+ if err != nil {
+ return nil, err
+ }
+ for _, img := range allImages {
+ if !img.IsReadOnly() {
+ images = append(images, img)
+ }
+ }
+ } else {
+ for _, i := range nameOrIDs {
+ img, err := ir.Libpod.ImageRuntime().NewFromLocal(i)
+ if err != nil {
+ return nil, err
+ }
+ images = append(images, img)
+ }
+ }
+
+ reports := []*entities.ImageUnmountReport{}
+ for _, img := range images {
+ report := entities.ImageUnmountReport{Id: img.ID()}
+ if err := img.Unmount(options.Force); err != nil {
+ if options.All && errors.Cause(err) == storage.ErrLayerNotMounted {
+ logrus.Debugf("Error umounting image %s, storage.ErrLayerNotMounted", img.ID())
+ continue
+ }
+ report.Err = errors.Wrapf(err, "error unmounting image %s", img.ID())
+ }
+ reports = append(reports, &report)
+ }
+ return reports, nil
+}
+
func ToDomainHistoryLayer(layer *libpodImage.History) entities.ImageHistoryLayer {
l := entities.ImageHistoryLayer{}
l.ID = layer.ID
@@ -225,7 +343,7 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
case "v2s2", "docker":
manifestType = manifest.DockerV2Schema2MediaType
default:
- return fmt.Errorf("unknown format %q. Choose on of the supported formats: 'oci', 'v2s1', or 'v2s2'", options.Format)
+ return errors.Errorf("unknown format %q. Choose on of the supported formats: 'oci', 'v2s1', or 'v2s2'", options.Format)
}
var registryCreds *types.DockerAuthConfig
@@ -292,7 +410,7 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
//
// // TODO: Determine Size
// report := entities.ImagePruneReport{}
-// copy(report.Report.Id, id)
+// copy(report.Report.ID, id)
// return &report, nil
// }
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 6407724b5..6845d01c0 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -54,6 +54,14 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions)
return is, nil
}
+func (ir *ImageEngine) Mount(ctx context.Context, images []string, options entities.ImageMountOptions) ([]*entities.ImageMountReport, error) {
+ return nil, errors.New("mounting images is not supported for remote clients")
+}
+
+func (ir *ImageEngine) Unmount(ctx context.Context, images []string, options entities.ImageUnmountOptions) ([]*entities.ImageUnmountReport, error) {
+ return nil, errors.New("unmounting images is not supported for remote clients")
+}
+
func (ir *ImageEngine) History(ctx context.Context, nameOrID string, opts entities.ImageHistoryOptions) (*entities.ImageHistoryReport, error) {
results, err := images.History(ir.ClientCxt, nameOrID)
if err != nil {
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c
index 8e0151496..d3e43e44d 100644
--- a/pkg/rootless/rootless_linux.c
+++ b/pkg/rootless/rootless_linux.c
@@ -211,7 +211,8 @@ can_use_shortcut ()
break;
}
- if (argv[argc+1] != NULL && strcmp (argv[argc], "container") == 0 &&
+ if (argv[argc+1] != NULL && (strcmp (argv[argc], "container") == 0 ||
+ strcmp (argv[argc], "image") == 0) &&
strcmp (argv[argc+1], "mount") == 0)
{
ret = false;