aboutsummaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2020-08-24 18:35:59 -0400
committerGitHub <noreply@github.com>2020-08-24 18:35:59 -0400
commit024f47068a894907ee47b1b90c86090a00586940 (patch)
tree4528b3566c3162ca2892b8c3d752d3957161e3d5 /libpod
parentc78c6b44ce63430218e141415a10b2010d42f883 (diff)
parent13d5b2d661478005a0b7eec5563d13580b6cd3f8 (diff)
downloadpodman-024f47068a894907ee47b1b90c86090a00586940.tar.gz
podman-024f47068a894907ee47b1b90c86090a00586940.tar.bz2
podman-024f47068a894907ee47b1b90c86090a00586940.zip
Merge pull request #7402 from mheon/last_pr_before_205_really_this_time
Final v2.0.5 backports
Diffstat (limited to 'libpod')
-rw-r--r--libpod/define/errors.go4
-rw-r--r--libpod/options.go20
-rw-r--r--libpod/pod.go11
-rw-r--r--libpod/pod_api.go134
-rw-r--r--libpod/runtime_pod_infra_linux.go6
5 files changed, 143 insertions, 32 deletions
diff --git a/libpod/define/errors.go b/libpod/define/errors.go
index 5cadce396..e27626fcc 100644
--- a/libpod/define/errors.go
+++ b/libpod/define/errors.go
@@ -160,4 +160,8 @@ var (
// ErrImageInUse indicates the requested operation failed because the image was in use
ErrImageInUse = errors.New("image is being used")
+
+ // ErrNetworkOnPodContainer indicates the user wishes to alter network attributes on a container
+ // in a pod. This cannot be done as the infra container has all the network information
+ ErrNetworkOnPodContainer = errors.New("network cannot be configured when it is shared with a pod")
)
diff --git a/libpod/options.go b/libpod/options.go
index a4e4b99e9..45775e73b 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -2036,3 +2036,23 @@ func WithPodHostNetwork() PodCreateOption {
return nil
}
}
+
+// WithPodInfraExitCommand sets an exit command for the pod's infra container.
+// Semantics are identical to WithExitCommand() above - the ID of the container
+// will be appended to the end of the provided command (note that this will
+// specifically be the ID of the infra container *and not the pod's id*.
+func WithPodInfraExitCommand(exitCmd []string) PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ if !pod.config.InfraContainer.HasInfraContainer {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod infra container exit command as no infra container is being created")
+ }
+
+ pod.config.InfraContainer.ExitCommand = exitCmd
+
+ return nil
+ }
+}
diff --git a/libpod/pod.go b/libpod/pod.go
index 00ba5d53c..4ce66b751 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -81,7 +81,15 @@ type podState struct {
InfraContainerID string
}
-// InfraContainerConfig is the configuration for the pod's infra container
+// InfraContainerConfig is the configuration for the pod's infra container.
+// Generally speaking, these are equivalent to container configuration options
+// you will find in container_config.go (and even named identically), save for
+// HasInfraContainer (which determines if an infra container is even created -
+// if it is false, no other options in this struct will be used) and HostNetwork
+// (this involves the created OCI spec, and as such is not represented directly
+// in container_config.go).
+// Generally speaking, aside from those two exceptions, these options will set
+// the equivalent field in the container's configuration.
type InfraContainerConfig struct {
ConmonPidFile string `json:"conmonPidFile"`
HasInfraContainer bool `json:"makeInfraContainer"`
@@ -96,6 +104,7 @@ type InfraContainerConfig struct {
UseImageHosts bool `json:"useImageHosts,omitempty"`
HostAdd []string `json:"hostsAdd,omitempty"`
Networks []string `json:"networks,omitempty"`
+ ExitCommand []string `json:"exitCommand,omitempty"`
}
// ID retrieves the pod's ID
diff --git a/libpod/pod_api.go b/libpod/pod_api.go
index f2ef81bec..3316b3b31 100644
--- a/libpod/pod_api.go
+++ b/libpod/pod_api.go
@@ -11,20 +11,20 @@ import (
"github.com/sirupsen/logrus"
)
-// Start starts all containers within a pod
-// It combines the effects of Init() and Start() on a container
+// Start starts all containers within a pod.
+// It combines the effects of Init() and Start() on a container.
// If a container has already been initialized it will be started,
// otherwise it will be initialized then started.
// Containers that are already running or have been paused are ignored
// All containers are started independently, in order dictated by their
// dependencies.
-// An error and a map[string]error are returned
+// An error and a map[string]error are returned.
// If the error is not nil and the map is nil, an error was encountered before
-// any containers were started
+// any containers were started.
// If map is not nil, an error was encountered when starting one or more
// containers. The container ID is mapped to the error encountered. The error is
-// set to ErrCtrExists
-// If both error and the map are nil, all containers were started successfully
+// set to ErrPodPartialFail.
+// If both error and the map are nil, all containers were started successfully.
func (p *Pod) Start(ctx context.Context) (map[string]error, error) {
p.lock.Lock()
defer p.lock.Unlock()
@@ -72,20 +72,20 @@ func (p *Pod) Stop(ctx context.Context, cleanup bool) (map[string]error, error)
}
// StopWithTimeout stops all containers within a pod that are not already stopped
-// Each container will use its own stop timeout
+// Each container will use its own stop timeout.
// Only running containers will be stopped. Paused, stopped, or created
// containers will be ignored.
// If cleanup is true, mounts and network namespaces will be cleaned up after
// the container is stopped.
// All containers are stopped independently. An error stopping one container
// will not prevent other containers being stopped.
-// An error and a map[string]error are returned
+// An error and a map[string]error are returned.
// If the error is not nil and the map is nil, an error was encountered before
-// any containers were stopped
+// any containers were stopped.
// If map is not nil, an error was encountered when stopping one or more
// containers. The container ID is mapped to the error encountered. The error is
-// set to ErrCtrExists
-// If both error and the map are nil, all containers were stopped without error
+// set to ErrPodPartialFail.
+// If both error and the map are nil, all containers were stopped without error.
func (p *Pod) StopWithTimeout(ctx context.Context, cleanup bool, timeout int) (map[string]error, error) {
p.lock.Lock()
defer p.lock.Unlock()
@@ -138,10 +138,82 @@ func (p *Pod) StopWithTimeout(ctx context.Context, cleanup bool, timeout int) (m
ctr.lock.Unlock()
}
+ p.newPodEvent(events.Stop)
+
if len(ctrErrors) > 0 {
return ctrErrors, errors.Wrapf(define.ErrPodPartialFail, "error stopping some containers")
}
- defer p.newPodEvent(events.Stop)
+ return nil, nil
+}
+
+// Cleanup cleans up all containers within a pod that have stopped.
+// All containers are cleaned up independently. An error with one container will
+// not prevent other containers being cleaned up.
+// An error and a map[string]error are returned.
+// If the error is not nil and the map is nil, an error was encountered before
+// any containers were cleaned up.
+// If map is not nil, an error was encountered when working on one or more
+// containers. The container ID is mapped to the error encountered. The error is
+// set to ErrPodPartialFail.
+// If both error and the map are nil, all containers were paused without error
+func (p *Pod) Cleanup(ctx context.Context) (map[string]error, error) {
+ p.lock.Lock()
+ defer p.lock.Unlock()
+
+ if !p.valid {
+ return nil, define.ErrPodRemoved
+ }
+
+ allCtrs, err := p.runtime.state.PodContainers(p)
+ if err != nil {
+ return nil, err
+ }
+
+ ctrErrors := make(map[string]error)
+
+ // Clean up all containers
+ for _, ctr := range allCtrs {
+ ctr.lock.Lock()
+
+ if err := ctr.syncContainer(); err != nil {
+ ctr.lock.Unlock()
+ ctrErrors[ctr.ID()] = err
+ continue
+ }
+
+ // Ignore containers that are running/paused
+ if !ctr.ensureState(define.ContainerStateConfigured, define.ContainerStateCreated, define.ContainerStateStopped, define.ContainerStateExited) {
+ ctr.lock.Unlock()
+ continue
+ }
+
+ // Check for running exec sessions, ignore containers with them.
+ sessions, err := ctr.getActiveExecSessions()
+ if err != nil {
+ ctr.lock.Unlock()
+ ctrErrors[ctr.ID()] = err
+ continue
+ }
+ if len(sessions) > 0 {
+ ctr.lock.Unlock()
+ continue
+ }
+
+ // TODO: Should we handle restart policy here?
+
+ ctr.newContainerEvent(events.Cleanup)
+
+ if err := ctr.cleanup(ctx); err != nil {
+ ctrErrors[ctr.ID()] = err
+ }
+
+ ctr.lock.Unlock()
+ }
+
+ if len(ctrErrors) > 0 {
+ return ctrErrors, errors.Wrapf(define.ErrPodPartialFail, "error cleaning up some containers")
+ }
+
return nil, nil
}
@@ -150,12 +222,12 @@ func (p *Pod) StopWithTimeout(ctx context.Context, cleanup bool, timeout int) (m
// containers will be ignored.
// All containers are paused independently. An error pausing one container
// will not prevent other containers being paused.
-// An error and a map[string]error are returned
+// An error and a map[string]error are returned.
// If the error is not nil and the map is nil, an error was encountered before
-// any containers were paused
+// any containers were paused.
// If map is not nil, an error was encountered when pausing one or more
// containers. The container ID is mapped to the error encountered. The error is
-// set to ErrCtrExists
+// set to ErrPodPartialFail.
// If both error and the map are nil, all containers were paused without error
func (p *Pod) Pause() (map[string]error, error) {
p.lock.Lock()
@@ -219,13 +291,13 @@ func (p *Pod) Pause() (map[string]error, error) {
// containers will be ignored.
// All containers are unpaused independently. An error unpausing one container
// will not prevent other containers being unpaused.
-// An error and a map[string]error are returned
+// An error and a map[string]error are returned.
// If the error is not nil and the map is nil, an error was encountered before
-// any containers were unpaused
+// any containers were unpaused.
// If map is not nil, an error was encountered when unpausing one or more
// containers. The container ID is mapped to the error encountered. The error is
-// set to ErrCtrExists
-// If both error and the map are nil, all containers were unpaused without error
+// set to ErrPodPartialFail.
+// If both error and the map are nil, all containers were unpaused without error.
func (p *Pod) Unpause() (map[string]error, error) {
p.lock.Lock()
defer p.lock.Unlock()
@@ -280,13 +352,13 @@ func (p *Pod) Unpause() (map[string]error, error) {
// All containers are started independently, in order dictated by their
// dependencies. An error restarting one container
// will not prevent other containers being restarted.
-// An error and a map[string]error are returned
+// An error and a map[string]error are returned.
// If the error is not nil and the map is nil, an error was encountered before
-// any containers were restarted
+// any containers were restarted.
// If map is not nil, an error was encountered when restarting one or more
// containers. The container ID is mapped to the error encountered. The error is
-// set to ErrCtrExists
-// If both error and the map are nil, all containers were restarted without error
+// set to ErrPodPartialFail.
+// If both error and the map are nil, all containers were restarted without error.
func (p *Pod) Restart(ctx context.Context) (map[string]error, error) {
p.lock.Lock()
defer p.lock.Unlock()
@@ -328,17 +400,17 @@ func (p *Pod) Restart(ctx context.Context) (map[string]error, error) {
return nil, nil
}
-// Kill sends a signal to all running containers within a pod
+// Kill sends a signal to all running containers within a pod.
// Signals will only be sent to running containers. Containers that are not
// running will be ignored. All signals are sent independently, and sending will
// continue even if some containers encounter errors.
-// An error and a map[string]error are returned
+// An error and a map[string]error are returned.
// If the error is not nil and the map is nil, an error was encountered before
-// any containers were signalled
+// any containers were signalled.
// If map is not nil, an error was encountered when signalling one or more
// containers. The container ID is mapped to the error encountered. The error is
-// set to ErrCtrExists
-// If both error and the map are nil, all containers were signalled successfully
+// set to ErrPodPartialFail.
+// If both error and the map are nil, all containers were signalled successfully.
func (p *Pod) Kill(signal uint) (map[string]error, error) {
p.lock.Lock()
defer p.lock.Unlock()
@@ -393,8 +465,8 @@ func (p *Pod) Kill(signal uint) (map[string]error, error) {
return nil, nil
}
-// Status gets the status of all containers in the pod
-// Returns a map of Container ID to Container Status
+// Status gets the status of all containers in the pod.
+// Returns a map of Container ID to Container Status.
func (p *Pod) Status() (map[string]define.ContainerStatus, error) {
p.lock.Lock()
defer p.lock.Unlock()
@@ -430,7 +502,7 @@ func containerStatusFromContainers(allCtrs []*Container) (map[string]define.Cont
return status, nil
}
-// Inspect returns a PodInspect struct to describe the pod
+// Inspect returns a PodInspect struct to describe the pod.
func (p *Pod) Inspect() (*define.InspectPodData, error) {
p.lock.Lock()
defer p.lock.Unlock()
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
index 24802f89e..faa627ff1 100644
--- a/libpod/runtime_pod_infra_linux.go
+++ b/libpod/runtime_pod_infra_linux.go
@@ -83,6 +83,9 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
return nil, errors.Wrapf(err, "error removing network namespace from pod %s infra container", p.ID())
}
+ // For each option in InfraContainerConfig - if set, pass into
+ // the infra container we're creating with the appropriate
+ // With... option.
if p.config.InfraContainer.StaticIP != nil {
options = append(options, WithStaticIP(p.config.InfraContainer.StaticIP))
}
@@ -107,6 +110,9 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
if len(p.config.InfraContainer.HostAdd) > 0 {
options = append(options, WithHosts(p.config.InfraContainer.HostAdd))
}
+ if len(p.config.InfraContainer.ExitCommand) > 0 {
+ options = append(options, WithExitCommand(p.config.InfraContainer.ExitCommand))
+ }
}
g.SetRootReadonly(true)