summaryrefslogtreecommitdiff
path: root/libpod/pod_api.go
diff options
context:
space:
mode:
authorBrent Baude <bbaude@redhat.com>2021-07-14 16:03:55 -0500
committerBrent Baude <bbaude@redhat.com>2021-08-04 14:14:36 -0500
commit3c3fa6fac4d0f8e89181ea2d4e1fe0318d24b6f4 (patch)
treef087d0a772797a9028df514d8d0369835724b3a2 /libpod/pod_api.go
parente93661f5e765d84893e2ad5a488682c0a67412d0 (diff)
downloadpodman-3c3fa6fac4d0f8e89181ea2d4e1fe0318d24b6f4.tar.gz
podman-3c3fa6fac4d0f8e89181ea2d4e1fe0318d24b6f4.tar.bz2
podman-3c3fa6fac4d0f8e89181ea2d4e1fe0318d24b6f4.zip
implement init containers in podman
this is the first pass at implementing init containers for podman pods. init containersare made popular by k8s as a way to run setup for pods before the pods standard containers run. unlike k8s, we support two styles of init containers: always and oneshot. always means the container stays in the pod and starts whenever a pod is started. this does not apply to pods restarting. oneshot means the container runs onetime when the pod starts and then is removed. Signed-off-by: Brent Baude <bbaude@redhat.com>
Diffstat (limited to 'libpod/pod_api.go')
-rw-r--r--libpod/pod_api.go67
1 files changed, 59 insertions, 8 deletions
diff --git a/libpod/pod_api.go b/libpod/pod_api.go
index 1ab012a8b..90d67dbb0 100644
--- a/libpod/pod_api.go
+++ b/libpod/pod_api.go
@@ -12,6 +12,45 @@ import (
"github.com/sirupsen/logrus"
)
+// startInitContainers starts a pod's init containers.
+func (p *Pod) startInitContainers(ctx context.Context) error {
+ initCtrs, err := p.initContainers()
+ if err != nil {
+ return err
+ }
+ // Now iterate init containers
+ for _, initCon := range initCtrs {
+ if err := initCon.Start(ctx, true); err != nil {
+ return err
+ }
+ // Check that the init container waited correctly and the exit
+ // code is good
+ rc, err := initCon.Wait(ctx)
+ if err != nil {
+ return err
+ }
+ if rc != 0 {
+ return errors.Errorf("init container %s exited with code %d", initCon.ID(), rc)
+ }
+ // If the container is an oneshot init container, we need to remove it
+ // after it runs
+ if initCon.Config().InitContainerType == define.OneShotInitContainer {
+ icLock := initCon.lock
+ icLock.Lock()
+ if err := p.runtime.removeContainer(ctx, initCon, false, false, true); err != nil {
+ icLock.Unlock()
+ return errors.Wrapf(err, "failed to remove oneshot init container %s", initCon.ID())
+ }
+ // Removing a container this way requires an explicit call to clean up the db
+ if err := p.runtime.state.RemoveContainerFromPod(p, initCon); err != nil {
+ logrus.Errorf("Error removing container %s from database: %v", initCon.ID(), err)
+ }
+ icLock.Unlock()
+ }
+ }
+ return nil
+}
+
// 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,
@@ -34,26 +73,29 @@ func (p *Pod) Start(ctx context.Context) (map[string]error, error) {
return nil, define.ErrPodRemoved
}
+ // Before "regular" containers start in the pod, all init containers
+ // must have run and exited successfully.
+ if err := p.startInitContainers(ctx); err != nil {
+ return nil, err
+ }
allCtrs, err := p.runtime.state.PodContainers(p)
if err != nil {
return nil, err
}
-
// Build a dependency graph of containers in the pod
graph, err := BuildContainerGraph(allCtrs)
if err != nil {
return nil, errors.Wrapf(err, "error generating dependency graph for pod %s", p.ID())
}
-
- ctrErrors := make(map[string]error)
- ctrsVisited := make(map[string]bool)
-
// If there are no containers without dependencies, we can't start
// Error out
if len(graph.noDepNodes) == 0 {
return nil, errors.Wrapf(define.ErrNoSuchCtr, "no containers in pod %s have no dependencies, cannot start pod", p.ID())
}
+ ctrErrors := make(map[string]error)
+ ctrsVisited := make(map[string]bool)
+
// Traverse the graph beginning at nodes with no dependencies
for _, node := range graph.noDepNodes {
startNode(ctx, node, false, ctrErrors, ctrsVisited, false)
@@ -449,12 +491,18 @@ func (p *Pod) Status() (map[string]define.ContainerStatus, error) {
if !p.valid {
return nil, define.ErrPodRemoved
}
-
allCtrs, err := p.runtime.state.PodContainers(p)
if err != nil {
return nil, err
}
- return containerStatusFromContainers(allCtrs)
+ noInitCtrs := make([]*Container, 0)
+ // Do not add init containers into status
+ for _, ctr := range allCtrs {
+ if ctrType := ctr.config.InitContainerType; len(ctrType) < 1 {
+ noInitCtrs = append(noInitCtrs, ctr)
+ }
+ }
+ return containerStatusFromContainers(noInitCtrs)
}
func containerStatusFromContainers(allCtrs []*Container) (map[string]define.ContainerStatus, error) {
@@ -504,7 +552,10 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
Name: c.Name(),
State: containerStatus,
})
- ctrStatuses[c.ID()] = c.state.State
+ // Do not add init containers fdr status
+ if len(c.config.InitContainerType) < 1 {
+ ctrStatuses[c.ID()] = c.state.State
+ }
}
podState, err := createPodStatusResults(ctrStatuses)
if err != nil {