summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/play/kube.go9
-rw-r--r--go.mod2
-rw-r--r--go.sum3
-rw-r--r--libpod/container.go8
-rw-r--r--libpod/container_config.go3
-rw-r--r--libpod/container_inspect.go1
-rw-r--r--libpod/container_validate.go8
-rw-r--r--libpod/define/container_inspect.go1
-rw-r--r--libpod/options.go38
-rw-r--r--libpod/pod.go7
-rw-r--r--libpod/pod_api.go22
-rw-r--r--libpod/runtime_img.go2
-rw-r--r--libpod/runtime_pod_linux.go4
-rw-r--r--libpod/service.go213
-rw-r--r--pkg/domain/entities/play.go2
-rw-r--r--pkg/domain/infra/abi/play.go82
-rw-r--r--pkg/specgen/generate/pause_image.go89
-rw-r--r--pkg/specgen/generate/pod_create.go104
-rw-r--r--pkg/specgen/podspecgen.go3
-rw-r--r--test/e2e/containers_conf_test.go7
-rw-r--r--test/system/200-pod.bats13
-rw-r--r--test/system/700-play.bats55
-rw-r--r--test/system/helpers.bash13
-rw-r--r--vendor/github.com/containers/common/libimage/image.go2
-rw-r--r--vendor/github.com/containers/common/libimage/load.go6
-rw-r--r--vendor/github.com/containers/common/libimage/normalize.go2
-rw-r--r--vendor/github.com/containers/common/libimage/pull.go2
-rw-r--r--vendor/github.com/containers/common/libimage/runtime.go39
-rw-r--r--vendor/github.com/containers/common/libnetwork/cni/config.go2
-rw-r--r--vendor/github.com/containers/common/libnetwork/cni/run.go2
-rw-r--r--vendor/github.com/containers/common/libnetwork/internal/util/create.go2
-rw-r--r--vendor/github.com/containers/common/libnetwork/netavark/config.go2
-rw-r--r--vendor/github.com/containers/common/libnetwork/network/interface.go3
-rw-r--r--vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go8
-rw-r--r--vendor/github.com/containers/common/pkg/auth/auth.go6
-rw-r--r--vendor/github.com/containers/common/pkg/capabilities/capabilities.go9
-rw-r--r--vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go29
-rw-r--r--vendor/github.com/containers/common/pkg/completion/completion.go2
-rw-r--r--vendor/github.com/containers/common/pkg/config/config.go9
-rw-r--r--vendor/github.com/containers/common/pkg/filters/filters.go6
-rw-r--r--vendor/github.com/containers/common/pkg/machine/machine.go4
-rw-r--r--vendor/github.com/containers/common/pkg/parse/parse_unix.go4
-rw-r--r--vendor/github.com/containers/common/pkg/retry/retry.go5
-rw-r--r--vendor/github.com/containers/common/pkg/seccomp/conversion.go11
-rw-r--r--vendor/github.com/containers/common/pkg/seccomp/filter.go2
-rw-r--r--vendor/github.com/containers/common/pkg/seccomp/types.go1
-rw-r--r--vendor/github.com/containers/common/pkg/secrets/filedriver/filedriver.go5
-rw-r--r--vendor/github.com/containers/common/pkg/secrets/secrets.go11
-rw-r--r--vendor/github.com/containers/common/pkg/secrets/secretsdb.go3
-rw-r--r--vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go2
-rw-r--r--vendor/github.com/containers/common/pkg/sysinfo/nummem_linux.go2
-rw-r--r--vendor/github.com/containers/common/version/version.go2
-rw-r--r--vendor/modules.txt2
53 files changed, 691 insertions, 183 deletions
diff --git a/cmd/podman/play/kube.go b/cmd/podman/play/kube.go
index 5fe059139..f5b121009 100644
--- a/cmd/podman/play/kube.go
+++ b/cmd/podman/play/kube.go
@@ -139,6 +139,15 @@ func init() {
flags.StringVar(&kubeOptions.ContextDir, contextDirFlagName, "", "Path to top level of context directory")
_ = kubeCmd.RegisterFlagCompletionFunc(contextDirFlagName, completion.AutocompleteDefault)
+ // NOTE: The service-container flag is marked as hidden as it
+ // is purely designed for running play-kube in systemd units.
+ // It is not something users should need to know or care about.
+ //
+ // Having a flag rather than an env variable is cleaner.
+ serviceFlagName := "service-container"
+ flags.BoolVar(&kubeOptions.ServiceContainer, serviceFlagName, false, "Starts a service container before all pods")
+ _ = flags.MarkHidden("service-container")
+
flags.StringVar(&kubeOptions.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
_ = flags.MarkHidden("signature-policy")
diff --git a/go.mod b/go.mod
index e5f11838c..38a066c53 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@ require (
github.com/containernetworking/cni v1.1.0
github.com/containernetworking/plugins v1.1.1
github.com/containers/buildah v1.26.1
- github.com/containers/common v0.48.0
+ github.com/containers/common v0.48.1-0.20220510094751-400832f41771
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.21.2-0.20220511203756-fe4fd4ed8be4
github.com/containers/ocicrypt v1.1.4-0.20220428134531-566b808bdf6f
diff --git a/go.sum b/go.sum
index 5c2fca7d7..494d892da 100644
--- a/go.sum
+++ b/go.sum
@@ -339,8 +339,9 @@ github.com/containernetworking/plugins v1.1.1 h1:+AGfFigZ5TiQH00vhR8qPeSatj53eNG
github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8=
github.com/containers/buildah v1.26.1 h1:D65Vuo+orsI14WWtJhSX6KrpgBBa7+hveVWevzG8p8E=
github.com/containers/buildah v1.26.1/go.mod h1:CsWSG8OpJd8v3mlLREJzVAOBgC93DjRNALUVHoi8QsY=
-github.com/containers/common v0.48.0 h1:997nnXBZ+eNpfSM7L4SxhhZubQrfEyw3jRyNMTSsNlw=
github.com/containers/common v0.48.0/go.mod h1:zPLZCfLXfnd1jI0QRsD4By54fP4k1+ifQs+tulIe3o0=
+github.com/containers/common v0.48.1-0.20220510094751-400832f41771 h1:rHd882jzJK1fIXCJWvc1zTX5CIv2aOyzzkqj6mezLLw=
+github.com/containers/common v0.48.1-0.20220510094751-400832f41771/go.mod h1:xapcAN0NbthUpjBv2UWZ5uiCGBlYbuj0o1Qg4hCaiL8=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.21.1/go.mod h1:zl35egpcDQa79IEXIuoUe1bW+D1pdxRxYjNlyb3YiXw=
diff --git a/libpod/container.go b/libpod/container.go
index d7af9a100..64b4453fb 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -211,6 +211,14 @@ type ContainerState struct {
// network and an interface names
NetInterfaceDescriptions ContainerNetworkDescriptions `json:"networkDescriptions,omitempty"`
+ // Service indicates that container is the service container of a
+ // service. A service consists of one or more pods. The service
+ // container is started before all pods and is stopped when the last
+ // pod stops. The service container allows for tracking and managing
+ // the entire life cycle of service which may be started via
+ // `podman-play-kube`.
+ Service Service
+
// containerPlatformState holds platform-specific container state.
containerPlatformState
diff --git a/libpod/container_config.go b/libpod/container_config.go
index 371a1dec0..3e85ad4d5 100644
--- a/libpod/container_config.go
+++ b/libpod/container_config.go
@@ -382,6 +382,9 @@ type ContainerMiscConfig struct {
// IsInfra is a bool indicating whether this container is an infra container used for
// sharing kernel namespaces in a pod
IsInfra bool `json:"pause"`
+ // IsService is a bool indicating whether this container is a service container used for
+ // tracking the life cycle of K8s service.
+ IsService bool `json:"isService"`
// SdNotifyMode tells libpod what to do with a NOTIFY_SOCKET if passed
SdNotifyMode string `json:"sdnotifyMode,omitempty"`
// Systemd tells libpod to setup the container in systemd mode, a value of nil denotes false
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 76e0e9e13..5d809644d 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -171,6 +171,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver
Mounts: inspectMounts,
Dependencies: c.Dependencies(),
IsInfra: c.IsInfra(),
+ IsService: c.isService(),
}
if c.state.ConfigPath != "" {
diff --git a/libpod/container_validate.go b/libpod/container_validate.go
index c6c9a4c6d..d939c94e6 100644
--- a/libpod/container_validate.go
+++ b/libpod/container_validate.go
@@ -1,6 +1,8 @@
package libpod
import (
+ "fmt"
+
"github.com/containers/podman/v4/libpod/define"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
@@ -27,6 +29,12 @@ func (c *Container) validate() error {
return errors.Wrapf(define.ErrInvalidArg, "must set root filesystem source to either image or rootfs")
}
+ // A container cannot be marked as an infra and service container at
+ // the same time.
+ if c.IsInfra() && c.isService() {
+ return fmt.Errorf("cannot be infra and service container at the same time: %w", define.ErrInvalidArg)
+ }
+
// Cannot make a network namespace if we are joining another container's
// network namespace
if c.config.CreateNetNS && c.config.NetNsCtr != "" {
diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go
index 6cdffb8b7..e7b82d654 100644
--- a/libpod/define/container_inspect.go
+++ b/libpod/define/container_inspect.go
@@ -683,6 +683,7 @@ type InspectContainerData struct {
NetworkSettings *InspectNetworkSettings `json:"NetworkSettings"`
Namespace string `json:"Namespace"`
IsInfra bool `json:"IsInfra"`
+ IsService bool `json:"IsService"`
Config *InspectContainerConfig `json:"Config"`
HostConfig *InspectContainerHostConfig `json:"HostConfig"`
}
diff --git a/libpod/options.go b/libpod/options.go
index 9b83cb76a..feb89510f 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1,6 +1,7 @@
package libpod
import (
+ "fmt"
"net"
"os"
"path/filepath"
@@ -1477,7 +1478,7 @@ func WithCreateCommand(cmd []string) CtrCreateOption {
}
}
-// withIsInfra allows us to dfferentiate between infra containers and regular containers
+// withIsInfra allows us to dfferentiate between infra containers and other containers
// within the container config
func withIsInfra() CtrCreateOption {
return func(ctr *Container) error {
@@ -1491,6 +1492,20 @@ func withIsInfra() CtrCreateOption {
}
}
+// WithIsService allows us to dfferentiate between service containers and other container
+// within the container config
+func WithIsService() CtrCreateOption {
+ return func(ctr *Container) error {
+ if ctr.valid {
+ return define.ErrCtrFinalized
+ }
+
+ ctr.config.IsService = true
+
+ return nil
+ }
+}
+
// WithCreateWorkingDir tells Podman to create the container's working directory
// if it does not exist.
func WithCreateWorkingDir() CtrCreateOption {
@@ -2081,6 +2096,27 @@ func WithInfraContainer() PodCreateOption {
}
}
+// WithServiceContainer associates the specified service container ID with the pod.
+func WithServiceContainer(id string) PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ ctr, err := pod.runtime.LookupContainer(id)
+ if err != nil {
+ return fmt.Errorf("looking up service container: %w", err)
+ }
+
+ if err := ctr.addServicePodLocked(pod.ID()); err != nil {
+ return fmt.Errorf("associating service container %s with pod %s: %w", id, pod.ID(), err)
+ }
+
+ pod.config.ServiceContainerID = id
+ return nil
+ }
+}
+
// WithVolatile sets the volatile flag for the container storage.
// The option can potentially cause data loss when used on a container that must survive a machine reboot.
func WithVolatile() CtrCreateOption {
diff --git a/libpod/pod.go b/libpod/pod.go
index 2211d5be7..3c8dc43d4 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -64,6 +64,13 @@ type PodConfig struct {
HasInfra bool `json:"hasInfra,omitempty"`
+ // ServiceContainerID is the main container of a service. A service
+ // consists of one or more pods. The service container is started
+ // before all pods and is stopped when the last pod stops.
+ // The service container allows for tracking and managing the entire
+ // life cycle of service which may be started via `podman-play-kube`.
+ ServiceContainerID string `json:"serviceContainerID,omitempty"`
+
// Time pod was created
CreatedTime time.Time `json:"created"`
diff --git a/libpod/pod_api.go b/libpod/pod_api.go
index 73b28822b..eede896a9 100644
--- a/libpod/pod_api.go
+++ b/libpod/pod_api.go
@@ -75,6 +75,10 @@ func (p *Pod) Start(ctx context.Context) (map[string]error, error) {
return nil, define.ErrPodRemoved
}
+ if err := p.maybeStartServiceContainer(ctx); err != nil {
+ return nil, err
+ }
+
// Before "regular" containers start in the pod, all init containers
// must have run and exited successfully.
if err := p.startInitContainers(ctx); err != nil {
@@ -197,6 +201,11 @@ func (p *Pod) stopWithTimeout(ctx context.Context, cleanup bool, timeout int) (m
if len(ctrErrors) > 0 {
return ctrErrors, errors.Wrapf(define.ErrPodPartialFail, "error stopping some containers")
}
+
+ if err := p.maybeStopServiceContainer(); err != nil {
+ return nil, err
+ }
+
return nil, nil
}
@@ -297,6 +306,10 @@ func (p *Pod) Cleanup(ctx context.Context) (map[string]error, error) {
return ctrErrors, errors.Wrapf(define.ErrPodPartialFail, "error cleaning up some containers")
}
+ if err := p.maybeStopServiceContainer(); err != nil {
+ return nil, err
+ }
+
return nil, nil
}
@@ -443,6 +456,10 @@ func (p *Pod) Restart(ctx context.Context) (map[string]error, error) {
return nil, define.ErrPodRemoved
}
+ if err := p.maybeStartServiceContainer(ctx); err != nil {
+ return nil, err
+ }
+
allCtrs, err := p.runtime.state.PodContainers(p)
if err != nil {
return nil, err
@@ -530,6 +547,11 @@ func (p *Pod) Kill(ctx context.Context, signal uint) (map[string]error, error) {
if len(ctrErrors) > 0 {
return ctrErrors, errors.Wrapf(define.ErrPodPartialFail, "error killing some containers")
}
+
+ if err := p.maybeStopServiceContainer(); err != nil {
+ return nil, err
+ }
+
return nil, nil
}
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index 54eadf6b8..b13482722 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -40,7 +40,7 @@ func (r *Runtime) RemoveContainersForImageCallback(ctx context.Context) libimage
if ctr.config.IsInfra {
pod, err := r.state.Pod(ctr.config.Pod)
if err != nil {
- return errors.Wrapf(err, "container %s is in pod %s, but pod cannot be retrieved", ctr.ID(), pod.ID())
+ return errors.Wrapf(err, "container %s is in pod %s, but pod cannot be retrieved", ctr.ID(), ctr.config.Pod)
}
if err := r.removePod(ctx, pod, true, true, timeout); err != nil {
return errors.Wrapf(err, "removing image %s: container %s using image could not be removed", imageID, ctr.ID())
diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go
index 62ec7df60..dcc3a044f 100644
--- a/libpod/runtime_pod_linux.go
+++ b/libpod/runtime_pod_linux.go
@@ -380,6 +380,10 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool,
}
}
+ if err := p.maybeRemoveServiceContainer(); err != nil {
+ return err
+ }
+
// Remove pod from state
if err := r.state.RemovePod(p); err != nil {
if removalErr != nil {
diff --git a/libpod/service.go b/libpod/service.go
new file mode 100644
index 000000000..ad147e87b
--- /dev/null
+++ b/libpod/service.go
@@ -0,0 +1,213 @@
+package libpod
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/podman/v4/libpod/define"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+// A service consists of one or more pods. The service container is started
+// before all pods and is stopped when the last pod stops. The service
+// container allows for tracking and managing the entire life cycle of service
+// which may be started via `podman-play-kube`.
+type Service struct {
+ // Pods running as part of the service.
+ Pods []string `json:"servicePods"`
+}
+
+// Indicates whether the pod is associated with a service container.
+// The pod is expected to be updated and locked.
+func (p *Pod) hasServiceContainer() bool {
+ return p.config.ServiceContainerID != ""
+}
+
+// Returns the pod's service container.
+// The pod is expected to be updated and locked.
+func (p *Pod) serviceContainer() (*Container, error) {
+ id := p.config.ServiceContainerID
+ if id == "" {
+ return nil, errors.Wrap(define.ErrNoSuchCtr, "pod has no service container")
+ }
+ return p.runtime.state.Container(id)
+}
+
+// ServiceContainer returns the service container.
+func (p *Pod) ServiceContainer() (*Container, error) {
+ p.lock.Lock()
+ defer p.lock.Unlock()
+ if err := p.updatePod(); err != nil {
+ return nil, err
+ }
+ return p.serviceContainer()
+}
+
+func (c *Container) addServicePodLocked(id string) error {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+ if err := c.syncContainer(); err != nil {
+ return err
+ }
+ c.state.Service.Pods = append(c.state.Service.Pods, id)
+ return c.save()
+}
+
+func (c *Container) isService() bool {
+ return c.config.IsService
+}
+
+// canStopServiceContainer returns true if all pods of the service are stopped.
+// Note that the method acquires the container lock.
+func (c *Container) canStopServiceContainerLocked() (bool, error) {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+ if err := c.syncContainer(); err != nil {
+ return false, err
+ }
+
+ if !c.isService() {
+ return false, fmt.Errorf("internal error: checking service: container %s is not a service container", c.ID())
+ }
+
+ for _, id := range c.state.Service.Pods {
+ pod, err := c.runtime.LookupPod(id)
+ if err != nil {
+ if errors.Is(err, define.ErrNoSuchPod) {
+ continue
+ }
+ return false, err
+ }
+
+ status, err := pod.GetPodStatus()
+ if err != nil {
+ return false, err
+ }
+
+ // We can only stop the service if all pods are done.
+ switch status {
+ case define.PodStateStopped, define.PodStateExited, define.PodStateErrored:
+ continue
+ default:
+ return false, nil
+ }
+ }
+
+ return true, nil
+}
+
+// Checks whether the service container can be stopped and does so.
+func (p *Pod) maybeStopServiceContainer() error {
+ if !p.hasServiceContainer() {
+ return nil
+ }
+
+ serviceCtr, err := p.serviceContainer()
+ if err != nil {
+ return fmt.Errorf("getting pod's service container: %w", err)
+ }
+ // Checking whether the service can be stopped must be done in
+ // the runtime's work queue to resolve ABBA dead locks in the
+ // pod->container->servicePods hierarchy.
+ p.runtime.queueWork(func() {
+ logrus.Debugf("Pod %s has a service %s: checking if it can be stopped", p.ID(), serviceCtr.ID())
+ canStop, err := serviceCtr.canStopServiceContainerLocked()
+ if err != nil {
+ logrus.Errorf("Checking whether service of container %s can be stopped: %v", serviceCtr.ID(), err)
+ return
+ }
+ if !canStop {
+ return
+ }
+ logrus.Debugf("Stopping service container %s", serviceCtr.ID())
+ if err := serviceCtr.Stop(); err != nil {
+ logrus.Errorf("Stopping service container %s: %v", serviceCtr.ID(), err)
+ }
+ })
+ return nil
+}
+
+// Starts the pod's service container if it's not already running.
+func (p *Pod) maybeStartServiceContainer(ctx context.Context) error {
+ if !p.hasServiceContainer() {
+ return nil
+ }
+
+ serviceCtr, err := p.serviceContainer()
+ if err != nil {
+ return fmt.Errorf("getting pod's service container: %w", err)
+ }
+
+ serviceCtr.lock.Lock()
+ defer serviceCtr.lock.Unlock()
+
+ if err := serviceCtr.syncContainer(); err != nil {
+ return err
+ }
+
+ if serviceCtr.state.State == define.ContainerStateRunning {
+ return nil
+ }
+
+ // Restart will reinit among other things.
+ return serviceCtr.restartWithTimeout(ctx, 0)
+}
+
+// canRemoveServiceContainer returns true if all pods of the service are removed.
+// Note that the method acquires the container lock.
+func (c *Container) canRemoveServiceContainerLocked() (bool, error) {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+ if err := c.syncContainer(); err != nil {
+ return false, err
+ }
+
+ if !c.isService() {
+ return false, fmt.Errorf("internal error: checking service: container %s is not a service container", c.ID())
+ }
+
+ for _, id := range c.state.Service.Pods {
+ if _, err := c.runtime.LookupPod(id); err != nil {
+ if errors.Is(err, define.ErrNoSuchPod) {
+ continue
+ }
+ return false, err
+ }
+ return false, nil
+ }
+
+ return true, nil
+}
+
+// Checks whether the service container can be removed and does so.
+func (p *Pod) maybeRemoveServiceContainer() error {
+ if !p.hasServiceContainer() {
+ return nil
+ }
+
+ serviceCtr, err := p.serviceContainer()
+ if err != nil {
+ return fmt.Errorf("getting pod's service container: %w", err)
+ }
+ // Checking whether the service can be stopped must be done in
+ // the runtime's work queue to resolve ABBA dead locks in the
+ // pod->container->servicePods hierarchy.
+ p.runtime.queueWork(func() {
+ logrus.Debugf("Pod %s has a service %s: checking if it can be removed", p.ID(), serviceCtr.ID())
+ canRemove, err := serviceCtr.canRemoveServiceContainerLocked()
+ if err != nil {
+ logrus.Errorf("Checking whether service of container %s can be removed: %v", serviceCtr.ID(), err)
+ return
+ }
+ if !canRemove {
+ return
+ }
+ timeout := uint(0)
+ logrus.Debugf("Removing service container %s", serviceCtr.ID())
+ if err := p.runtime.RemoveContainer(context.Background(), serviceCtr, true, false, &timeout); err != nil {
+ logrus.Errorf("Removing service container %s: %v", serviceCtr.ID(), err)
+ }
+ })
+ return nil
+}
diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go
index bf7c33f2b..f1ba21650 100644
--- a/pkg/domain/entities/play.go
+++ b/pkg/domain/entities/play.go
@@ -54,6 +54,8 @@ type PlayKubeOptions struct {
LogOptions []string
// Start - don't start the pod if false
Start types.OptionalBool
+ // ServiceContainer - creates a service container that is started before and is stopped after all pods.
+ ServiceContainer bool
// Userns - define the user namespace to use.
Userns string
}
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index 019361694..420d51483 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -28,12 +28,54 @@ import (
"github.com/containers/podman/v4/pkg/specgenutil"
"github.com/containers/podman/v4/pkg/util"
"github.com/ghodss/yaml"
+ "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
yamlv2 "gopkg.in/yaml.v2"
)
-func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
+// createServiceContainer creates a container that can later on
+// be associated with the pods of a K8s yaml. It will be started along with
+// the first pod.
+func (ic *ContainerEngine) createServiceContainer(ctx context.Context, name string) (*libpod.Container, error) {
+ // Similar to infra containers, a service container is using the pause image.
+ image, err := generate.PullOrBuildInfraImage(ic.Libpod, "")
+ if err != nil {
+ return nil, fmt.Errorf("image for service container: %w", err)
+ }
+
+ ctrOpts := entities.ContainerCreateOptions{
+ // Inherited from infra containers
+ ImageVolume: "bind",
+ IsInfra: false,
+ MemorySwappiness: -1,
+ // No need to spin up slirp etc.
+ Net: &entities.NetOptions{Network: specgen.Namespace{NSMode: specgen.NoNetwork}},
+ }
+
+ // Create and fill out the runtime spec.
+ s := specgen.NewSpecGenerator(image, false)
+ if err := specgenutil.FillOutSpecGen(s, &ctrOpts, []string{}); err != nil {
+ return nil, fmt.Errorf("completing spec for service container: %w", err)
+ }
+ s.Name = name
+
+ runtimeSpec, spec, opts, err := generate.MakeContainer(ctx, ic.Libpod, s, false, nil)
+ if err != nil {
+ return nil, fmt.Errorf("creating runtime spec for service container: %w", err)
+ }
+ opts = append(opts, libpod.WithIsService())
+
+ // Create a new libpod container based on the spec.
+ ctr, err := ic.Libpod.NewContainer(ctx, runtimeSpec, spec, false, opts...)
+ if err != nil {
+ return nil, fmt.Errorf("creating service container: %w", err)
+ }
+
+ return ctr, nil
+}
+
+func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options entities.PlayKubeOptions) (_ *entities.PlayKubeReport, finalErr error) {
report := &entities.PlayKubeReport{}
validKinds := 0
@@ -67,6 +109,30 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
return nil, errors.Wrap(err, "unable to read kube YAML")
}
+ // TODO: create constants for the various "kinds" of yaml files.
+ var serviceContainer *libpod.Container
+ if options.ServiceContainer && (kind == "Pod" || kind == "Deployment") {
+ // The name of the service container is the first 12
+ // characters of the yaml file's hash followed by the
+ // '-service' suffix to guarantee a predictable and
+ // discoverable name.
+ hash := digest.FromBytes(content).Encoded()
+ ctr, err := ic.createServiceContainer(ctx, hash[0:12]+"-service")
+ if err != nil {
+ return nil, err
+ }
+ serviceContainer = ctr
+ // Make sure to remove the container in case something goes wrong below.
+ defer func() {
+ if finalErr == nil {
+ return
+ }
+ if err := ic.Libpod.RemoveContainer(ctx, ctr, true, false, nil); err != nil {
+ logrus.Errorf("Cleaning up service container after failure: %v", err)
+ }
+ }()
+ }
+
switch kind {
case "Pod":
var podYAML v1.Pod
@@ -90,7 +156,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
podYAML.Annotations[name] = val
}
- r, err := ic.playKubePod(ctx, podTemplateSpec.ObjectMeta.Name, &podTemplateSpec, options, &ipIndex, podYAML.Annotations, configMaps)
+ r, err := ic.playKubePod(ctx, podTemplateSpec.ObjectMeta.Name, &podTemplateSpec, options, &ipIndex, podYAML.Annotations, configMaps, serviceContainer)
if err != nil {
return nil, err
}
@@ -104,7 +170,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
return nil, errors.Wrap(err, "unable to read YAML as Kube Deployment")
}
- r, err := ic.playKubeDeployment(ctx, &deploymentYAML, options, &ipIndex, configMaps)
+ r, err := ic.playKubeDeployment(ctx, &deploymentYAML, options, &ipIndex, configMaps, serviceContainer)
if err != nil {
return nil, err
}
@@ -148,7 +214,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
return report, nil
}
-func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAML *v1apps.Deployment, options entities.PlayKubeOptions, ipIndex *int, configMaps []v1.ConfigMap) (*entities.PlayKubeReport, error) {
+func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAML *v1apps.Deployment, options entities.PlayKubeOptions, ipIndex *int, configMaps []v1.ConfigMap, serviceContainer *libpod.Container) (*entities.PlayKubeReport, error) {
var (
deploymentName string
podSpec v1.PodTemplateSpec
@@ -170,7 +236,7 @@ func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAM
// create "replicas" number of pods
for i = 0; i < numReplicas; i++ {
podName := fmt.Sprintf("%s-pod-%d", deploymentName, i)
- podReport, err := ic.playKubePod(ctx, podName, &podSpec, options, ipIndex, deploymentYAML.Annotations, configMaps)
+ podReport, err := ic.playKubePod(ctx, podName, &podSpec, options, ipIndex, deploymentYAML.Annotations, configMaps, serviceContainer)
if err != nil {
return nil, errors.Wrapf(err, "error encountered while bringing up pod %s", podName)
}
@@ -179,7 +245,7 @@ func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAM
return &report, nil
}
-func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec, options entities.PlayKubeOptions, ipIndex *int, annotations map[string]string, configMaps []v1.ConfigMap) (*entities.PlayKubeReport, error) {
+func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec, options entities.PlayKubeOptions, ipIndex *int, annotations map[string]string, configMaps []v1.ConfigMap, serviceContainer *libpod.Container) (*entities.PlayKubeReport, error) {
var (
writer io.Writer
playKubePod entities.PlayKubePod
@@ -374,6 +440,10 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
}
}
+ if serviceContainer != nil {
+ podSpec.PodSpecGen.ServiceContainerID = serviceContainer.ID()
+ }
+
// Create the Pod
pod, err := generate.MakePod(&podSpec, ic.Libpod)
if err != nil {
diff --git a/pkg/specgen/generate/pause_image.go b/pkg/specgen/generate/pause_image.go
new file mode 100644
index 000000000..4aba230a3
--- /dev/null
+++ b/pkg/specgen/generate/pause_image.go
@@ -0,0 +1,89 @@
+package generate
+
+import (
+ "context"
+ "fmt"
+ "io/ioutil"
+ "os"
+
+ buildahDefine "github.com/containers/buildah/define"
+ "github.com/containers/common/pkg/config"
+ "github.com/containers/podman/v4/libpod"
+ "github.com/containers/podman/v4/libpod/define"
+)
+
+// PullOrBuildInfraImage pulls down the specified image or the one set in
+// containers.conf. If none is set, it builds a local pause image.
+func PullOrBuildInfraImage(rt *libpod.Runtime, imageName string) (string, error) {
+ rtConfig, err := rt.GetConfigNoCopy()
+ if err != nil {
+ return "", err
+ }
+
+ if imageName == "" {
+ imageName = rtConfig.Engine.InfraImage
+ }
+
+ if imageName != "" {
+ _, err := rt.LibimageRuntime().Pull(context.Background(), imageName, config.PullPolicyMissing, nil)
+ if err != nil {
+ return "", err
+ }
+ return imageName, nil
+ }
+
+ name, err := buildPauseImage(rt, rtConfig)
+ if err != nil {
+ return "", fmt.Errorf("building local pause image: %w", err)
+ }
+ return name, nil
+}
+
+func buildPauseImage(rt *libpod.Runtime, rtConfig *config.Config) (string, error) {
+ version, err := define.GetVersion()
+ if err != nil {
+ return "", err
+ }
+ imageName := fmt.Sprintf("localhost/podman-pause:%s-%d", version.Version, version.Built)
+
+ // First check if the image has already been built.
+ if _, _, err := rt.LibimageRuntime().LookupImage(imageName, nil); err == nil {
+ return imageName, nil
+ }
+
+ // Also look into the path as some distributions install catatonit in
+ // /usr/bin.
+ catatonitPath, err := rtConfig.FindHelperBinary("catatonit", true)
+ if err != nil {
+ return "", fmt.Errorf("finding pause binary: %w", err)
+ }
+
+ buildContent := fmt.Sprintf(`FROM scratch
+COPY %s /catatonit
+ENTRYPOINT ["/catatonit", "-P"]`, catatonitPath)
+
+ tmpF, err := ioutil.TempFile("", "pause.containerfile")
+ if err != nil {
+ return "", err
+ }
+ if _, err := tmpF.WriteString(buildContent); err != nil {
+ return "", err
+ }
+ if err := tmpF.Close(); err != nil {
+ return "", err
+ }
+ defer os.Remove(tmpF.Name())
+
+ buildOptions := buildahDefine.BuildOptions{
+ CommonBuildOpts: &buildahDefine.CommonBuildOptions{},
+ Output: imageName,
+ Quiet: true,
+ IgnoreFile: "/dev/null", // makes sure to not read a local .ignorefile (see #13529)
+ IIDFile: "/dev/null", // prevents Buildah from writing the ID on stdout
+ }
+ if _, _, err := rt.Build(context.Background(), buildOptions, tmpF.Name()); err != nil {
+ return "", err
+ }
+
+ return imageName, nil
+}
diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go
index fce32d688..5b7bb2b57 100644
--- a/pkg/specgen/generate/pod_create.go
+++ b/pkg/specgen/generate/pod_create.go
@@ -2,13 +2,8 @@ package generate
import (
"context"
- "fmt"
- "io/ioutil"
"net"
- "os"
- buildahDefine "github.com/containers/buildah/define"
- "github.com/containers/common/pkg/config"
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/domain/entities"
@@ -17,98 +12,18 @@ import (
"github.com/sirupsen/logrus"
)
-func buildPauseImage(rt *libpod.Runtime, rtConfig *config.Config) (string, error) {
- version, err := define.GetVersion()
- if err != nil {
- return "", err
- }
- imageName := fmt.Sprintf("localhost/podman-pause:%s-%d", version.Version, version.Built)
-
- // First check if the image has already been built.
- if _, _, err := rt.LibimageRuntime().LookupImage(imageName, nil); err == nil {
- return imageName, nil
- }
-
- // Also look into the path as some distributions install catatonit in
- // /usr/bin.
- catatonitPath, err := rtConfig.FindHelperBinary("catatonit", true)
- if err != nil {
- return "", fmt.Errorf("finding pause binary: %w", err)
- }
-
- buildContent := fmt.Sprintf(`FROM scratch
-COPY %s /catatonit
-ENTRYPOINT ["/catatonit", "-P"]`, catatonitPath)
-
- tmpF, err := ioutil.TempFile("", "pause.containerfile")
- if err != nil {
- return "", err
- }
- if _, err := tmpF.WriteString(buildContent); err != nil {
- return "", err
- }
- if err := tmpF.Close(); err != nil {
- return "", err
- }
- defer os.Remove(tmpF.Name())
-
- buildOptions := buildahDefine.BuildOptions{
- CommonBuildOpts: &buildahDefine.CommonBuildOptions{},
- Output: imageName,
- Quiet: true,
- IgnoreFile: "/dev/null", // makes sure to not read a local .ignorefile (see #13529)
- IIDFile: "/dev/null", // prevents Buildah from writing the ID on stdout
- }
- if _, _, err := rt.Build(context.Background(), buildOptions, tmpF.Name()); err != nil {
- return "", err
- }
-
- return imageName, nil
-}
-
-func pullOrBuildInfraImage(p *entities.PodSpec, rt *libpod.Runtime) error {
- if p.PodSpecGen.NoInfra {
- return nil
- }
-
- rtConfig, err := rt.GetConfigNoCopy()
- if err != nil {
- return err
- }
-
- // NOTE: we need pull down the infra image if it was explicitly set by
- // the user (or containers.conf) to the non-default one.
- imageName := p.PodSpecGen.InfraImage
- if imageName == "" {
- imageName = rtConfig.Engine.InfraImage
- }
-
- if imageName != "" {
- _, err := rt.LibimageRuntime().Pull(context.Background(), imageName, config.PullPolicyMissing, nil)
- if err != nil {
- return err
- }
- } else {
- name, err := buildPauseImage(rt, rtConfig)
- if err != nil {
- return fmt.Errorf("building local pause image: %w", err)
- }
- imageName = name
- }
-
- p.PodSpecGen.InfraImage = imageName
- p.PodSpecGen.InfraContainerSpec.RawImageName = imageName
-
- return nil
-}
-
func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) {
if err := p.PodSpecGen.Validate(); err != nil {
return nil, err
}
- if err := pullOrBuildInfraImage(p, rt); err != nil {
- return nil, err
+ if !p.PodSpecGen.NoInfra {
+ imageName, err := PullOrBuildInfraImage(rt, p.PodSpecGen.InfraImage)
+ if err != nil {
+ return nil, err
+ }
+ p.PodSpecGen.InfraImage = imageName
+ p.PodSpecGen.InfraContainerSpec.RawImageName = imageName
}
if !p.PodSpecGen.NoInfra && p.PodSpecGen.InfraContainerSpec != nil {
@@ -180,6 +95,11 @@ func createPodOptions(p *specgen.PodSpecGenerator) ([]libpod.PodCreateOption, er
options = append(options, libpod.WithPodUser())
}
}
+
+ if len(p.ServiceContainerID) > 0 {
+ options = append(options, libpod.WithServiceContainer(p.ServiceContainerID))
+ }
+
if len(p.CgroupParent) > 0 {
options = append(options, libpod.WithPodCgroupParent(p.CgroupParent))
}
diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go
index 1bb64448f..603506241 100644
--- a/pkg/specgen/podspecgen.go
+++ b/pkg/specgen/podspecgen.go
@@ -204,6 +204,9 @@ type PodSpecGenerator struct {
PodStorageConfig
PodSecurityConfig
InfraContainerSpec *SpecGenerator `json:"-"`
+
+ // The ID of the pod's service container.
+ ServiceContainerID string `json:"serviceContainerID,omitempty"`
}
type PodResourceConfig struct {
diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go
index b48e1ed62..854bf7420 100644
--- a/test/e2e/containers_conf_test.go
+++ b/test/e2e/containers_conf_test.go
@@ -456,13 +456,12 @@ var _ = Describe("Verify podman containers.conf usage", func() {
containersConf = []byte("[engine]\nimage_copy_tmp_dir=\"storage1\"")
err = ioutil.WriteFile(configPath, containersConf, os.ModePerm)
Expect(err).ToNot(HaveOccurred())
- if IsRemote() {
- podmanTest.RestartRemoteService()
- }
+
+ SkipIfRemote("Restarting the system service will fail loading the broken containers.conf")
session = podmanTest.Podman([]string{"info", "--format", "{{.Store.ImageCopyTmpDir}}"})
session.WaitWithDefaultTimeout()
- Expect(session).Should(Exit(0))
+ Expect(session).Should(Exit(125))
Expect(session.Err.Contents()).To(ContainSubstring("invalid image_copy_tmp_dir"))
})
diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats
index 39982848f..4250f2680 100644
--- a/test/system/200-pod.bats
+++ b/test/system/200-pod.bats
@@ -408,19 +408,6 @@ EOF
run_podman pod rm test
}
-# Wait for the pod (1st arg) to transition into the state (2nd arg)
-function _ensure_pod_state() {
- for i in {0..5}; do
- run_podman pod inspect $1 --format "{{.State}}"
- if [[ $output == "$2" ]]; then
- break
- fi
- sleep 0.5
- done
-
- is "$output" "$2" "unexpected pod state"
-}
-
@test "pod exit policies" {
# Test setting exit policies
run_podman pod create
diff --git a/test/system/700-play.bats b/test/system/700-play.bats
index 7988b26a4..2e5327a85 100644
--- a/test/system/700-play.bats
+++ b/test/system/700-play.bats
@@ -100,6 +100,61 @@ RELABEL="system_u:object_r:container_file_t:s0"
run_podman pod rm -t 0 -f test_pod
}
+@test "podman play --service-container" {
+ skip_if_remote "service containers only work locally"
+
+ TESTDIR=$PODMAN_TMPDIR/testdir
+ mkdir -p $TESTDIR
+
+yaml="
+apiVersion: v1
+kind: Pod
+metadata:
+ labels:
+ app: test
+ name: test_pod
+spec:
+ containers:
+ - command:
+ - top
+ image: $IMAGE
+ name: test
+ resources: {}
+"
+
+ echo "$yaml" > $PODMAN_TMPDIR/test.yaml
+ run_podman play kube --service-container=true $PODMAN_TMPDIR/test.yaml
+
+ # Make sure that the service container exists and runs.
+ run_podman container inspect "352a88685060-service" --format "{{.State.Running}}"
+ is "$output" "true"
+
+ # Stop the *main* container and make sure that
+ # 1) The pod transitions to Exited
+ # 2) The service container is stopped
+ # #) The service container is marked as an service container
+ run_podman stop test_pod-test
+ _ensure_pod_state test_pod Exited
+ run_podman container inspect "352a88685060-service" --format "{{.State.Running}}"
+ is "$output" "false"
+ run_podman container inspect "352a88685060-service" --format "{{.IsService}}"
+ is "$output" "true"
+
+ # Restart the pod, make sure the service is running again
+ run_podman pod restart test_pod
+ run_podman container inspect "352a88685060-service" --format "{{.State.Running}}"
+ is "$output" "true"
+
+ # Kill the pod and make sure the service is not running
+ run_podman pod kill test_pod
+ run_podman container inspect "352a88685060-service" --format "{{.State.Running}}"
+ is "$output" "false"
+
+ # Remove the pod and make sure the service is removed along with it
+ run_podman pod rm test_pod
+ run_podman 1 container exists "352a88685060-service"
+}
+
@test "podman play --network" {
TESTDIR=$PODMAN_TMPDIR/testdir
mkdir -p $TESTDIR
diff --git a/test/system/helpers.bash b/test/system/helpers.bash
index 138d668f4..072131202 100644
--- a/test/system/helpers.bash
+++ b/test/system/helpers.bash
@@ -392,6 +392,19 @@ function pause_image() {
echo "localhost/podman-pause:$output"
}
+# Wait for the pod (1st arg) to transition into the state (2nd arg)
+function _ensure_pod_state() {
+ for i in {0..5}; do
+ run_podman pod inspect $1 --format "{{.State}}"
+ if [[ $output == "$2" ]]; then
+ break
+ fi
+ sleep 0.5
+ done
+
+ is "$output" "$2" "unexpected pod state"
+}
+
###########################
# _add_label_if_missing # make sure skip messages include rootless/remote
###########################
diff --git a/vendor/github.com/containers/common/libimage/image.go b/vendor/github.com/containers/common/libimage/image.go
index 661ca159b..d7c4fcd51 100644
--- a/vendor/github.com/containers/common/libimage/image.go
+++ b/vendor/github.com/containers/common/libimage/image.go
@@ -608,7 +608,7 @@ func (i *Image) RepoTags() ([]string, error) {
// NamedTaggedRepoTags returns the repotags associated with the image as a
// slice of reference.NamedTagged.
func (i *Image) NamedTaggedRepoTags() ([]reference.NamedTagged, error) {
- var repoTags []reference.NamedTagged
+ repoTags := make([]reference.NamedTagged, 0, len(i.Names()))
for _, name := range i.Names() {
parsed, err := reference.Parse(name)
if err != nil {
diff --git a/vendor/github.com/containers/common/libimage/load.go b/vendor/github.com/containers/common/libimage/load.go
index 4dfac7106..c2d066645 100644
--- a/vendor/github.com/containers/common/libimage/load.go
+++ b/vendor/github.com/containers/common/libimage/load.go
@@ -32,8 +32,8 @@ func (r *Runtime) Load(ctx context.Context, path string, options *LoadOptions) (
options = &LoadOptions{}
}
- var loadErrors []error
-
+ // we have 4 functions, so a maximum of 4 errors
+ loadErrors := make([]error, 0, 4)
for _, f := range []func() ([]string, string, error){
// OCI
func() ([]string, string, error) {
@@ -88,6 +88,8 @@ func (r *Runtime) Load(ctx context.Context, path string, options *LoadOptions) (
}
// Give a decent error message if nothing above worked.
+ // we want the colon here for the multiline error
+ //nolint:revive
loadError := fmt.Errorf("payload does not match any of the supported image formats:")
for _, err := range loadErrors {
loadError = fmt.Errorf("%v\n * %v", loadError, err)
diff --git a/vendor/github.com/containers/common/libimage/normalize.go b/vendor/github.com/containers/common/libimage/normalize.go
index 7ceb62830..b36bbf396 100644
--- a/vendor/github.com/containers/common/libimage/normalize.go
+++ b/vendor/github.com/containers/common/libimage/normalize.go
@@ -115,7 +115,7 @@ type NameTagPair struct {
func ToNameTagPairs(repoTags []reference.Named) ([]NameTagPair, error) {
none := "<none>"
- var pairs []NameTagPair
+ pairs := make([]NameTagPair, 0, len(repoTags))
for i, named := range repoTags {
pair := NameTagPair{
Name: named.Name(),
diff --git a/vendor/github.com/containers/common/libimage/pull.go b/vendor/github.com/containers/common/libimage/pull.go
index ff93b6ed8..4ce8add2f 100644
--- a/vendor/github.com/containers/common/libimage/pull.go
+++ b/vendor/github.com/containers/common/libimage/pull.go
@@ -413,11 +413,11 @@ func (r *Runtime) imagesIDsForManifest(manifestBytes []byte, sys *types.SystemCo
}
imageDigest = d
}
- var results []string
images, err := r.store.ImagesByDigest(imageDigest)
if err != nil {
return nil, errors.Wrapf(err, "listing images by manifest digest")
}
+ results := make([]string, 0, len(images))
for _, image := range images {
results = append(results, image.ID)
}
diff --git a/vendor/github.com/containers/common/libimage/runtime.go b/vendor/github.com/containers/common/libimage/runtime.go
index 974b50b50..472482410 100644
--- a/vendor/github.com/containers/common/libimage/runtime.go
+++ b/vendor/github.com/containers/common/libimage/runtime.go
@@ -6,6 +6,7 @@ import (
"os"
"strings"
+ "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/pkg/shortnames"
storageTransport "github.com/containers/image/v5/storage"
@@ -22,13 +23,16 @@ import (
var json = jsoniter.ConfigCompatibleWithStandardLibrary
// tmpdir returns a path to a temporary directory.
-func tmpdir() string {
- tmpdir := os.Getenv("TMPDIR")
- if tmpdir == "" {
- tmpdir = "/var/tmp"
+func tmpdir() (string, error) {
+ var tmpdir string
+ defaultContainerConfig, err := config.Default()
+ if err == nil {
+ tmpdir, err = defaultContainerConfig.ImageCopyTmpDir()
+ if err == nil {
+ return tmpdir, nil
+ }
}
-
- return tmpdir
+ return tmpdir, err
}
// RuntimeOptions allow for creating a customized Runtime.
@@ -103,7 +107,11 @@ func RuntimeFromStore(store storage.Store, options *RuntimeOptions) (*Runtime, e
systemContext = types.SystemContext{}
}
if systemContext.BigFilesTemporaryDir == "" {
- systemContext.BigFilesTemporaryDir = tmpdir()
+ tmpdir, err := tmpdir()
+ if err != nil {
+ return nil, err
+ }
+ systemContext.BigFilesTemporaryDir = tmpdir
}
setRegistriesConfPath(&systemContext)
@@ -224,16 +232,15 @@ func (r *Runtime) LookupImage(name string, options *LookupImageOptions) (*Image,
}
logrus.Debugf("Found image %q in local containers storage (%s)", name, storageRef.StringWithinTransport())
return r.storageToImage(img, storageRef), "", nil
- } else {
- // Docker compat: strip off the tag iff name is tagged and digested
- // (e.g., fedora:latest@sha256...). In that case, the tag is stripped
- // off and entirely ignored. The digest is the sole source of truth.
- normalizedName, err := normalizeTaggedDigestedString(name)
- if err != nil {
- return nil, "", err
- }
- name = normalizedName
}
+ // Docker compat: strip off the tag iff name is tagged and digested
+ // (e.g., fedora:latest@sha256...). In that case, the tag is stripped
+ // off and entirely ignored. The digest is the sole source of truth.
+ normalizedName, err := normalizeTaggedDigestedString(name)
+ if err != nil {
+ return nil, "", err
+ }
+ name = normalizedName
byDigest := false
originalName := name
diff --git a/vendor/github.com/containers/common/libnetwork/cni/config.go b/vendor/github.com/containers/common/libnetwork/cni/config.go
index c6967b600..f6954db05 100644
--- a/vendor/github.com/containers/common/libnetwork/cni/config.go
+++ b/vendor/github.com/containers/common/libnetwork/cni/config.go
@@ -96,7 +96,7 @@ func (n *cniNetwork) networkCreate(newNetwork *types.Network, defaultNet bool) (
newNetwork.ID = getNetworkIDFromName(newNetwork.Name)
// when we do not have ipam we must disable dns
- internalutil.IpamNoneDisableDns(newNetwork)
+ internalutil.IpamNoneDisableDNS(newNetwork)
// FIXME: Should this be a hard error?
if newNetwork.DNSEnabled && newNetwork.Internal && hasDNSNamePlugin(n.cniPluginDirs) {
diff --git a/vendor/github.com/containers/common/libnetwork/cni/run.go b/vendor/github.com/containers/common/libnetwork/cni/run.go
index c7fa86ed0..c5461d74c 100644
--- a/vendor/github.com/containers/common/libnetwork/cni/run.go
+++ b/vendor/github.com/containers/common/libnetwork/cni/run.go
@@ -106,7 +106,7 @@ func (n *cniNetwork) Setup(namespacePath string, options types.SetupOptions) (ma
}
// CNIResultToStatus convert the cni result to status block
-// nolint:golint
+// nolint:golint,revive
func CNIResultToStatus(res cnitypes.Result) (types.StatusBlock, error) {
result := types.StatusBlock{}
cniResult, err := types040.GetResult(res)
diff --git a/vendor/github.com/containers/common/libnetwork/internal/util/create.go b/vendor/github.com/containers/common/libnetwork/internal/util/create.go
index c1a4bee75..d4d574065 100644
--- a/vendor/github.com/containers/common/libnetwork/internal/util/create.go
+++ b/vendor/github.com/containers/common/libnetwork/internal/util/create.go
@@ -41,7 +41,7 @@ func CommonNetworkCreate(n NetUtil, network *types.Network) error {
return nil
}
-func IpamNoneDisableDns(network *types.Network) {
+func IpamNoneDisableDNS(network *types.Network) {
if network.IPAMOptions[types.Driver] == types.NoneIPAMDriver {
logrus.Debugf("dns disabled for network %q because ipam driver is set to none", network.Name)
network.DNSEnabled = false
diff --git a/vendor/github.com/containers/common/libnetwork/netavark/config.go b/vendor/github.com/containers/common/libnetwork/netavark/config.go
index 0bb0539b2..f2c72ab9e 100644
--- a/vendor/github.com/containers/common/libnetwork/netavark/config.go
+++ b/vendor/github.com/containers/common/libnetwork/netavark/config.go
@@ -121,7 +121,7 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo
}
// when we do not have ipam we must disable dns
- internalutil.IpamNoneDisableDns(newNetwork)
+ internalutil.IpamNoneDisableDNS(newNetwork)
// add gateway when not internal or dns enabled
addGateway := !newNetwork.Internal || newNetwork.DNSEnabled
diff --git a/vendor/github.com/containers/common/libnetwork/network/interface.go b/vendor/github.com/containers/common/libnetwork/network/interface.go
index 893bdea2e..e70f096a4 100644
--- a/vendor/github.com/containers/common/libnetwork/network/interface.go
+++ b/vendor/github.com/containers/common/libnetwork/network/interface.go
@@ -46,6 +46,9 @@ const (
// 1. read ${graphroot}/defaultNetworkBackend
// 2. find netavark binary (if not installed use CNI)
// 3. check containers, images and CNI networks and if there are some we have an existing install and should continue to use CNI
+//
+// revive does not like the name because the package is already called network
+//nolint:revive
func NetworkBackend(store storage.Store, conf *config.Config, syslog bool) (types.NetworkBackend, types.ContainerNetwork, error) {
backend := types.NetworkBackend(conf.Network.NetworkBackend)
if backend == "" {
diff --git a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go
index 35f79a1ad..1fd269255 100644
--- a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go
+++ b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go
@@ -251,19 +251,17 @@ func CheckProfileAndLoadDefault(name string) (string, error) {
if unshare.IsRootless() {
if name != "" {
return "", errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name)
- } else {
- logrus.Debug("Skipping loading default AppArmor profile (rootless mode)")
- return "", nil
}
+ logrus.Debug("Skipping loading default AppArmor profile (rootless mode)")
+ return "", nil
}
// Check if AppArmor is disabled and error out if a profile is to be set.
if !runcaa.IsEnabled() {
if name == "" {
return "", nil
- } else {
- return "", errors.Errorf("profile %q specified but AppArmor is disabled on the host", name)
}
+ return "", errors.Errorf("profile %q specified but AppArmor is disabled on the host", name)
}
if name == "" {
diff --git a/vendor/github.com/containers/common/pkg/auth/auth.go b/vendor/github.com/containers/common/pkg/auth/auth.go
index 6765c9e5b..188e06c12 100644
--- a/vendor/github.com/containers/common/pkg/auth/auth.go
+++ b/vendor/github.com/containers/common/pkg/auth/auth.go
@@ -26,8 +26,8 @@ func GetDefaultAuthFile() string {
if authfile := os.Getenv("REGISTRY_AUTH_FILE"); authfile != "" {
return authfile
}
- if auth_env := os.Getenv("DOCKER_CONFIG"); auth_env != "" {
- return filepath.Join(auth_env, "config.json")
+ if authEnv := os.Getenv("DOCKER_CONFIG"); authEnv != "" {
+ return filepath.Join(authEnv, "config.json")
}
return ""
}
@@ -313,7 +313,7 @@ func Logout(systemContext *types.SystemContext, opts *LogoutOptions, args []stri
fmt.Printf("Not logged into %s with current tool. Existing credentials were established via docker login. Please use docker logout instead.\n", key)
return nil
}
- return errors.Errorf("Not logged into %s\n", key)
+ return errors.Errorf("not logged into %s", key)
default:
return errors.Wrapf(err, "logging out of %q", key)
}
diff --git a/vendor/github.com/containers/common/pkg/capabilities/capabilities.go b/vendor/github.com/containers/common/pkg/capabilities/capabilities.go
index 10c5dd7c4..b8e3fbcb5 100644
--- a/vendor/github.com/containers/common/pkg/capabilities/capabilities.go
+++ b/vendor/github.com/containers/common/pkg/capabilities/capabilities.go
@@ -104,8 +104,8 @@ func AllCapabilities() []string {
// NormalizeCapabilities normalizes caps by adding a "CAP_" prefix (if not yet
// present).
func NormalizeCapabilities(caps []string) ([]string, error) {
- normalized := make([]string, len(caps))
- for i, c := range caps {
+ normalized := make([]string, 0, len(caps))
+ for _, c := range caps {
c = strings.ToUpper(c)
if c == All {
normalized = append(normalized, c)
@@ -117,7 +117,7 @@ func NormalizeCapabilities(caps []string) ([]string, error) {
if !stringInSlice(c, capabilityList) {
return nil, errors.Wrapf(ErrUnknownCapability, "%q", c)
}
- normalized[i] = c
+ normalized = append(normalized, c)
}
sort.Strings(normalized)
return normalized, nil
@@ -140,8 +140,6 @@ func ValidateCapabilities(caps []string) error {
// "ALL" in capAdd adds returns known capabilities
// "All" in capDrop returns only the capabilities specified in capAdd
func MergeCapabilities(base, adds, drops []string) ([]string, error) {
- var caps []string
-
// Normalize the base capabilities
base, err := NormalizeCapabilities(base)
if err != nil {
@@ -189,6 +187,7 @@ func MergeCapabilities(base, adds, drops []string) ([]string, error) {
}
}
+ caps := make([]string, 0, len(base)+len(capAdd))
// Drop any capabilities in capDrop that are in base
for _, cap := range base {
if stringInSlice(cap, capDrop) {
diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go
index edb28ad18..5c6c199e0 100644
--- a/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go
+++ b/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go
@@ -9,6 +9,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
+ "strconv"
"strings"
"sync"
"syscall"
@@ -96,6 +97,22 @@ func UserOwnsCurrentSystemdCgroup() (bool, error) {
// It differs from os.RemoveAll as it doesn't attempt to unlink files.
// On cgroupfs we are allowed only to rmdir empty directories.
func rmDirRecursively(path string) error {
+ killProcesses := func(signal syscall.Signal) {
+ if signal == unix.SIGKILL {
+ if err := ioutil.WriteFile(filepath.Join(path, "cgroup.kill"), []byte("1"), 0600); err == nil {
+ return
+ }
+ }
+ // kill all the processes that are still part of the cgroup
+ if procs, err := ioutil.ReadFile(filepath.Join(path, "cgroup.procs")); err == nil {
+ for _, pidS := range strings.Split(string(procs), "\n") {
+ if pid, err := strconv.Atoi(pidS); err == nil {
+ _ = unix.Kill(pid, signal)
+ }
+ }
+ }
+ }
+
if err := os.Remove(path); err == nil || os.IsNotExist(err) {
return nil
}
@@ -118,8 +135,16 @@ func rmDirRecursively(path string) error {
return nil
}
if errors.Is(err, unix.EBUSY) {
- // attempt up to 5 seconds if the cgroup is busy
- if attempts < 500 {
+ // send a SIGTERM after 3 second
+ if attempts == 300 {
+ killProcesses(unix.SIGTERM)
+ }
+ // send SIGKILL after 8 seconds
+ if attempts == 800 {
+ killProcesses(unix.SIGKILL)
+ }
+ // give up after 10 seconds
+ if attempts < 1000 {
time.Sleep(time.Millisecond * 10)
attempts++
continue
diff --git a/vendor/github.com/containers/common/pkg/completion/completion.go b/vendor/github.com/containers/common/pkg/completion/completion.go
index c90bf540b..b5e6d6d30 100644
--- a/vendor/github.com/containers/common/pkg/completion/completion.go
+++ b/vendor/github.com/containers/common/pkg/completion/completion.go
@@ -51,7 +51,7 @@ func AutocompleteCapabilities(cmd *cobra.Command, args []string, toComplete stri
offset = 4
}
- var completions []string
+ completions := make([]string, 0, len(caps))
for _, cap := range caps {
completions = append(completions, convertCase(cap)[offset:])
}
diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go
index a86eca88e..ebd02e9a1 100644
--- a/vendor/github.com/containers/common/pkg/config/config.go
+++ b/vendor/github.com/containers/common/pkg/config/config.go
@@ -553,6 +553,9 @@ type SecretConfig struct {
}
// ConfigMapConfig represents the "configmap" TOML config table
+//
+// revive does not like the name because the package is already called config
+//nolint:revive
type ConfigMapConfig struct {
// Driver specifies the configmap driver to use.
// Current valid value:
@@ -1215,14 +1218,14 @@ func (c *Config) ActiveDestination() (uri, identity string, err error) {
// FindHelperBinary will search the given binary name in the configured directories.
// If searchPATH is set to true it will also search in $PATH.
func (c *Config) FindHelperBinary(name string, searchPATH bool) (string, error) {
- dir_list := c.Engine.HelperBinariesDir
+ dirList := c.Engine.HelperBinariesDir
// If set, search this directory first. This is used in testing.
if dir, found := os.LookupEnv("CONTAINERS_HELPER_BINARY_DIR"); found {
- dir_list = append([]string{dir}, dir_list...)
+ dirList = append([]string{dir}, dirList...)
}
- for _, path := range dir_list {
+ for _, path := range dirList {
fullpath := filepath.Join(path, name)
if fi, err := os.Stat(fullpath); err == nil && fi.Mode().IsRegular() {
return fullpath, nil
diff --git a/vendor/github.com/containers/common/pkg/filters/filters.go b/vendor/github.com/containers/common/pkg/filters/filters.go
index e26e056ad..53650efc9 100644
--- a/vendor/github.com/containers/common/pkg/filters/filters.go
+++ b/vendor/github.com/containers/common/pkg/filters/filters.go
@@ -36,11 +36,13 @@ func ComputeUntilTimestamp(filterValues []string) (time.Time, error) {
//
// Please refer to https://github.com/containers/podman/issues/6899 for some
// background.
+//
+// revive does not like the name because the package is already called filters
+//nolint:revive
func FiltersFromRequest(r *http.Request) ([]string, error) {
var (
compatFilters map[string]map[string]bool
filters map[string][]string
- libpodFilters []string
raw []byte
)
@@ -54,6 +56,7 @@ func FiltersFromRequest(r *http.Request) ([]string, error) {
// Backwards compat with older versions of Docker.
if err := json.Unmarshal(raw, &compatFilters); err == nil {
+ libpodFilters := make([]string, 0, len(compatFilters))
for filterKey, filterMap := range compatFilters {
for filterValue, toAdd := range filterMap {
if toAdd {
@@ -68,6 +71,7 @@ func FiltersFromRequest(r *http.Request) ([]string, error) {
return nil, err
}
+ libpodFilters := make([]string, 0, len(filters))
for filterKey, filterSlice := range filters {
f := filterKey
for _, filterValue := range filterSlice {
diff --git a/vendor/github.com/containers/common/pkg/machine/machine.go b/vendor/github.com/containers/common/pkg/machine/machine.go
index 465eeceaf..37e89a08e 100644
--- a/vendor/github.com/containers/common/pkg/machine/machine.go
+++ b/vendor/github.com/containers/common/pkg/machine/machine.go
@@ -9,6 +9,8 @@ import (
"github.com/sirupsen/logrus"
)
+// TODO: change name to MachineMarker since package is already called machine
+//nolint:revive
type MachineMarker struct {
Enabled bool
Type string
@@ -54,6 +56,8 @@ func IsPodmanMachine() bool {
return GetMachineMarker().Enabled
}
+// TODO: change name to HostType since package is already called machine
+//nolint:revive
func MachineHostType() string {
return GetMachineMarker().Type
}
diff --git a/vendor/github.com/containers/common/pkg/parse/parse_unix.go b/vendor/github.com/containers/common/pkg/parse/parse_unix.go
index d087c4a02..2d1f1ce4b 100644
--- a/vendor/github.com/containers/common/pkg/parse/parse_unix.go
+++ b/vendor/github.com/containers/common/pkg/parse/parse_unix.go
@@ -13,7 +13,6 @@ import (
)
func DeviceFromPath(device string) ([]devices.Device, error) {
- var devs []devices.Device
src, dst, permissions, err := Device(device)
if err != nil {
return nil, err
@@ -27,7 +26,7 @@ func DeviceFromPath(device string) ([]devices.Device, error) {
}
if !srcInfo.IsDir() {
-
+ devs := make([]devices.Device, 0, 1)
dev, err := devices.DeviceFromPath(src, permissions)
if err != nil {
return nil, errors.Wrapf(err, "%s is not a valid device", src)
@@ -42,6 +41,7 @@ func DeviceFromPath(device string) ([]devices.Device, error) {
if err != nil {
return nil, errors.Wrapf(err, "error getting source devices from directory %s", src)
}
+ devs := make([]devices.Device, 0, len(srcDevices))
for _, d := range srcDevices {
d.Path = filepath.Join(dst, filepath.Base(d.Path))
d.Permissions = devices.Permissions(permissions)
diff --git a/vendor/github.com/containers/common/pkg/retry/retry.go b/vendor/github.com/containers/common/pkg/retry/retry.go
index a9573e4e8..234fd3448 100644
--- a/vendor/github.com/containers/common/pkg/retry/retry.go
+++ b/vendor/github.com/containers/common/pkg/retry/retry.go
@@ -17,12 +17,17 @@ import (
)
// RetryOptions defines the option to retry
+// revive does not like the name because the package is already called retry
+//nolint:revive
type RetryOptions struct {
MaxRetry int // The number of times to possibly retry
Delay time.Duration // The delay to use between retries, if set
}
// RetryIfNecessary retries the operation in exponential backoff with the retryOptions
+//
+// revive does not like the name because the package is already called retry
+//nolint:revive
func RetryIfNecessary(ctx context.Context, operation func() error, retryOptions *RetryOptions) error {
err := operation()
for attempt := 0; err != nil && isRetryable(err) && attempt < retryOptions.MaxRetry; attempt++ {
diff --git a/vendor/github.com/containers/common/pkg/seccomp/conversion.go b/vendor/github.com/containers/common/pkg/seccomp/conversion.go
index 4c25cb1b1..cd599f0f3 100644
--- a/vendor/github.com/containers/common/pkg/seccomp/conversion.go
+++ b/vendor/github.com/containers/common/pkg/seccomp/conversion.go
@@ -71,11 +71,12 @@ var (
// https://github.com/opencontainers/runtime-spec/pull/1064
// specs.ActKillProcess ActKillProcess,
// specs.ActKillThread ActKillThread,
- specs.ActErrno: ActErrno,
- specs.ActTrap: ActTrap,
- specs.ActAllow: ActAllow,
- specs.ActTrace: ActTrace,
- specs.ActLog: ActLog,
+ specs.ActErrno: ActErrno,
+ specs.ActTrap: ActTrap,
+ specs.ActAllow: ActAllow,
+ specs.ActTrace: ActTrace,
+ specs.ActLog: ActLog,
+ specs.ActNotify: ActNotify,
}
specOperatorToSeccompOperatorMap = map[specs.LinuxSeccompOperator]Operator{
specs.OpNotEqual: OpNotEqual,
diff --git a/vendor/github.com/containers/common/pkg/seccomp/filter.go b/vendor/github.com/containers/common/pkg/seccomp/filter.go
index 5c278574c..609036c82 100644
--- a/vendor/github.com/containers/common/pkg/seccomp/filter.go
+++ b/vendor/github.com/containers/common/pkg/seccomp/filter.go
@@ -130,7 +130,7 @@ func matchSyscall(filter *libseccomp.ScmpFilter, call *Syscall) error {
return errors.Wrapf(err, "create seccomp syscall condition for syscall %s", call.Name)
}
- argCounts[cond.Index] += 1
+ argCounts[cond.Index]++
conditions = append(conditions, newCond)
}
diff --git a/vendor/github.com/containers/common/pkg/seccomp/types.go b/vendor/github.com/containers/common/pkg/seccomp/types.go
index 784b1ba8d..56fd22a38 100644
--- a/vendor/github.com/containers/common/pkg/seccomp/types.go
+++ b/vendor/github.com/containers/common/pkg/seccomp/types.go
@@ -75,6 +75,7 @@ const (
ActTrace Action = "SCMP_ACT_TRACE"
ActAllow Action = "SCMP_ACT_ALLOW"
ActLog Action = "SCMP_ACT_LOG"
+ ActNotify Action = "SCMP_ACT_NOTIFY"
)
// Operator used to match syscall arguments in Seccomp
diff --git a/vendor/github.com/containers/common/pkg/secrets/filedriver/filedriver.go b/vendor/github.com/containers/common/pkg/secrets/filedriver/filedriver.go
index e0c275851..6b92714d0 100644
--- a/vendor/github.com/containers/common/pkg/secrets/filedriver/filedriver.go
+++ b/vendor/github.com/containers/common/pkg/secrets/filedriver/filedriver.go
@@ -55,7 +55,7 @@ func (d *Driver) List() ([]string, error) {
if err != nil {
return nil, err
}
- var allID []string
+ allID := make([]string, 0, len(secretData))
for k := range secretData {
allID = append(allID, k)
}
@@ -134,9 +134,8 @@ func (d *Driver) getAllData() (map[string][]byte, error) {
if os.IsNotExist(err) {
// the file will be created later on a store()
return make(map[string][]byte), nil
- } else {
- return nil, err
}
+ return nil, err
}
file, err := os.Open(d.secretsDataFilePath)
diff --git a/vendor/github.com/containers/common/pkg/secrets/secrets.go b/vendor/github.com/containers/common/pkg/secrets/secrets.go
index 4a04e2b2f..e45995b2e 100644
--- a/vendor/github.com/containers/common/pkg/secrets/secrets.go
+++ b/vendor/github.com/containers/common/pkg/secrets/secrets.go
@@ -53,6 +53,9 @@ var secretsFile = "secrets.json"
var secretNameRegexp = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_.-]*$`)
// SecretsManager holds information on handling secrets
+//
+// revive does not like the name because the package is already called secrets
+//nolint:revive
type SecretsManager struct {
// secretsPath is the path to the db file where secrets are stored
secretsDBPath string
@@ -82,6 +85,9 @@ type Secret struct {
// The driver stores the actual bytes of secret data, as opposed to
// the secret metadata.
// Currently only the unencrypted filedriver is implemented.
+//
+// revive does not like the name because the package is already called secrets
+//nolint:revive
type SecretsDriver interface {
// List lists all secret ids in the secrets data store
List() ([]string, error)
@@ -234,7 +240,7 @@ func (s *SecretsManager) List() ([]Secret, error) {
if err != nil {
return nil, err
}
- var ls []Secret
+ ls := make([]Secret, 0, len(secrets))
for _, v := range secrets {
ls = append(ls, v)
}
@@ -276,9 +282,8 @@ func getDriver(name string, opts map[string]string) (SecretsDriver, error) {
case "file":
if path, ok := opts["path"]; ok {
return filedriver.NewDriver(path)
- } else {
- return nil, errors.Wrap(errInvalidDriverOpt, "need path for filedriver")
}
+ return nil, errors.Wrap(errInvalidDriverOpt, "need path for filedriver")
case "pass":
return passdriver.NewDriver(opts)
case "shell":
diff --git a/vendor/github.com/containers/common/pkg/secrets/secretsdb.go b/vendor/github.com/containers/common/pkg/secrets/secretsdb.go
index 4d2ca0fca..8d21aa754 100644
--- a/vendor/github.com/containers/common/pkg/secrets/secretsdb.go
+++ b/vendor/github.com/containers/common/pkg/secrets/secretsdb.go
@@ -31,9 +31,8 @@ func (s *SecretsManager) loadDB() error {
// the db cache will show no entries anyway.
// The file will be created later on a store()
return nil
- } else {
- return err
}
+ return err
}
// We check if the file has been modified after the last time it was loaded into the cache.
diff --git a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
index 4410292a7..b111ae7ff 100644
--- a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
+++ b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
@@ -212,8 +212,8 @@ func rchown(chowndir string, uid, gid int) error {
// addSubscriptionsFromMountsFile copies the contents of host directory to container directory
// and returns a list of mounts
func addSubscriptionsFromMountsFile(filePath, mountLabel, containerRunDir string, uid, gid int) ([]rspec.Mount, error) {
- var mounts []rspec.Mount
defaultMountsPaths := getMounts(filePath)
+ mounts := make([]rspec.Mount, 0, len(defaultMountsPaths))
for _, path := range defaultMountsPaths {
hostDirOrFile, ctrDirOrFile, err := getMountsMap(path)
if err != nil {
diff --git a/vendor/github.com/containers/common/pkg/sysinfo/nummem_linux.go b/vendor/github.com/containers/common/pkg/sysinfo/nummem_linux.go
index 859791e36..018c488be 100644
--- a/vendor/github.com/containers/common/pkg/sysinfo/nummem_linux.go
+++ b/vendor/github.com/containers/common/pkg/sysinfo/nummem_linux.go
@@ -12,6 +12,8 @@ import (
// NUMANodeCount queries the system for the count of Memory Nodes available
// for use to this process.
func NUMANodeCount() int {
+ // this is the correct flag name (not defined in the unix package)
+ //nolint:revive
MPOL_F_MEMS_ALLOWED := (1 << 2)
var mask [1024 / 64]uintptr
_, _, err := unix.RawSyscall6(unix.SYS_GET_MEMPOLICY, 0, uintptr(unsafe.Pointer(&mask[0])), uintptr(len(mask)*8), 0, uintptr(MPOL_F_MEMS_ALLOWED), 0)
diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go
index 61fce9d22..f8a24f823 100644
--- a/vendor/github.com/containers/common/version/version.go
+++ b/vendor/github.com/containers/common/version/version.go
@@ -1,4 +1,4 @@
package version
// Version is the version of the build.
-const Version = "0.48.0"
+const Version = "0.49.0-dev"
diff --git a/vendor/modules.txt b/vendor/modules.txt
index d2d7a6df9..077eeba04 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -109,7 +109,7 @@ github.com/containers/buildah/pkg/rusage
github.com/containers/buildah/pkg/sshagent
github.com/containers/buildah/pkg/util
github.com/containers/buildah/util
-# github.com/containers/common v0.48.0
+# github.com/containers/common v0.48.1-0.20220510094751-400832f41771
## explicit
github.com/containers/common/libimage
github.com/containers/common/libimage/manifests