diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_config.go | 4 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 43 | ||||
-rw-r--r-- | libpod/container_path_resolution.go | 2 | ||||
-rw-r--r-- | libpod/define/container.go | 9 | ||||
-rw-r--r-- | libpod/define/container_inspect.go | 2 | ||||
-rw-r--r-- | libpod/kube.go | 49 | ||||
-rw-r--r-- | libpod/options.go | 22 | ||||
-rw-r--r-- | libpod/pod_internal.go | 7 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 5 | ||||
-rw-r--r-- | libpod/runtime_pod_linux.go | 25 |
10 files changed, 133 insertions, 35 deletions
diff --git a/libpod/container_config.go b/libpod/container_config.go index da732c05b..904c03f9b 100644 --- a/libpod/container_config.go +++ b/libpod/container_config.go @@ -301,7 +301,7 @@ type ContainerMiscConfig struct { StopSignal uint `json:"stopSignal,omitempty"` // StopTimeout is the signal that will be used to stop the container StopTimeout uint `json:"stopTimeout,omitempty"` - // Timeout is maximimum time a container will run before getting the kill signal + // Timeout is maximum time a container will run before getting the kill signal Timeout uint `json:"timeout,omitempty"` // Time container was created CreatedTime time.Time `json:"createdTime"` @@ -373,4 +373,6 @@ type ContainerMiscConfig struct { PidFile string `json:"pid_file,omitempty"` // CDIDevices contains devices that use the CDI CDIDevices []string `json:"cdiDevices,omitempty"` + // EnvSecrets are secrets that are set as environment variables + EnvSecrets map[string]*secrets.Secret `json:"secret_env,omitempty"` } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index f87e845cb..7d57e8965 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -29,6 +29,7 @@ import ( "github.com/containers/common/pkg/apparmor" "github.com/containers/common/pkg/chown" "github.com/containers/common/pkg/config" + "github.com/containers/common/pkg/secrets" "github.com/containers/common/pkg/subscriptions" "github.com/containers/common/pkg/umask" "github.com/containers/podman/v3/libpod/define" @@ -377,14 +378,8 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { case "z": fallthrough case "Z": - if c.MountLabel() != "" { - if c.ProcessLabel() != "" { - if err := label.Relabel(m.Source, c.MountLabel(), label.IsShared(o)); err != nil { - return nil, err - } - } else { - logrus.Infof("Not relabeling volume %q in container %s as SELinux is disabled", m.Source, c.ID()) - } + if err := label.Relabel(m.Source, c.MountLabel(), label.IsShared(o)); err != nil { + return nil, err } default: @@ -763,6 +758,19 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { if c.state.ExtensionStageHooks, err = c.setupOCIHooks(ctx, g.Config); err != nil { return nil, errors.Wrapf(err, "error setting up OCI Hooks") } + if len(c.config.EnvSecrets) > 0 { + manager, err := secrets.NewManager(c.runtime.GetSecretsStorageDir()) + if err != nil { + return nil, err + } + for name, secr := range c.config.EnvSecrets { + _, data, err := manager.LookupSecretData(secr.Name) + if err != nil { + return nil, err + } + g.AddProcessEnv(name, string(data)) + } + } return g.Config, nil } @@ -2216,6 +2224,17 @@ func (c *Container) generatePasswdAndGroup() (string, string, error) { return passwdPath, groupPath, nil } +func isRootlessCgroupSet(cgroup string) bool { + // old versions of podman were setting the CgroupParent to CgroupfsDefaultCgroupParent + // by default. Avoid breaking these versions and check whether the cgroup parent is + // set to the default and in this case enable the old behavior. It should not be a real + // problem because the default CgroupParent is usually owned by root so rootless users + // cannot access it. + // This check might be lifted in a future version of Podman. + // Check both that the cgroup or its parent is set to the default value (used by pods). + return cgroup != CgroupfsDefaultCgroupParent && filepath.Dir(cgroup) != CgroupfsDefaultCgroupParent +} + // Get cgroup path in a format suitable for the OCI spec func (c *Container) getOCICgroupPath() (string, error) { unified, err := cgroups.IsCgroup2UnifiedMode() @@ -2227,13 +2246,7 @@ func (c *Container) getOCICgroupPath() (string, error) { case c.config.NoCgroups: return "", nil case (rootless.IsRootless() && (cgroupManager == config.CgroupfsCgroupsManager || !unified)): - if c.config.CgroupParent == CgroupfsDefaultCgroupParent { - // old versions of podman were setting the CgroupParent to CgroupfsDefaultCgroupParent - // by default. Avoid breaking these versions and check whether the cgroup parent is - // set to the default and in this case enable the old behavior. It should not be a real - // problem because the default CgroupParent is usually owned by root so rootless users - // cannot access it. - // This check might be lifted in a future version of Podman. + if !isRootlessCgroupSet(c.config.CgroupParent) { return "", nil } return c.config.CgroupParent, nil diff --git a/libpod/container_path_resolution.go b/libpod/container_path_resolution.go index d798963b1..ec7306ca1 100644 --- a/libpod/container_path_resolution.go +++ b/libpod/container_path_resolution.go @@ -128,7 +128,7 @@ func isPathOnVolume(c *Container, containerPath string) bool { if cleanedContainerPath == filepath.Clean(vol.Dest) { return true } - for dest := vol.Dest; dest != "/"; dest = filepath.Dir(dest) { + for dest := vol.Dest; dest != "/" && dest != "."; dest = filepath.Dir(dest) { if cleanedContainerPath == dest { return true } diff --git a/libpod/define/container.go b/libpod/define/container.go index 5a2ff026f..f3125afa9 100644 --- a/libpod/define/container.go +++ b/libpod/define/container.go @@ -17,3 +17,12 @@ const ( // handling of system restart, which Podman does not yet support. RestartPolicyUnlessStopped = "unless-stopped" ) + +// RestartPolicyMap maps between restart-policy valid values to restart policy types +var RestartPolicyMap = map[string]string{ + "none": RestartPolicyNone, + RestartPolicyNo: RestartPolicyNo, + RestartPolicyAlways: RestartPolicyAlways, + RestartPolicyOnFailure: RestartPolicyOnFailure, + RestartPolicyUnlessStopped: RestartPolicyUnlessStopped, +} diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go index c236f35b0..5283946fa 100644 --- a/libpod/define/container_inspect.go +++ b/libpod/define/container_inspect.go @@ -66,7 +66,7 @@ type InspectContainerConfig struct { Secrets []*InspectSecret `json:"Secrets,omitempty"` // Timeout is time before container is killed by conmon Timeout uint `json:"Timeout"` - // StopTimeout is time before container is stoped when calling stop + // StopTimeout is time before container is stopped when calling stop StopTimeout uint `json:"StopTimeout"` } diff --git a/libpod/kube.go b/libpod/kube.go index adcfe92c9..a3f49bfe8 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -218,9 +218,15 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor deDupPodVolumes := make(map[string]*v1.Volume) first := true podContainers := make([]v1.Container, 0, len(containers)) + podAnnotations := make(map[string]string) dnsInfo := v1.PodDNSConfig{} for _, ctr := range containers { if !ctr.IsInfra() { + // Convert auto-update labels into kube annotations + for k, v := range getAutoUpdateAnnotations(removeUnderscores(ctr.Name()), ctr.Labels()) { + podAnnotations[k] = v + } + ctr, volumes, _, err := containerToV1Container(ctr) if err != nil { return nil, err @@ -267,10 +273,16 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor podVolumes = append(podVolumes, *vol) } - return addContainersAndVolumesToPodObject(podContainers, podVolumes, p.Name(), &dnsInfo, hostNetwork), nil + return newPodObject( + p.Name(), + podAnnotations, + podContainers, + podVolumes, + &dnsInfo, + hostNetwork), nil } -func addContainersAndVolumesToPodObject(containers []v1.Container, volumes []v1.Volume, podName string, dnsOptions *v1.PodDNSConfig, hostNetwork bool) *v1.Pod { +func newPodObject(podName string, annotations map[string]string, containers []v1.Container, volumes []v1.Volume, dnsOptions *v1.PodDNSConfig, hostNetwork bool) *v1.Pod { tm := v12.TypeMeta{ Kind: "Pod", APIVersion: "v1", @@ -287,6 +299,7 @@ func addContainersAndVolumesToPodObject(containers []v1.Container, volumes []v1. // will reflect time this is run (not container create time) because the conversion // of the container create time to v1 Time is probably not warranted nor worthwhile. CreationTimestamp: v12.Now(), + Annotations: annotations, } ps := v1.PodSpec{ Containers: containers, @@ -311,7 +324,13 @@ func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) { kubeVolumes := make([]v1.Volume, 0) hostNetwork := true podDNS := v1.PodDNSConfig{} + kubeAnnotations := make(map[string]string) for _, ctr := range ctrs { + // Convert auto-update labels into kube annotations + for k, v := range getAutoUpdateAnnotations(removeUnderscores(ctr.Name()), ctr.Labels()) { + kubeAnnotations[k] = v + } + if !ctr.HostNetwork() { hostNetwork = false } @@ -355,7 +374,13 @@ func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) { } } // end if ctrDNS } - return addContainersAndVolumesToPodObject(kubeCtrs, kubeVolumes, strings.ReplaceAll(ctrs[0].Name(), "_", ""), &podDNS, hostNetwork), nil + return newPodObject( + strings.ReplaceAll(ctrs[0].Name(), "_", ""), + kubeAnnotations, + kubeCtrs, + kubeVolumes, + &podDNS, + hostNetwork), nil } // containerToV1Container converts information we know about a libpod container @@ -792,3 +817,21 @@ func generateKubeVolumeDeviceFromLinuxDevice(devices []specs.LinuxDevice) []v1.V func removeUnderscores(s string) string { return strings.Replace(s, "_", "", -1) } + +// getAutoUpdateAnnotations searches for auto-update container labels +// and returns them as kube annotations +func getAutoUpdateAnnotations(ctrName string, ctrLabels map[string]string) map[string]string { + autoUpdateLabel := "io.containers.autoupdate" + annotations := make(map[string]string) + + for k, v := range ctrLabels { + if strings.Contains(k, autoUpdateLabel) { + // since labels can variate between containers within a pod, they will be + // identified with the container name when converted into kube annotations + kc := fmt.Sprintf("%s/%s", k, ctrName) + annotations[kc] = v + } + } + + return annotations +} diff --git a/libpod/options.go b/libpod/options.go index 391cf0147..be26ced99 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1716,6 +1716,28 @@ func WithSecrets(secretNames []string) CtrCreateOption { } } +// WithSecrets adds environment variable secrets to the container +func WithEnvSecrets(envSecrets map[string]string) CtrCreateOption { + return func(ctr *Container) error { + ctr.config.EnvSecrets = make(map[string]*secrets.Secret) + if ctr.valid { + return define.ErrCtrFinalized + } + manager, err := secrets.NewManager(ctr.runtime.GetSecretsStorageDir()) + if err != nil { + return err + } + for target, src := range envSecrets { + secr, err := manager.Lookup(src) + if err != nil { + return err + } + ctr.config.EnvSecrets[target] = secr + } + return nil + } +} + // WithPidFile adds pidFile to the container func WithPidFile(pidFile string) CtrCreateOption { return func(ctr *Container) error { diff --git a/libpod/pod_internal.go b/libpod/pod_internal.go index 31b4ba443..e81bd7b16 100644 --- a/libpod/pod_internal.go +++ b/libpod/pod_internal.go @@ -7,6 +7,7 @@ import ( "github.com/containers/common/pkg/config" "github.com/containers/podman/v3/libpod/define" + "github.com/containers/podman/v3/pkg/rootless" "github.com/containers/storage/pkg/stringid" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -74,9 +75,11 @@ func (p *Pod) refresh() error { } p.state.CgroupPath = cgroupPath case config.CgroupfsCgroupsManager: - p.state.CgroupPath = filepath.Join(p.config.CgroupParent, p.ID()) + if rootless.IsRootless() && isRootlessCgroupSet(p.config.CgroupParent) { + p.state.CgroupPath = filepath.Join(p.config.CgroupParent, p.ID()) - logrus.Debugf("setting pod cgroup to %s", p.state.CgroupPath) + logrus.Debugf("setting pod cgroup to %s", p.state.CgroupPath) + } default: return errors.Wrapf(define.ErrInvalidArg, "unknown cgroups manager %s specified", p.runtime.config.Engine.CgroupManager) } diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 328f47c12..7d31e392f 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -295,7 +295,10 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai if podCgroup == "" { return nil, errors.Wrapf(define.ErrInternal, "pod %s cgroup is not set", pod.ID()) } - ctr.config.CgroupParent = podCgroup + canUseCgroup := !rootless.IsRootless() || isRootlessCgroupSet(podCgroup) + if canUseCgroup { + ctr.config.CgroupParent = podCgroup + } } else if !rootless.IsRootless() { ctr.config.CgroupParent = CgroupfsDefaultCgroupParent } diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go index cf48a9453..4ede23cac 100644 --- a/libpod/runtime_pod_linux.go +++ b/libpod/runtime_pod_linux.go @@ -75,17 +75,20 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po // Check CGroup parent sanity, and set it if it was not set switch r.config.Engine.CgroupManager { case config.CgroupfsCgroupsManager: - if pod.config.CgroupParent == "" { - pod.config.CgroupParent = CgroupfsDefaultCgroupParent - } else if strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") { - return nil, errors.Wrapf(define.ErrInvalidArg, "systemd slice received as cgroup parent when using cgroupfs") - } - // If we are set to use pod cgroups, set the cgroup parent that - // all containers in the pod will share - // No need to create it with cgroupfs - the first container to - // launch should do it for us - if pod.config.UsePodCgroup { - pod.state.CgroupPath = filepath.Join(pod.config.CgroupParent, pod.ID()) + canUseCgroup := !rootless.IsRootless() || isRootlessCgroupSet(pod.config.CgroupParent) + if canUseCgroup { + if pod.config.CgroupParent == "" { + pod.config.CgroupParent = CgroupfsDefaultCgroupParent + } else if strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") { + return nil, errors.Wrapf(define.ErrInvalidArg, "systemd slice received as cgroup parent when using cgroupfs") + } + // If we are set to use pod cgroups, set the cgroup parent that + // all containers in the pod will share + // No need to create it with cgroupfs - the first container to + // launch should do it for us + if pod.config.UsePodCgroup { + pod.state.CgroupPath = filepath.Join(pod.config.CgroupParent, pod.ID()) + } } case config.SystemdCgroupsManager: if pod.config.CgroupParent == "" { |