diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_inspect.go | 2 | ||||
-rw-r--r-- | libpod/container_validate.go | 2 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 20 | ||||
-rw-r--r-- | libpod/service.go | 15 |
4 files changed, 33 insertions, 6 deletions
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 5d809644d..93240812d 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -171,7 +171,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver Mounts: inspectMounts, Dependencies: c.Dependencies(), IsInfra: c.IsInfra(), - IsService: c.isService(), + IsService: c.IsService(), } if c.state.ConfigPath != "" { diff --git a/libpod/container_validate.go b/libpod/container_validate.go index d939c94e6..cfbdd2b1e 100644 --- a/libpod/container_validate.go +++ b/libpod/container_validate.go @@ -31,7 +31,7 @@ func (c *Container) validate() error { // A container cannot be marked as an infra and service container at // the same time. - if c.IsInfra() && c.isService() { + if c.IsInfra() && c.IsService() { return fmt.Errorf("cannot be infra and service container at the same time: %w", define.ErrInvalidArg) } diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 7e8a21a8c..2eaa77572 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -644,6 +644,16 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo return err } + if c.IsService() { + canStop, err := c.canStopServiceContainer() + if err != nil { + return err + } + if !canStop { + return fmt.Errorf("container %s is the service container of pod(s) %s and cannot be removed without removing the pod(s)", c.ID(), strings.Join(c.state.Service.Pods, ",")) + } + } + // If we're not force-removing, we need to check if we're in a good // state to remove. if !force { @@ -907,6 +917,16 @@ func (r *Runtime) evictContainer(ctx context.Context, idOrName string, removeVol } } + if c.IsService() { + canStop, err := c.canStopServiceContainer() + if err != nil { + return id, err + } + if !canStop { + return id, fmt.Errorf("container %s is the service container of pod(s) %s and cannot be removed without removing the pod(s)", c.ID(), strings.Join(c.state.Service.Pods, ",")) + } + } + var cleanupErr error // Remove the container from the state if c.config.Pod != "" { diff --git a/libpod/service.go b/libpod/service.go index ad147e87b..c14f5e51d 100644 --- a/libpod/service.go +++ b/libpod/service.go @@ -54,11 +54,12 @@ func (c *Container) addServicePodLocked(id string) error { return c.save() } -func (c *Container) isService() bool { +// IsService returns true when the container is a "service container". +func (c *Container) IsService() bool { return c.config.IsService } -// canStopServiceContainer returns true if all pods of the service are stopped. +// canStopServiceContainerLocked 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() @@ -67,10 +68,16 @@ func (c *Container) canStopServiceContainerLocked() (bool, error) { return false, err } - if !c.isService() { + if !c.IsService() { return false, fmt.Errorf("internal error: checking service: container %s is not a service container", c.ID()) } + return c.canStopServiceContainer() +} + +// canStopServiceContainer returns true if all pods of the service are stopped. +// Note that the method expects the container to be locked. +func (c *Container) canStopServiceContainer() (bool, error) { for _, id := range c.state.Service.Pods { pod, err := c.runtime.LookupPod(id) if err != nil { @@ -163,7 +170,7 @@ func (c *Container) canRemoveServiceContainerLocked() (bool, error) { return false, err } - if !c.isService() { + if !c.IsService() { return false, fmt.Errorf("internal error: checking service: container %s is not a service container", c.ID()) } |