summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container.go11
-rw-r--r--libpod/container_api.go44
-rw-r--r--libpod/container_commit.go2
-rw-r--r--libpod/container_inspect.go2
-rw-r--r--libpod/container_internal.go45
-rw-r--r--libpod/image/docker_registry_options.go12
-rw-r--r--libpod/image/image.go284
-rw-r--r--libpod/image/image_test.go13
-rw-r--r--libpod/image/parts.go2
-rw-r--r--libpod/image/pull.go30
-rw-r--r--libpod/image/pull_test.go6
-rw-r--r--libpod/image/search.go4
-rw-r--r--libpod/image/utils.go22
-rw-r--r--libpod/networking_linux.go28
-rw-r--r--libpod/oci_conmon_linux.go2
-rw-r--r--libpod/options.go2
-rw-r--r--libpod/runtime.go49
-rw-r--r--libpod/runtime_img.go6
-rw-r--r--libpod/runtime_volume_linux.go9
-rw-r--r--libpod/storage.go4
-rw-r--r--libpod/util.go17
21 files changed, 385 insertions, 209 deletions
diff --git a/libpod/container.go b/libpod/container.go
index 7be73b3c3..5a7cf202b 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -10,7 +10,7 @@ import (
"github.com/containernetworking/cni/pkg/types"
cnitypes "github.com/containernetworking/cni/pkg/types/current"
- "github.com/containers/image/v4/manifest"
+ "github.com/containers/image/v5/manifest"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/lock"
"github.com/containers/libpod/pkg/namespaces"
@@ -1185,3 +1185,12 @@ func (c *Container) HasHealthCheck() bool {
func (c *Container) HealthCheckConfig() *manifest.Schema2HealthConfig {
return c.config.HealthCheckConfig
}
+
+// AutoRemove indicates whether the container will be removed after it is executed
+func (c *Container) AutoRemove() bool {
+ spec := c.config.Spec
+ if spec.Annotations == nil {
+ return false
+ }
+ return c.Spec().Annotations[InspectAnnotationAutoremove] == InspectResponseTrue
+}
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 759a7067e..1b2d52ce3 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -32,9 +32,7 @@ func (c *Container) Init(ctx context.Context) (err error) {
}
}
- if !(c.state.State == define.ContainerStateConfigured ||
- c.state.State == define.ContainerStateStopped ||
- c.state.State == define.ContainerStateExited) {
+ if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateStopped, define.ContainerStateExited) {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s has already been created in runtime", c.ID())
}
@@ -176,15 +174,12 @@ func (c *Container) StopWithTimeout(timeout uint) error {
}
}
- if c.state.State == define.ContainerStateConfigured ||
- c.state.State == define.ContainerStateUnknown ||
- c.state.State == define.ContainerStatePaused {
- return errors.Wrapf(define.ErrCtrStateInvalid, "can only stop created, running, or stopped containers. %s is in state %s", c.ID(), c.state.State.String())
+ if c.ensureState(define.ContainerStateStopped, define.ContainerStateExited) {
+ return define.ErrCtrStopped
}
- if c.state.State == define.ContainerStateStopped ||
- c.state.State == define.ContainerStateExited {
- return define.ErrCtrStopped
+ if !c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning) {
+ return errors.Wrapf(define.ErrCtrStateInvalid, "can only stop created or running containers. %s is in state %s", c.ID(), c.state.State.String())
}
return c.stop(timeout, false)
@@ -201,6 +196,7 @@ func (c *Container) Kill(signal uint) error {
}
}
+ // TODO: Is killing a paused container OK?
if c.state.State != define.ContainerStateRunning {
return errors.Wrapf(define.ErrCtrStateInvalid, "can only kill running containers. %s is in state %s", c.ID(), c.state.State.String())
}
@@ -234,10 +230,7 @@ func (c *Container) Exec(tty, privileged bool, env map[string]string, cmd []stri
}
}
- conState := c.state.State
-
- // TODO can probably relax this once we track exec sessions
- if conState != define.ContainerStateRunning {
+ if c.state.State != define.ContainerStateRunning {
return define.ExecErrorCodeCannotInvoke, errors.Wrapf(define.ErrCtrStateInvalid, "cannot exec into container that is not running")
}
@@ -391,11 +384,10 @@ func (c *Container) Attach(streams *AttachStreams, keys string, resize <-chan re
c.lock.Unlock()
}
- if c.state.State != define.ContainerStateCreated &&
- c.state.State != define.ContainerStateRunning &&
- c.state.State != define.ContainerStateExited {
+ if !c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning) {
return errors.Wrapf(define.ErrCtrStateInvalid, "can only attach to created or running containers")
}
+
defer c.newContainerEvent(events.Attach)
return c.attach(streams, keys, resize, false, nil)
}
@@ -432,7 +424,7 @@ func (c *Container) Unmount(force bool) error {
return errors.Wrapf(err, "can't determine how many times %s is mounted, refusing to unmount", c.ID())
}
if mounted == 1 {
- if c.state.State == define.ContainerStateRunning || c.state.State == define.ContainerStatePaused {
+ if c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) {
return errors.Wrapf(define.ErrCtrStateInvalid, "cannot unmount storage for container %s as it is running or paused", c.ID())
}
if len(c.state.ExecSessions) != 0 {
@@ -574,7 +566,7 @@ func (c *Container) Cleanup(ctx context.Context) error {
}
// Check if state is good
- if c.state.State == define.ContainerStateRunning || c.state.State == define.ContainerStatePaused {
+ if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateCreated, define.ContainerStateStopped, define.ContainerStateExited) {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is running or paused, refusing to clean up", c.ID())
}
@@ -652,9 +644,7 @@ func (c *Container) Sync() error {
// If runtime knows about the container, update its status in runtime
// And then save back to disk
- if (c.state.State != define.ContainerStateUnknown) &&
- (c.state.State != define.ContainerStateConfigured) &&
- (c.state.State != define.ContainerStateExited) {
+ if c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning, define.ContainerStatePaused, define.ContainerStateStopped) {
oldState := c.state.State
if err := c.ociRuntime.UpdateContainerStatus(c); err != nil {
return err
@@ -666,6 +656,7 @@ func (c *Container) Sync() error {
}
}
}
+
defer c.newContainerEvent(events.Sync)
return nil
}
@@ -840,12 +831,3 @@ func (c *Container) Restore(ctx context.Context, options ContainerCheckpointOpti
defer c.newContainerEvent(events.Restore)
return c.restore(ctx, options)
}
-
-// AutoRemove indicates whether the container will be removed after it is executed
-func (c *Container) AutoRemove() bool {
- spec := c.config.Spec
- if spec.Annotations == nil {
- return false
- }
- return c.Spec().Annotations[InspectAnnotationAutoremove] == InspectResponseTrue
-}
diff --git a/libpod/container_commit.go b/libpod/container_commit.go
index d5afe0da7..42f298a81 100644
--- a/libpod/container_commit.go
+++ b/libpod/container_commit.go
@@ -8,7 +8,7 @@ import (
"github.com/containers/buildah"
"github.com/containers/buildah/util"
- is "github.com/containers/image/v4/storage"
+ is "github.com/containers/image/v5/storage"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/libpod/image"
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 70b51960b..d28d37937 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -5,7 +5,7 @@ import (
"strings"
"time"
- "github.com/containers/image/v4/manifest"
+ "github.com/containers/image/v5/manifest"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/driver"
"github.com/containers/libpod/pkg/util"
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 0043c9651..028d7601d 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -328,7 +328,7 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (restarted bool, er
// Is the container running again?
// If so, we don't have to do anything
- if c.state.State == define.ContainerStateRunning || c.state.State == define.ContainerStatePaused {
+ if c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) {
return false, nil
} else if c.state.State == define.ContainerStateUnknown {
return false, errors.Wrapf(define.ErrInternal, "invalid container state encountered in restart attempt!")
@@ -359,8 +359,7 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (restarted bool, er
if err := c.reinit(ctx, true); err != nil {
return false, err
}
- } else if c.state.State == define.ContainerStateConfigured ||
- c.state.State == define.ContainerStateExited {
+ } else if c.ensureState(define.ContainerStateConfigured, define.ContainerStateExited) {
// Initialize the container
if err := c.init(ctx, true); err != nil {
return false, err
@@ -372,6 +371,18 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (restarted bool, er
return true, nil
}
+// Ensure that the container is in a specific state or state.
+// Returns true if the container is in one of the given states,
+// or false otherwise.
+func (c *Container) ensureState(states ...define.ContainerStatus) bool {
+ for _, state := range states {
+ if state == c.state.State {
+ return true
+ }
+ }
+ return false
+}
+
// Sync this container with on-disk state and runtime status
// Should only be called with container lock held
// This function should suffice to ensure a container's state is accurate and
@@ -382,9 +393,7 @@ func (c *Container) syncContainer() error {
}
// If runtime knows about the container, update its status in runtime
// And then save back to disk
- if (c.state.State != define.ContainerStateUnknown) &&
- (c.state.State != define.ContainerStateConfigured) &&
- (c.state.State != define.ContainerStateExited) {
+ if c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning, define.ContainerStateStopped, define.ContainerStatePaused) {
oldState := c.state.State
if err := c.checkExitFile(); err != nil {
@@ -516,7 +525,7 @@ func (c *Container) setupStorage(ctx context.Context) error {
// Tear down a container's storage prior to removal
func (c *Container) teardownStorage() error {
- if c.state.State == define.ContainerStateRunning || c.state.State == define.ContainerStatePaused {
+ if c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) {
return errors.Wrapf(define.ErrCtrStateInvalid, "cannot remove storage for container %s as it is running or paused", c.ID())
}
@@ -721,10 +730,7 @@ func (c *Container) save() error {
// Otherwise, this function will return with error if there are dependencies of this container that aren't running.
func (c *Container) prepareToStart(ctx context.Context, recursive bool) (err error) {
// Container must be created or stopped to be started
- if !(c.state.State == define.ContainerStateConfigured ||
- c.state.State == define.ContainerStateCreated ||
- c.state.State == define.ContainerStateStopped ||
- c.state.State == define.ContainerStateExited) {
+ if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateCreated, define.ContainerStateStopped, define.ContainerStateExited) {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s must be in Created or Stopped state to be started", c.ID())
}
@@ -755,8 +761,7 @@ func (c *Container) prepareToStart(ctx context.Context, recursive bool) (err err
if err := c.reinit(ctx, false); err != nil {
return err
}
- } else if c.state.State == define.ContainerStateConfigured ||
- c.state.State == define.ContainerStateExited {
+ } else if c.ensureState(define.ContainerStateConfigured, define.ContainerStateExited) {
// Or initialize it if necessary
if err := c.init(ctx, false); err != nil {
return err
@@ -987,7 +992,7 @@ func (c *Container) cleanupRuntime(ctx context.Context) error {
// If the container is not ContainerStateStopped or
// ContainerStateCreated, do nothing.
- if c.state.State != define.ContainerStateStopped && c.state.State != define.ContainerStateCreated {
+ if !c.ensureState(define.ContainerStateStopped, define.ContainerStateCreated) {
return nil
}
@@ -1078,8 +1083,7 @@ func (c *Container) initAndStart(ctx context.Context) (err error) {
if err := c.reinit(ctx, false); err != nil {
return err
}
- } else if c.state.State == define.ContainerStateConfigured ||
- c.state.State == define.ContainerStateExited {
+ } else if c.ensureState(define.ContainerStateConfigured, define.ContainerStateExited) {
if err := c.init(ctx, false); err != nil {
return err
}
@@ -1205,7 +1209,7 @@ func (c *Container) unpause() error {
// Internal, non-locking function to restart a container
func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (err error) {
- if c.state.State == define.ContainerStateUnknown || c.state.State == define.ContainerStatePaused {
+ if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateCreated, define.ContainerStateRunning, define.ContainerStateStopped, define.ContainerStateExited) {
return errors.Wrapf(define.ErrCtrStateInvalid, "unable to restart a container in a paused or unknown state")
}
@@ -1733,9 +1737,8 @@ func (c *Container) checkReadyForRemoval() error {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is in invalid state", c.ID())
}
- if c.state.State == define.ContainerStateRunning ||
- c.state.State == define.ContainerStatePaused {
- return errors.Wrapf(define.ErrCtrStateInvalid, "cannot remove container %s as it is %s - running or paused containers cannot be removed", c.ID(), c.state.State.String())
+ if c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) {
+ return errors.Wrapf(define.ErrCtrStateInvalid, "cannot remove container %s as it is %s - running or paused containers cannot be removed without force", c.ID(), c.state.State.String())
}
if len(c.state.ExecSessions) != 0 {
@@ -1816,7 +1819,7 @@ func (c *Container) sortUserVolumes(ctrSpec *spec.Spec) ([]*ContainerNamedVolume
// Check for an exit file, and handle one if present
func (c *Container) checkExitFile() error {
// If the container's not running, nothing to do.
- if c.state.State != define.ContainerStateRunning && c.state.State != define.ContainerStatePaused {
+ if !c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) {
return nil
}
diff --git a/libpod/image/docker_registry_options.go b/libpod/image/docker_registry_options.go
index d205fe4ac..62a4af465 100644
--- a/libpod/image/docker_registry_options.go
+++ b/libpod/image/docker_registry_options.go
@@ -3,8 +3,8 @@ package image
import (
"fmt"
- "github.com/containers/image/v4/docker/reference"
- "github.com/containers/image/v4/types"
+ "github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/types"
podmanVersion "github.com/containers/libpod/version"
)
@@ -26,6 +26,10 @@ type DockerRegistryOptions struct {
// certificates and allows connecting to registries without encryption
// - or forces it on even if registries.conf has the registry configured as insecure.
DockerInsecureSkipTLSVerify types.OptionalBool
+ // If not "", overrides the use of platform.GOOS when choosing an image or verifying OS match.
+ OSChoice string
+ // If not "", overrides the use of platform.GOARCH when choosing an image or verifying architecture match.
+ ArchitectureChoice string
}
// GetSystemContext constructs a new system context from a parent context. the values in the DockerRegistryOptions, and other parameters.
@@ -35,12 +39,16 @@ func (o DockerRegistryOptions) GetSystemContext(parent *types.SystemContext, add
DockerCertPath: o.DockerCertPath,
DockerInsecureSkipTLSVerify: o.DockerInsecureSkipTLSVerify,
DockerArchiveAdditionalTags: additionalDockerArchiveTags,
+ OSChoice: o.OSChoice,
+ ArchitectureChoice: o.ArchitectureChoice,
}
if parent != nil {
sc.SignaturePolicyPath = parent.SignaturePolicyPath
sc.AuthFilePath = parent.AuthFilePath
sc.DirForceCompress = parent.DirForceCompress
sc.DockerRegistryUserAgent = parent.DockerRegistryUserAgent
+ sc.OSChoice = parent.OSChoice
+ sc.ArchitectureChoice = parent.ArchitectureChoice
}
return sc
}
diff --git a/libpod/image/image.go b/libpod/image/image.go
index 9adefb5c5..c912ac2ca 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -3,26 +3,29 @@ package image
import (
"context"
"encoding/json"
+ stderrors "errors"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
+ "sort"
"strings"
"syscall"
"time"
- cp "github.com/containers/image/v4/copy"
- "github.com/containers/image/v4/directory"
- dockerarchive "github.com/containers/image/v4/docker/archive"
- "github.com/containers/image/v4/docker/reference"
- "github.com/containers/image/v4/manifest"
- ociarchive "github.com/containers/image/v4/oci/archive"
- is "github.com/containers/image/v4/storage"
- "github.com/containers/image/v4/tarball"
- "github.com/containers/image/v4/transports"
- "github.com/containers/image/v4/transports/alltransports"
- "github.com/containers/image/v4/types"
+ cp "github.com/containers/image/v5/copy"
+ "github.com/containers/image/v5/directory"
+ dockerarchive "github.com/containers/image/v5/docker/archive"
+ "github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/image"
+ "github.com/containers/image/v5/manifest"
+ ociarchive "github.com/containers/image/v5/oci/archive"
+ is "github.com/containers/image/v5/storage"
+ "github.com/containers/image/v5/tarball"
+ "github.com/containers/image/v5/transports"
+ "github.com/containers/image/v5/transports/alltransports"
+ "github.com/containers/image/v5/types"
"github.com/containers/libpod/libpod/driver"
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/pkg/inspect"
@@ -42,8 +45,8 @@ import (
type Image struct {
// Adding these two structs for now but will cull when we near
// completion of this library.
- imgRef types.Image
- storeRef types.ImageReference
+ imgRef types.Image
+ imgSrcRef types.ImageSource
inspect.ImageData
inspect.ImageResult
inspectInfo *types.ImageInspectInfo
@@ -72,7 +75,10 @@ type InfoImage struct {
}
// ErrRepoTagNotFound is the error returned when the image id given doesn't match a rep tag in store
-var ErrRepoTagNotFound = errors.New("unable to match user input to any specific repotag")
+var ErrRepoTagNotFound = stderrors.New("unable to match user input to any specific repotag")
+
+// ErrImageIsBareList is the error returned when the image is just a list or index
+var ErrImageIsBareList = stderrors.New("image contains a manifest list or image index, but no runnable image")
// NewImageRuntimeFromStore creates an ImageRuntime based on a provided store
func NewImageRuntimeFromStore(store storage.Store) *Runtime {
@@ -294,9 +300,23 @@ func (i *Image) Digest() digest.Digest {
return i.image.Digest
}
+// Digests returns the image's digests
+func (i *Image) Digests() []digest.Digest {
+ return i.image.Digests
+}
+
+// GetManifest returns the image's manifest as a byte array
+// and manifest type as a string.
+func (i *Image) GetManifest(ctx context.Context, instanceDigest *digest.Digest) ([]byte, string, error) {
+ imgSrcRef, err := i.toImageSourceRef(ctx)
+ if err != nil {
+ return nil, "", err
+ }
+ return imgSrcRef.GetManifest(ctx, instanceDigest)
+}
+
// Manifest returns the image's manifest as a byte array
-// and manifest type as a string. The manifest type is
-// MediaTypeImageManifest from ociv1.
+// and manifest type as a string.
func (i *Image) Manifest(ctx context.Context) ([]byte, string, error) {
imgRef, err := i.toImageRef(ctx)
if err != nil {
@@ -305,29 +325,54 @@ func (i *Image) Manifest(ctx context.Context) ([]byte, string, error) {
return imgRef.Manifest(ctx)
}
-// Names returns a string array of names associated with the image
+// Names returns a string array of names associated with the image, which may be a mixture of tags and digests
func (i *Image) Names() []string {
return i.image.Names
}
-// RepoDigests returns a string array of repodigests associated with the image
-func (i *Image) RepoDigests() ([]string, error) {
- var repoDigests []string
- imageDigest := i.Digest()
-
+// RepoTags returns a string array of repotags associated with the image
+func (i *Image) RepoTags() ([]string, error) {
+ var repoTags []string
for _, name := range i.Names() {
named, err := reference.ParseNormalizedNamed(name)
if err != nil {
return nil, err
}
-
- canonical, err := reference.WithDigest(reference.TrimNamed(named), imageDigest)
- if err != nil {
- return nil, err
+ if tagged, isTagged := named.(reference.NamedTagged); isTagged {
+ repoTags = append(repoTags, tagged.String())
}
+ }
+ return repoTags, nil
+}
+
+// RepoDigests returns a string array of repodigests associated with the image
+func (i *Image) RepoDigests() ([]string, error) {
+ var repoDigests []string
+ added := make(map[string]struct{})
- repoDigests = append(repoDigests, canonical.String())
+ for _, name := range i.Names() {
+ for _, imageDigest := range append(i.Digests(), i.Digest()) {
+ if imageDigest == "" {
+ continue
+ }
+
+ named, err := reference.ParseNormalizedNamed(name)
+ if err != nil {
+ return nil, err
+ }
+
+ canonical, err := reference.WithDigest(reference.TrimNamed(named), imageDigest)
+ if err != nil {
+ return nil, err
+ }
+
+ if _, alreadyInList := added[canonical.String()]; !alreadyInList {
+ repoDigests = append(repoDigests, canonical.String())
+ added[canonical.String()] = struct{}{}
+ }
+ }
}
+ sort.Strings(repoDigests)
return repoDigests, nil
}
@@ -379,26 +424,6 @@ func (i *Image) Remove(ctx context.Context, force bool) error {
return nil
}
-// TODO: Rework this method to not require an assembly of the fq name with transport
-/*
-// GetManifest tries to GET an images manifest, returns nil on success and err on failure
-func (i *Image) GetManifest() error {
- pullRef, err := alltransports.ParseImageName(i.assembleFqNameTransport())
- if err != nil {
- return errors.Errorf("unable to parse '%s'", i.Names()[0])
- }
- imageSource, err := pullRef.NewImageSource(nil)
- if err != nil {
- return errors.Wrapf(err, "unable to create new image source")
- }
- _, _, err = imageSource.GetManifest(nil)
- if err == nil {
- return nil
- }
- return err
-}
-*/
-
// getImage retrieves an image matching the given name or hash from system
// storage
// If no matching image can be found, an error is returned
@@ -612,76 +637,98 @@ func (i *Image) PushImageToReference(ctx context.Context, dest types.ImageRefere
// MatchesID returns a bool based on if the input id
// matches the image's id
+// TODO: This isn't used anywhere, so remove it
func (i *Image) MatchesID(id string) bool {
return strings.HasPrefix(i.ID(), id)
}
-// toStorageReference returns a *storageReference from an Image
-func (i *Image) toStorageReference() (types.ImageReference, error) {
- var lookupName string
- if i.storeRef == nil {
- if i.image != nil {
- lookupName = i.ID()
- } else {
- lookupName = i.InputName
- }
- storeRef, err := is.Transport.ParseStoreReference(i.imageruntime.store, lookupName)
- if err != nil {
- return nil, err
- }
- i.storeRef = storeRef
- }
- return i.storeRef, nil
-}
-
// ToImageRef returns an image reference type from an image
// TODO: Hopefully we can remove this exported function for mheon
func (i *Image) ToImageRef(ctx context.Context) (types.Image, error) {
return i.toImageRef(ctx)
}
-// toImageRef returns an Image Reference type from an image
-func (i *Image) toImageRef(ctx context.Context) (types.Image, error) {
+// toImageSourceRef returns an ImageSource Reference type from an image
+func (i *Image) toImageSourceRef(ctx context.Context) (types.ImageSource, error) {
if i == nil {
- return nil, errors.Errorf("cannot convert nil image to image reference")
+ return nil, errors.Errorf("cannot convert nil image to image source reference")
}
- if i.imgRef == nil {
+ if i.imgSrcRef == nil {
ref, err := is.Transport.ParseStoreReference(i.imageruntime.store, "@"+i.ID())
if err != nil {
return nil, errors.Wrapf(err, "error parsing reference to image %q", i.ID())
}
- imgRef, err := ref.NewImage(ctx, nil)
+ imgSrcRef, err := ref.NewImageSource(ctx, nil)
if err != nil {
- return nil, errors.Wrapf(err, "error reading image %q", i.ID())
+ return nil, errors.Wrapf(err, "error reading image %q as image source", i.ID())
}
- i.imgRef = imgRef
+ i.imgSrcRef = imgSrcRef
}
- return i.imgRef, nil
-}
-
-// sizer knows its size.
-type sizer interface {
- Size() (int64, error)
+ return i.imgSrcRef, nil
}
//Size returns the size of the image
func (i *Image) Size(ctx context.Context) (*uint64, error) {
- storeRef, err := is.Transport.ParseStoreReference(i.imageruntime.store, i.ID())
- if err != nil {
- return nil, err
+ if i.image == nil {
+ localImage, err := i.getLocalImage()
+ if err != nil {
+ return nil, err
+ }
+ i.image = localImage
}
- systemContext := &types.SystemContext{}
- img, err := storeRef.NewImageSource(ctx, systemContext)
+ if sum, err := i.imageruntime.store.ImageSize(i.ID()); err == nil && sum >= 0 {
+ usum := uint64(sum)
+ return &usum, nil
+ }
+ return nil, errors.Errorf("unable to determine size")
+}
+
+// toImageRef returns an Image Reference type from an image
+func (i *Image) toImageRef(ctx context.Context) (types.Image, error) {
+ if i == nil {
+ return nil, errors.Errorf("cannot convert nil image to image reference")
+ }
+ imgSrcRef, err := i.toImageSourceRef(ctx)
if err != nil {
return nil, err
}
- if s, ok := img.(sizer); ok {
- if sum, err := s.Size(); err == nil {
- usum := uint64(sum)
- return &usum, nil
+ if i.imgRef == nil {
+ systemContext := &types.SystemContext{}
+ unparsedDefaultInstance := image.UnparsedInstance(imgSrcRef, nil)
+ imgRef, err := image.FromUnparsedImage(ctx, systemContext, unparsedDefaultInstance)
+ if err != nil {
+ // check for a "tried-to-treat-a-bare-list-like-a-runnable-image" problem, else
+ // return info about the not-a-bare-list runnable image part of this storage.Image
+ if manifestBytes, manifestType, err2 := imgSrcRef.GetManifest(ctx, nil); err2 == nil {
+ if manifest.MIMETypeIsMultiImage(manifestType) {
+ if list, err3 := manifest.ListFromBlob(manifestBytes, manifestType); err3 == nil {
+ switch manifestType {
+ case ociv1.MediaTypeImageIndex:
+ err = errors.Wrapf(ErrImageIsBareList, "%q is an image index", i.InputName)
+ case manifest.DockerV2ListMediaType:
+ err = errors.Wrapf(ErrImageIsBareList, "%q is a manifest list", i.InputName)
+ default:
+ err = errors.Wrapf(ErrImageIsBareList, "%q", i.InputName)
+ }
+ for _, instanceDigest := range list.Instances() {
+ instance := instanceDigest
+ unparsedInstance := image.UnparsedInstance(imgSrcRef, &instance)
+ if imgRef2, err4 := image.FromUnparsedImage(ctx, systemContext, unparsedInstance); err4 == nil {
+ imgRef = imgRef2
+ err = nil
+ break
+ }
+ }
+ }
+ }
+ }
+ if err != nil {
+ return nil, errors.Wrapf(err, "error reading image %q as image", i.ID())
+ }
}
+ i.imgRef = imgRef
}
- return nil, errors.Errorf("unable to determine size")
+ return i.imgRef, nil
}
// DriverData gets the driver data from the store on a layer
@@ -708,6 +755,9 @@ type History struct {
func (i *Image) History(ctx context.Context) ([]*History, error) {
img, err := i.toImageRef(ctx)
if err != nil {
+ if errors.Cause(err) == ErrImageIsBareList {
+ return nil, nil
+ }
return nil, err
}
oci, err := img.OCIConfig(ctx)
@@ -853,7 +903,10 @@ func (i *Image) GetLabel(ctx context.Context, label string) (string, error) {
func (i *Image) Annotations(ctx context.Context) (map[string]string, error) {
imageManifest, manifestType, err := i.Manifest(ctx)
if err != nil {
- return nil, err
+ imageManifest, manifestType, err = i.GetManifest(ctx, nil)
+ if err != nil {
+ return nil, err
+ }
}
annotations := make(map[string]string)
switch manifestType {
@@ -868,24 +921,19 @@ func (i *Image) Annotations(ctx context.Context) (map[string]string, error) {
return annotations, nil
}
-// ociv1Image converts and image to an imgref and then an
-// ociv1 image type
+// ociv1Image converts an image to an imgref and then returns its config blob
+// converted to an ociv1 image type
func (i *Image) ociv1Image(ctx context.Context) (*ociv1.Image, error) {
imgRef, err := i.toImageRef(ctx)
if err != nil {
return nil, err
}
-
return imgRef.OCIConfig(ctx)
}
func (i *Image) imageInspectInfo(ctx context.Context) (*types.ImageInspectInfo, error) {
if i.inspectInfo == nil {
- sr, err := i.toStorageReference()
- if err != nil {
- return nil, err
- }
- ic, err := sr.NewImage(ctx, &types.SystemContext{})
+ ic, err := i.toImageRef(ctx)
if err != nil {
return nil, err
}
@@ -906,18 +954,23 @@ func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) {
ociv1Img, err := i.ociv1Image(ctx)
if err != nil {
- return nil, err
+ ociv1Img = &ociv1.Image{}
}
info, err := i.imageInspectInfo(ctx)
if err != nil {
- return nil, err
+ info = &types.ImageInspectInfo{}
}
annotations, err := i.Annotations(ctx)
if err != nil {
return nil, err
}
- size, err := i.Size(ctx)
+ size := int64(-1)
+ if usize, err := i.Size(ctx); err == nil {
+ size = int64(*usize)
+ }
+
+ repoTags, err := i.RepoTags()
if err != nil {
return nil, err
}
@@ -932,7 +985,7 @@ func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) {
return nil, err
}
- _, manifestType, err := i.Manifest(ctx)
+ _, manifestType, err := i.GetManifest(ctx, nil)
if err != nil {
return nil, errors.Wrapf(err, "unable to determine manifest type")
}
@@ -943,7 +996,7 @@ func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) {
data := &inspect.ImageData{
ID: i.ID(),
- RepoTags: i.Names(),
+ RepoTags: repoTags,
RepoDigests: repoDigests,
Comment: comment,
Created: ociv1Img.Created,
@@ -952,8 +1005,8 @@ func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) {
Os: ociv1Img.OS,
Config: &ociv1Img.Config,
Version: info.DockerVersion,
- Size: int64(*size),
- VirtualSize: int64(*size),
+ Size: size,
+ VirtualSize: size,
Annotations: annotations,
Digest: i.Digest(),
Labels: info.Labels,
@@ -1082,6 +1135,9 @@ func splitString(input string) string {
func (i *Image) IsParent(ctx context.Context) (bool, error) {
children, err := i.getChildren(ctx, 1)
if err != nil {
+ if errors.Cause(err) == ErrImageIsBareList {
+ return false, nil
+ }
return false, err
}
return len(children) > 0, nil
@@ -1165,6 +1221,9 @@ func (i *Image) GetParent(ctx context.Context) (*Image, error) {
// fetch the configuration for the child image
child, err := i.ociv1Image(ctx)
if err != nil {
+ if errors.Cause(err) == ErrImageIsBareList {
+ return nil, nil
+ }
return nil, err
}
for _, img := range images {
@@ -1205,12 +1264,24 @@ func (i *Image) GetParent(ctx context.Context) (*Image, error) {
// GetChildren returns a list of the imageIDs that depend on the image
func (i *Image) GetChildren(ctx context.Context) ([]string, error) {
- return i.getChildren(ctx, 0)
+ children, err := i.getChildren(ctx, 0)
+ if err != nil {
+ if errors.Cause(err) == ErrImageIsBareList {
+ return nil, nil
+ }
+ return nil, err
+ }
+ return children, nil
}
// getChildren returns a list of at most "max" imageIDs that depend on the image
func (i *Image) getChildren(ctx context.Context, max int) ([]string, error) {
var children []string
+
+ if _, err := i.toImageRef(ctx); err != nil {
+ return nil, nil
+ }
+
images, err := i.imageruntime.GetImages()
if err != nil {
return nil, err
@@ -1301,6 +1372,9 @@ func (i *Image) Comment(ctx context.Context, manifestType string) (string, error
}
ociv1Img, err := i.ociv1Image(ctx)
if err != nil {
+ if errors.Cause(err) == ErrImageIsBareList {
+ return "", nil
+ }
return "", err
}
if len(ociv1Img.History) > 0 {
diff --git a/libpod/image/image_test.go b/libpod/image/image_test.go
index ef39d09c3..5aff7d860 100644
--- a/libpod/image/image_test.go
+++ b/libpod/image/image_test.go
@@ -247,6 +247,19 @@ func TestImage_RepoDigests(t *testing.T) {
}
assert.Equal(t, test.expected, actual)
+
+ image = &Image{
+ image: &storage.Image{
+ Names: test.names,
+ Digests: []digest.Digest{dgst},
+ },
+ }
+ actual, err = image.RepoDigests()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ assert.Equal(t, test.expected, actual)
})
}
}
diff --git a/libpod/image/parts.go b/libpod/image/parts.go
index 69bc44cdd..d4677f935 100644
--- a/libpod/image/parts.go
+++ b/libpod/image/parts.go
@@ -3,7 +3,7 @@ package image
import (
"strings"
- "github.com/containers/image/v4/docker/reference"
+ "github.com/containers/image/v5/docker/reference"
"github.com/pkg/errors"
)
diff --git a/libpod/image/pull.go b/libpod/image/pull.go
index 36950b6f3..7f5dc33b9 100644
--- a/libpod/image/pull.go
+++ b/libpod/image/pull.go
@@ -7,17 +7,17 @@ import (
"path/filepath"
"strings"
- cp "github.com/containers/image/v4/copy"
- "github.com/containers/image/v4/directory"
- "github.com/containers/image/v4/docker"
- dockerarchive "github.com/containers/image/v4/docker/archive"
- "github.com/containers/image/v4/docker/tarfile"
- ociarchive "github.com/containers/image/v4/oci/archive"
- oci "github.com/containers/image/v4/oci/layout"
- is "github.com/containers/image/v4/storage"
- "github.com/containers/image/v4/transports"
- "github.com/containers/image/v4/transports/alltransports"
- "github.com/containers/image/v4/types"
+ cp "github.com/containers/image/v5/copy"
+ "github.com/containers/image/v5/directory"
+ "github.com/containers/image/v5/docker"
+ dockerarchive "github.com/containers/image/v5/docker/archive"
+ "github.com/containers/image/v5/docker/tarfile"
+ ociarchive "github.com/containers/image/v5/oci/archive"
+ oci "github.com/containers/image/v5/oci/layout"
+ is "github.com/containers/image/v5/storage"
+ "github.com/containers/image/v5/transports"
+ "github.com/containers/image/v5/transports/alltransports"
+ "github.com/containers/image/v5/types"
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/pkg/registries"
"github.com/hashicorp/go-multierror"
@@ -223,6 +223,10 @@ func (ir *Runtime) pullImageFromHeuristicSource(ctx context.Context, inputName s
var goal *pullGoal
sc := GetSystemContext(signaturePolicyPath, authfile, false)
+ if dockerOptions != nil {
+ sc.OSChoice = dockerOptions.OSChoice
+ sc.ArchitectureChoice = dockerOptions.ArchitectureChoice
+ }
sc.BlobInfoCacheDir = filepath.Join(ir.store.GraphRoot(), "cache")
srcRef, err := alltransports.ParseImageName(inputName)
if err != nil {
@@ -246,6 +250,10 @@ func (ir *Runtime) pullImageFromReference(ctx context.Context, srcRef types.Imag
defer span.Finish()
sc := GetSystemContext(signaturePolicyPath, authfile, false)
+ if dockerOptions != nil {
+ sc.OSChoice = dockerOptions.OSChoice
+ sc.ArchitectureChoice = dockerOptions.ArchitectureChoice
+ }
goal, err := ir.pullGoalFromImageReference(ctx, srcRef, transports.ImageName(srcRef), sc)
if err != nil {
return nil, errors.Wrapf(err, "error determining pull goal for image %q", transports.ImageName(srcRef))
diff --git a/libpod/image/pull_test.go b/libpod/image/pull_test.go
index 131b8b1f6..0046cdfef 100644
--- a/libpod/image/pull_test.go
+++ b/libpod/image/pull_test.go
@@ -9,9 +9,9 @@ import (
"strings"
"testing"
- "github.com/containers/image/v4/transports"
- "github.com/containers/image/v4/transports/alltransports"
- "github.com/containers/image/v4/types"
+ "github.com/containers/image/v5/transports"
+ "github.com/containers/image/v5/transports/alltransports"
+ "github.com/containers/image/v5/types"
"github.com/containers/storage"
"github.com/containers/storage/pkg/idtools"
"github.com/stretchr/testify/assert"
diff --git a/libpod/image/search.go b/libpod/image/search.go
index 0313c2d6e..fd29dac45 100644
--- a/libpod/image/search.go
+++ b/libpod/image/search.go
@@ -6,8 +6,8 @@ import (
"strings"
"sync"
- "github.com/containers/image/v4/docker"
- "github.com/containers/image/v4/types"
+ "github.com/containers/image/v5/docker"
+ "github.com/containers/image/v5/types"
sysreg "github.com/containers/libpod/pkg/registries"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
diff --git a/libpod/image/utils.go b/libpod/image/utils.go
index e4ff1cfc4..b7ea63c66 100644
--- a/libpod/image/utils.go
+++ b/libpod/image/utils.go
@@ -7,10 +7,10 @@ import (
"regexp"
"strings"
- cp "github.com/containers/image/v4/copy"
- "github.com/containers/image/v4/docker/reference"
- "github.com/containers/image/v4/signature"
- "github.com/containers/image/v4/types"
+ cp "github.com/containers/image/v5/copy"
+ "github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/signature"
+ "github.com/containers/image/v5/types"
"github.com/containers/storage"
"github.com/pkg/errors"
)
@@ -87,18 +87,18 @@ func hasTransport(image string) bool {
}
// ReposToMap parses the specified repotags and returns a map with repositories
-// as keys and the corresponding arrays of tags as values.
-func ReposToMap(repotags []string) (map[string][]string, error) {
- // map format is repo -> tag
+// as keys and the corresponding arrays of tags or digests-as-strings as values.
+func ReposToMap(names []string) (map[string][]string, error) {
+ // map format is repo -> []tag-or-digest
repos := make(map[string][]string)
- for _, repo := range repotags {
+ for _, name := range names {
var repository, tag string
- if len(repo) > 0 {
- named, err := reference.ParseNormalizedNamed(repo)
- repository = named.Name()
+ if len(name) > 0 {
+ named, err := reference.ParseNormalizedNamed(name)
if err != nil {
return nil, err
}
+ repository = named.Name()
if ref, ok := named.(reference.NamedTagged); ok {
tag = ref.Tag()
} else if ref, ok := named.(reference.Canonical); ok {
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 4360c8c15..daa0619a2 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -5,6 +5,7 @@ package libpod
import (
"crypto/rand"
"fmt"
+ "io/ioutil"
"net"
"os"
"os/exec"
@@ -131,7 +132,7 @@ func checkSlirpFlags(path string) (bool, bool, bool, error) {
cmd := exec.Command(path, "--help")
out, err := cmd.CombinedOutput()
if err != nil {
- return false, false, false, err
+ return false, false, false, errors.Wrapf(err, "slirp4netns %q", out)
}
return strings.Contains(string(out), "--disable-host-loopback"), strings.Contains(string(out), "--mtu"), strings.Contains(string(out), "--enable-sandbox"), nil
}
@@ -158,6 +159,7 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) {
havePortMapping := len(ctr.Config().PortMappings) > 0
apiSocket := filepath.Join(ctr.runtime.config.TmpDir, fmt.Sprintf("%s.net", ctr.config.ID))
+ logPath := filepath.Join(ctr.runtime.config.TmpDir, fmt.Sprintf("slirp4netns-%s.log", ctr.config.ID))
cmdArgs := []string{}
if havePortMapping {
@@ -165,7 +167,7 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) {
}
dhp, mtu, sandbox, err := checkSlirpFlags(path)
if err != nil {
- return errors.Wrapf(err, "error checking slirp4netns binary %s", path)
+ return errors.Wrapf(err, "error checking slirp4netns binary %s: %q", path, err)
}
if dhp {
cmdArgs = append(cmdArgs, "--disable-host-loopback")
@@ -210,6 +212,18 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) {
// Leak one end of the pipe in slirp4netns, the other will be sent to conmon
cmd.ExtraFiles = append(cmd.ExtraFiles, ctr.rootlessSlirpSyncR, syncW)
+ logFile, err := os.Create(logPath)
+ if err != nil {
+ return errors.Wrapf(err, "failed to open slirp4netns log file %s", logPath)
+ }
+ defer logFile.Close()
+ // Unlink immediately the file so we won't need to worry about cleaning it up later.
+ // It is still accessible through the open fd logFile.
+ if err := os.Remove(logPath); err != nil {
+ return errors.Wrapf(err, "delete file %s", logPath)
+ }
+ cmd.Stdout = logFile
+ cmd.Stderr = logFile
if err := cmd.Start(); err != nil {
return errors.Wrapf(err, "failed to start slirp4netns process")
}
@@ -238,7 +252,15 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) {
continue
}
if status.Exited() {
- return errors.New("slirp4netns failed")
+ // Seek at the beginning of the file and read all its content
+ if _, err := logFile.Seek(0, 0); err != nil {
+ logrus.Errorf("could not seek log file: %q", err)
+ }
+ logContent, err := ioutil.ReadAll(logFile)
+ if err != nil {
+ return errors.Wrapf(err, "slirp4netns failed")
+ }
+ return errors.Errorf("slirp4netns failed: %q", logContent)
}
if status.Signaled() {
return errors.New("slirp4netns killed by signal")
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index 448e05bdf..2798c3043 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -1023,8 +1023,8 @@ func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, se
if err != nil {
return nil, err
}
-
pspec := c.config.Spec.Process
+ pspec.SelinuxLabel = c.config.ProcessLabel
pspec.Args = cmd
// We need to default this to false else it will inherit terminal as true
// from the container.
diff --git a/libpod/options.go b/libpod/options.go
index f779b0413..f79c75e98 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -7,7 +7,7 @@ import (
"regexp"
"syscall"
- "github.com/containers/image/v4/manifest"
+ "github.com/containers/image/v5/manifest"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/pkg/namespaces"
diff --git a/libpod/runtime.go b/libpod/runtime.go
index a06b2bb51..300477c09 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -16,8 +16,8 @@ import (
"syscall"
"github.com/BurntSushi/toml"
- is "github.com/containers/image/v4/storage"
- "github.com/containers/image/v4/types"
+ is "github.com/containers/image/v5/storage"
+ "github.com/containers/image/v5/types"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/libpod/image"
@@ -84,6 +84,15 @@ var (
// DefaultDetachKeys is the default keys sequence for detaching a
// container
DefaultDetachKeys = "ctrl-p,ctrl-q"
+
+ // minConmonMajor is the major version required for conmon
+ minConmonMajor = 2
+
+ // minConmonMinor is the minor version required for conmon
+ minConmonMinor = 0
+
+ // minConmonPatch is the sub-minor version required for conmon
+ minConmonPatch = 1
)
// A RuntimeOption is a functional option which alters the Runtime created by
@@ -788,6 +797,7 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) {
// probeConmon calls conmon --version and verifies it is a new enough version for
// the runtime expectations podman currently has
func probeConmon(conmonBinary string) error {
+ versionFormatErr := "conmon version changed format"
cmd := exec.Command(conmonBinary, "--version")
var out bytes.Buffer
cmd.Stdout = &out
@@ -799,19 +809,40 @@ func probeConmon(conmonBinary string) error {
matches := r.FindStringSubmatch(out.String())
if len(matches) != 4 {
- return errors.Wrapf(err, "conmon version changed format")
+ return errors.Wrapf(err, versionFormatErr)
}
major, err := strconv.Atoi(matches[1])
- if err != nil || major < 1 {
+ if err != nil {
+ return errors.Wrapf(err, versionFormatErr)
+ }
+ if major < minConmonMajor {
return define.ErrConmonOutdated
}
- // conmon used to be shipped with CRI-O, and was versioned along with it.
- // even though the conmon that came with crio-1.9 to crio-1.15 has a higher
- // version number than conmon 1.0.0, 1.0.0 is newer, so we need this check
+ if major > minConmonMajor {
+ return nil
+ }
+
minor, err := strconv.Atoi(matches[2])
- if err != nil || minor > 9 {
+ if err != nil {
+ return errors.Wrapf(err, versionFormatErr)
+ }
+ if minor < minConmonMinor {
return define.ErrConmonOutdated
}
+ if minor > minConmonMinor {
+ return nil
+ }
+
+ patch, err := strconv.Atoi(matches[3])
+ if err != nil {
+ return errors.Wrapf(err, versionFormatErr)
+ }
+ if patch < minConmonPatch {
+ return define.ErrConmonOutdated
+ }
+ if patch > minConmonPatch {
+ return nil
+ }
return nil
}
@@ -871,7 +902,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) {
if !foundConmon {
if foundOutdatedConmon {
- return errors.Wrapf(define.ErrConmonOutdated, "please update to v1.0.0 or later")
+ return errors.Errorf("please update to v%d.%d.%d or later: %v", minConmonMajor, minConmonMinor, minConmonPatch, define.ErrConmonOutdated)
}
return errors.Wrapf(define.ErrInvalidArg,
"could not find a working conmon binary (configured options: %v)",
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index 35c0cdfb9..f2784c07d 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -17,9 +17,9 @@ import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
- "github.com/containers/image/v4/directory"
- dockerarchive "github.com/containers/image/v4/docker/archive"
- ociarchive "github.com/containers/image/v4/oci/archive"
+ "github.com/containers/image/v5/directory"
+ dockerarchive "github.com/containers/image/v5/docker/archive"
+ ociarchive "github.com/containers/image/v5/oci/archive"
"github.com/opencontainers/image-spec/specs-go/v1"
)
diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go
index ba4fff4be..5b05acea4 100644
--- a/libpod/runtime_volume_linux.go
+++ b/libpod/runtime_volume_linux.go
@@ -48,6 +48,15 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption)
}
volume.config.CreatedTime = time.Now()
+ // Check if volume with given name exists.
+ exists, err := r.state.HasVolume(volume.config.Name)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error checking if volume with name %s exists", volume.config.Name)
+ }
+ if exists {
+ return nil, errors.Wrapf(define.ErrVolumeExists, "volume with name %s already exists", volume.config.Name)
+ }
+
if volume.config.Driver == define.VolumeDriverLocal {
logrus.Debugf("Validating options for local driver")
// Validate options
diff --git a/libpod/storage.go b/libpod/storage.go
index 9a06c96fd..6375d031b 100644
--- a/libpod/storage.go
+++ b/libpod/storage.go
@@ -4,8 +4,8 @@ import (
"context"
"time"
- istorage "github.com/containers/image/v4/storage"
- "github.com/containers/image/v4/types"
+ istorage "github.com/containers/image/v5/storage"
+ "github.com/containers/image/v5/types"
"github.com/containers/libpod/libpod/define"
"github.com/containers/storage"
"github.com/opencontainers/image-spec/specs-go/v1"
diff --git a/libpod/util.go b/libpod/util.go
index 84fd490bf..5ae5ab491 100644
--- a/libpod/util.go
+++ b/libpod/util.go
@@ -189,3 +189,20 @@ func programVersion(mountProgram string) (string, error) {
}
return strings.TrimSuffix(output, "\n"), nil
}
+
+func DefaultSeccompPath() (string, error) {
+ _, err := os.Stat(SeccompOverridePath)
+ if err == nil {
+ return SeccompOverridePath, nil
+ }
+ if !os.IsNotExist(err) {
+ return "", errors.Wrapf(err, "can't check if %q exists", SeccompOverridePath)
+ }
+ if _, err := os.Stat(SeccompDefaultPath); err != nil {
+ if !os.IsNotExist(err) {
+ return "", errors.Wrapf(err, "can't check if %q exists", SeccompDefaultPath)
+ }
+ return "", nil
+ }
+ return SeccompDefaultPath, nil
+}