mirror of
https://github.com/containers/podman.git
synced 2025-06-26 21:07:02 +08:00
Merge pull request #11793 from baude/playgenkubeselinux
Support selinux options with bind mounts play/gen
This commit is contained in:
@ -90,3 +90,6 @@ const (
|
|||||||
|
|
||||||
// DefaultRlimitValue is the value set by default for nofile and nproc
|
// DefaultRlimitValue is the value set by default for nofile and nproc
|
||||||
const RLimitDefaultValue = uint64(1048576)
|
const RLimitDefaultValue = uint64(1048576)
|
||||||
|
|
||||||
|
// BindMountPrefix distinguishes its annotations from others
|
||||||
|
const BindMountPrefix = "bind-mount-options:"
|
||||||
|
@ -241,11 +241,13 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
|
|||||||
|
|
||||||
isInit := ctr.IsInitCtr()
|
isInit := ctr.IsInitCtr()
|
||||||
|
|
||||||
ctr, volumes, _, err := containerToV1Container(ctx, ctr)
|
ctr, volumes, _, annotations, err := containerToV1Container(ctx, ctr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
for k, v := range annotations {
|
||||||
|
podAnnotations[define.BindMountPrefix+k] = v
|
||||||
|
}
|
||||||
// Since port bindings for the pod are handled by the
|
// Since port bindings for the pod are handled by the
|
||||||
// infra container, wipe them here.
|
// infra container, wipe them here.
|
||||||
ctr.Ports = nil
|
ctr.Ports = nil
|
||||||
@ -271,7 +273,7 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
|
|||||||
deDupPodVolumes[vol.Name] = &vol
|
deDupPodVolumes[vol.Name] = &vol
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_, _, infraDNS, err := containerToV1Container(ctx, ctr)
|
_, _, infraDNS, _, err := containerToV1Container(ctx, ctr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -359,17 +361,19 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod,
|
|||||||
if !ctr.HostNetwork() {
|
if !ctr.HostNetwork() {
|
||||||
hostNetwork = false
|
hostNetwork = false
|
||||||
}
|
}
|
||||||
kubeCtr, kubeVols, ctrDNS, err := containerToV1Container(ctx, ctr)
|
kubeCtr, kubeVols, ctrDNS, annotations, err := containerToV1Container(ctx, ctr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
for k, v := range annotations {
|
||||||
|
kubeAnnotations[define.BindMountPrefix+k] = v
|
||||||
|
}
|
||||||
if isInit {
|
if isInit {
|
||||||
kubeInitCtrs = append(kubeInitCtrs, kubeCtr)
|
kubeInitCtrs = append(kubeInitCtrs, kubeCtr)
|
||||||
} else {
|
} else {
|
||||||
kubeCtrs = append(kubeCtrs, kubeCtr)
|
kubeCtrs = append(kubeCtrs, kubeCtr)
|
||||||
}
|
}
|
||||||
kubeVolumes = append(kubeVolumes, kubeVols...)
|
kubeVolumes = append(kubeVolumes, kubeVols...)
|
||||||
|
|
||||||
// Combine DNS information in sum'd structure
|
// Combine DNS information in sum'd structure
|
||||||
if ctrDNS != nil {
|
if ctrDNS != nil {
|
||||||
// nameservers
|
// nameservers
|
||||||
@ -415,42 +419,44 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod,
|
|||||||
|
|
||||||
// containerToV1Container converts information we know about a libpod container
|
// containerToV1Container converts information we know about a libpod container
|
||||||
// to a V1.Container specification.
|
// to a V1.Container specification.
|
||||||
func containerToV1Container(ctx context.Context, c *Container) (v1.Container, []v1.Volume, *v1.PodDNSConfig, error) {
|
func containerToV1Container(ctx context.Context, c *Container) (v1.Container, []v1.Volume, *v1.PodDNSConfig, map[string]string, error) {
|
||||||
kubeContainer := v1.Container{}
|
kubeContainer := v1.Container{}
|
||||||
kubeVolumes := []v1.Volume{}
|
kubeVolumes := []v1.Volume{}
|
||||||
|
annotations := make(map[string]string)
|
||||||
kubeSec, err := generateKubeSecurityContext(c)
|
kubeSec, err := generateKubeSecurityContext(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return kubeContainer, kubeVolumes, nil, err
|
return kubeContainer, kubeVolumes, nil, annotations, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: a privileged container mounts all of /dev/*.
|
// NOTE: a privileged container mounts all of /dev/*.
|
||||||
if !c.Privileged() && len(c.config.Spec.Linux.Devices) > 0 {
|
if !c.Privileged() && len(c.config.Spec.Linux.Devices) > 0 {
|
||||||
// TODO Enable when we can support devices and their names
|
// TODO Enable when we can support devices and their names
|
||||||
kubeContainer.VolumeDevices = generateKubeVolumeDeviceFromLinuxDevice(c.config.Spec.Linux.Devices)
|
kubeContainer.VolumeDevices = generateKubeVolumeDeviceFromLinuxDevice(c.config.Spec.Linux.Devices)
|
||||||
return kubeContainer, kubeVolumes, nil, errors.Wrapf(define.ErrNotImplemented, "linux devices")
|
return kubeContainer, kubeVolumes, nil, annotations, errors.Wrapf(define.ErrNotImplemented, "linux devices")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.config.UserVolumes) > 0 {
|
if len(c.config.UserVolumes) > 0 {
|
||||||
volumeMounts, volumes, err := libpodMountsToKubeVolumeMounts(c)
|
volumeMounts, volumes, localAnnotations, err := libpodMountsToKubeVolumeMounts(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return kubeContainer, kubeVolumes, nil, err
|
return kubeContainer, kubeVolumes, nil, nil, err
|
||||||
}
|
}
|
||||||
|
annotations = localAnnotations
|
||||||
kubeContainer.VolumeMounts = volumeMounts
|
kubeContainer.VolumeMounts = volumeMounts
|
||||||
kubeVolumes = append(kubeVolumes, volumes...)
|
kubeVolumes = append(kubeVolumes, volumes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
envVariables, err := libpodEnvVarsToKubeEnvVars(c.config.Spec.Process.Env)
|
envVariables, err := libpodEnvVarsToKubeEnvVars(c.config.Spec.Process.Env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return kubeContainer, kubeVolumes, nil, err
|
return kubeContainer, kubeVolumes, nil, annotations, err
|
||||||
}
|
}
|
||||||
|
|
||||||
portmappings, err := c.PortMappings()
|
portmappings, err := c.PortMappings()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return kubeContainer, kubeVolumes, nil, err
|
return kubeContainer, kubeVolumes, nil, annotations, err
|
||||||
}
|
}
|
||||||
ports, err := ocicniPortMappingToContainerPort(portmappings)
|
ports, err := ocicniPortMappingToContainerPort(portmappings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return kubeContainer, kubeVolumes, nil, err
|
return kubeContainer, kubeVolumes, nil, annotations, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle command and arguments.
|
// Handle command and arguments.
|
||||||
@ -469,11 +475,11 @@ func containerToV1Container(ctx context.Context, c *Container) (v1.Container, []
|
|||||||
kubeContainer.Stdin = c.Stdin()
|
kubeContainer.Stdin = c.Stdin()
|
||||||
img, _, err := c.runtime.libimageRuntime.LookupImage(image, nil)
|
img, _, err := c.runtime.libimageRuntime.LookupImage(image, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return kubeContainer, kubeVolumes, nil, err
|
return kubeContainer, kubeVolumes, nil, annotations, err
|
||||||
}
|
}
|
||||||
imgData, err := img.Inspect(ctx, false)
|
imgData, err := img.Inspect(ctx, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return kubeContainer, kubeVolumes, nil, err
|
return kubeContainer, kubeVolumes, nil, annotations, err
|
||||||
}
|
}
|
||||||
if reflect.DeepEqual(imgData.Config.Cmd, kubeContainer.Command) {
|
if reflect.DeepEqual(imgData.Config.Cmd, kubeContainer.Command) {
|
||||||
kubeContainer.Command = nil
|
kubeContainer.Command = nil
|
||||||
@ -555,7 +561,7 @@ func containerToV1Container(ctx context.Context, c *Container) (v1.Container, []
|
|||||||
}
|
}
|
||||||
dns.Options = dnsOptions
|
dns.Options = dnsOptions
|
||||||
}
|
}
|
||||||
return kubeContainer, kubeVolumes, &dns, nil
|
return kubeContainer, kubeVolumes, &dns, annotations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ocicniPortMappingToContainerPort takes an ocicni portmapping and converts
|
// ocicniPortMappingToContainerPort takes an ocicni portmapping and converts
|
||||||
@ -606,16 +612,23 @@ func libpodEnvVarsToKubeEnvVars(envs []string) ([]v1.EnvVar, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// libpodMountsToKubeVolumeMounts converts the containers mounts to a struct kube understands
|
// libpodMountsToKubeVolumeMounts converts the containers mounts to a struct kube understands
|
||||||
func libpodMountsToKubeVolumeMounts(c *Container) ([]v1.VolumeMount, []v1.Volume, error) {
|
func libpodMountsToKubeVolumeMounts(c *Container) ([]v1.VolumeMount, []v1.Volume, map[string]string, error) {
|
||||||
namedVolumes, mounts := c.sortUserVolumes(c.config.Spec)
|
namedVolumes, mounts := c.sortUserVolumes(c.config.Spec)
|
||||||
vms := make([]v1.VolumeMount, 0, len(mounts))
|
vms := make([]v1.VolumeMount, 0, len(mounts))
|
||||||
vos := make([]v1.Volume, 0, len(mounts))
|
vos := make([]v1.Volume, 0, len(mounts))
|
||||||
|
annotations := make(map[string]string)
|
||||||
|
|
||||||
var suffix string
|
var suffix string
|
||||||
for index, m := range mounts {
|
for index, m := range mounts {
|
||||||
|
for _, opt := range m.Options {
|
||||||
|
if opt == "Z" || opt == "z" {
|
||||||
|
annotations[m.Source] = opt
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
vm, vo, err := generateKubeVolumeMount(m)
|
vm, vo, err := generateKubeVolumeMount(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return vms, vos, err
|
return vms, vos, annotations, err
|
||||||
}
|
}
|
||||||
// Name will be the same, so use the index as suffix
|
// Name will be the same, so use the index as suffix
|
||||||
suffix = fmt.Sprintf("-%d", index)
|
suffix = fmt.Sprintf("-%d", index)
|
||||||
@ -629,7 +642,7 @@ func libpodMountsToKubeVolumeMounts(c *Container) ([]v1.VolumeMount, []v1.Volume
|
|||||||
vms = append(vms, vm)
|
vms = append(vms, vm)
|
||||||
vos = append(vos, vo)
|
vos = append(vos, vo)
|
||||||
}
|
}
|
||||||
return vms, vos, nil
|
return vms, vos, annotations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateKubePersistentVolumeClaim converts a ContainerNamedVolume to a Kubernetes PersistentVolumeClaim
|
// generateKubePersistentVolumeClaim converts a ContainerNamedVolume to a Kubernetes PersistentVolumeClaim
|
||||||
|
@ -319,8 +319,8 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
specgenOpts := kube.CtrSpecGenOptions{
|
specgenOpts := kube.CtrSpecGenOptions{
|
||||||
|
Annotations: annotations,
|
||||||
Container: initCtr,
|
Container: initCtr,
|
||||||
Image: pulledImage,
|
Image: pulledImage,
|
||||||
Volumes: volumes,
|
Volumes: volumes,
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/containers/common/pkg/parse"
|
"github.com/containers/common/pkg/parse"
|
||||||
"github.com/containers/common/pkg/secrets"
|
"github.com/containers/common/pkg/secrets"
|
||||||
"github.com/containers/image/v5/manifest"
|
"github.com/containers/image/v5/manifest"
|
||||||
|
"github.com/containers/podman/v3/libpod/define"
|
||||||
"github.com/containers/podman/v3/libpod/network/types"
|
"github.com/containers/podman/v3/libpod/network/types"
|
||||||
ann "github.com/containers/podman/v3/pkg/annotations"
|
ann "github.com/containers/podman/v3/pkg/annotations"
|
||||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||||
@ -86,6 +87,8 @@ func ToPodOpt(ctx context.Context, podName string, p entities.PodCreateOptions,
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CtrSpecGenOptions struct {
|
type CtrSpecGenOptions struct {
|
||||||
|
// Annotations from the Pod
|
||||||
|
Annotations map[string]string
|
||||||
// Container as read from the pod yaml
|
// Container as read from the pod yaml
|
||||||
Container v1.Container
|
Container v1.Container
|
||||||
// Image available to use (pulled or found local)
|
// Image available to use (pulled or found local)
|
||||||
@ -289,6 +292,14 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
|
|||||||
volume.MountPath = dest
|
volume.MountPath = dest
|
||||||
switch volumeSource.Type {
|
switch volumeSource.Type {
|
||||||
case KubeVolumeTypeBindMount:
|
case KubeVolumeTypeBindMount:
|
||||||
|
// If the container has bind mounts, we need to check if
|
||||||
|
// a selinux mount option exists for it
|
||||||
|
for k, v := range opts.Annotations {
|
||||||
|
// Make sure the z/Z option is not already there (from editing the YAML)
|
||||||
|
if strings.Replace(k, define.BindMountPrefix, "", 1) == volumeSource.Source && !util.StringInSlice("z", options) && !util.StringInSlice("Z", options) {
|
||||||
|
options = append(options, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
mount := spec.Mount{
|
mount := spec.Mount{
|
||||||
Destination: volume.MountPath,
|
Destination: volume.MountPath,
|
||||||
Source: volumeSource.Source,
|
Source: volumeSource.Source,
|
||||||
|
@ -6,6 +6,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/containers/podman/v3/libpod/define"
|
||||||
|
|
||||||
"github.com/containers/podman/v3/pkg/util"
|
"github.com/containers/podman/v3/pkg/util"
|
||||||
. "github.com/containers/podman/v3/test/utils"
|
. "github.com/containers/podman/v3/test/utils"
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
@ -555,6 +557,15 @@ var _ = Describe("Podman generate kube", func() {
|
|||||||
kube.WaitWithDefaultTimeout()
|
kube.WaitWithDefaultTimeout()
|
||||||
Expect(kube).Should(Exit(0))
|
Expect(kube).Should(Exit(0))
|
||||||
|
|
||||||
|
b, err := ioutil.ReadFile(outputFile)
|
||||||
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
pod := new(v1.Pod)
|
||||||
|
err = yaml.Unmarshal(b, pod)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
val, found := pod.Annotations[define.BindMountPrefix+vol1]
|
||||||
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(val).To(HaveSuffix("z"))
|
||||||
|
|
||||||
rm := podmanTest.Podman([]string{"pod", "rm", "-f", "test1"})
|
rm := podmanTest.Podman([]string{"pod", "rm", "-f", "test1"})
|
||||||
rm.WaitWithDefaultTimeout()
|
rm.WaitWithDefaultTimeout()
|
||||||
Expect(rm).Should(Exit(0))
|
Expect(rm).Should(Exit(0))
|
||||||
|
Reference in New Issue
Block a user