mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 10:19:50 +00:00
Add API for mount propagation.
In fact, this is one annotation + its parsing & validation. Appropriate kubelet logic that uses this annotation is in following patches.
This commit is contained in:
parent
2db8af96e2
commit
c49e34fd17
@ -1445,8 +1445,34 @@ type VolumeMount struct {
|
|||||||
// Defaults to "" (volume's root).
|
// Defaults to "" (volume's root).
|
||||||
// +optional
|
// +optional
|
||||||
SubPath string
|
SubPath string
|
||||||
|
// mountPropagation determines how mounts are propagated from the host
|
||||||
|
// to container and the other way around.
|
||||||
|
// When not set, MountPropagationHostToContainer is used.
|
||||||
|
// This field is alpha in 1.8 and can be reworked or removed in a future
|
||||||
|
// release.
|
||||||
|
// +optional
|
||||||
|
MountPropagation *MountPropagationMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MountPropagationMode describes mount propagation.
|
||||||
|
type MountPropagationMode string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MountPropagationHostToContainer means that the volume in a container will
|
||||||
|
// receive new mounts from the host or other containers, but filesystems
|
||||||
|
// mounted inside the container won't be propagated to the host or other
|
||||||
|
// containers.
|
||||||
|
// Note that this mode is recursively applied to all mounts in the volume
|
||||||
|
// ("rslave" in Linux terminology).
|
||||||
|
MountPropagationHostToContainer MountPropagationMode = "HostToContainer"
|
||||||
|
// MountPropagationBidirectional means that the volume in a container will
|
||||||
|
// receive new mounts from the host or other containers, and its own mounts
|
||||||
|
// will be propagated from the container to the host or other containers.
|
||||||
|
// Note that this mode is recursively applied to all mounts in the volume
|
||||||
|
// ("rshared" in Linux terminology).
|
||||||
|
MountPropagationBidirectional MountPropagationMode = "Bidirectional"
|
||||||
|
)
|
||||||
|
|
||||||
// EnvVar represents an environment variable present in a Container.
|
// EnvVar represents an environment variable present in a Container.
|
||||||
type EnvVar struct {
|
type EnvVar struct {
|
||||||
// Required: This must be a C_IDENTIFIER.
|
// Required: This must be a C_IDENTIFIER.
|
||||||
|
@ -5133,6 +5133,7 @@ func autoConvert_v1_VolumeMount_To_api_VolumeMount(in *v1.VolumeMount, out *api.
|
|||||||
out.ReadOnly = in.ReadOnly
|
out.ReadOnly = in.ReadOnly
|
||||||
out.MountPath = in.MountPath
|
out.MountPath = in.MountPath
|
||||||
out.SubPath = in.SubPath
|
out.SubPath = in.SubPath
|
||||||
|
out.MountPropagation = (*api.MountPropagationMode)(unsafe.Pointer(in.MountPropagation))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5146,6 +5147,7 @@ func autoConvert_api_VolumeMount_To_v1_VolumeMount(in *api.VolumeMount, out *v1.
|
|||||||
out.ReadOnly = in.ReadOnly
|
out.ReadOnly = in.ReadOnly
|
||||||
out.MountPath = in.MountPath
|
out.MountPath = in.MountPath
|
||||||
out.SubPath = in.SubPath
|
out.SubPath = in.SubPath
|
||||||
|
out.MountPropagation = (*v1.MountPropagationMode)(unsafe.Pointer(in.MountPropagation))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1027,6 +1027,38 @@ func validatePathNoBacksteps(targetPath string, fldPath *field.Path) field.Error
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validateMountPropagation verifies that MountPropagation field is valid and
|
||||||
|
// allowed for given container.
|
||||||
|
func validateMountPropagation(mountPropagation *api.MountPropagationMode, container *api.Container, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
|
||||||
|
if mountPropagation == nil {
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
if !utilfeature.DefaultFeatureGate.Enabled(features.MountPropagation) {
|
||||||
|
allErrs = append(allErrs, field.Forbidden(fldPath, "mount propagation is disabled by feature-gate"))
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
supportedMountPropagations := sets.NewString(string(api.MountPropagationBidirectional), string(api.MountPropagationHostToContainer))
|
||||||
|
if !supportedMountPropagations.Has(string(*mountPropagation)) {
|
||||||
|
allErrs = append(allErrs, field.NotSupported(fldPath, *mountPropagation, supportedMountPropagations.List()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if container == nil {
|
||||||
|
// The container is not available yet, e.g. during validation of
|
||||||
|
// PodPreset. Stop validation now, Pod validation will refuse final
|
||||||
|
// Pods with Bidirectional propagation in non-privileged containers.
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
privileged := container.SecurityContext != nil && container.SecurityContext.Privileged != nil && *container.SecurityContext.Privileged
|
||||||
|
if *mountPropagation == api.MountPropagationBidirectional && !privileged {
|
||||||
|
allErrs = append(allErrs, field.Forbidden(fldPath, "Bidirectional mount propagation is available only to privileged containers"))
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
// This validate will make sure targetPath:
|
// This validate will make sure targetPath:
|
||||||
// 1. is not abs path
|
// 1. is not abs path
|
||||||
// 2. does not contain any '..' elements
|
// 2. does not contain any '..' elements
|
||||||
@ -1845,7 +1877,7 @@ func validateSecretKeySelector(s *api.SecretKeySelector, fldPath *field.Path) fi
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateVolumeMounts(mounts []api.VolumeMount, volumes sets.String, fldPath *field.Path) field.ErrorList {
|
func ValidateVolumeMounts(mounts []api.VolumeMount, volumes sets.String, container *api.Container, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
mountpoints := sets.NewString()
|
mountpoints := sets.NewString()
|
||||||
|
|
||||||
@ -1869,6 +1901,10 @@ func ValidateVolumeMounts(mounts []api.VolumeMount, volumes sets.String, fldPath
|
|||||||
if len(mnt.SubPath) > 0 {
|
if len(mnt.SubPath) > 0 {
|
||||||
allErrs = append(allErrs, validateLocalDescendingPath(mnt.SubPath, fldPath.Child("subPath"))...)
|
allErrs = append(allErrs, validateLocalDescendingPath(mnt.SubPath, fldPath.Child("subPath"))...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if mnt.MountPropagation != nil {
|
||||||
|
allErrs = append(allErrs, validateMountPropagation(mnt.MountPropagation, container, fldPath.Child("mountPropagation"))...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
@ -2135,7 +2171,7 @@ func validateContainers(containers []api.Container, volumes sets.String, fldPath
|
|||||||
allErrs = append(allErrs, validateContainerPorts(ctr.Ports, idxPath.Child("ports"))...)
|
allErrs = append(allErrs, validateContainerPorts(ctr.Ports, idxPath.Child("ports"))...)
|
||||||
allErrs = append(allErrs, ValidateEnv(ctr.Env, idxPath.Child("env"))...)
|
allErrs = append(allErrs, ValidateEnv(ctr.Env, idxPath.Child("env"))...)
|
||||||
allErrs = append(allErrs, ValidateEnvFrom(ctr.EnvFrom, idxPath.Child("envFrom"))...)
|
allErrs = append(allErrs, ValidateEnvFrom(ctr.EnvFrom, idxPath.Child("envFrom"))...)
|
||||||
allErrs = append(allErrs, ValidateVolumeMounts(ctr.VolumeMounts, volumes, idxPath.Child("volumeMounts"))...)
|
allErrs = append(allErrs, ValidateVolumeMounts(ctr.VolumeMounts, volumes, &ctr, idxPath.Child("volumeMounts"))...)
|
||||||
allErrs = append(allErrs, validatePullPolicy(ctr.ImagePullPolicy, idxPath.Child("imagePullPolicy"))...)
|
allErrs = append(allErrs, validatePullPolicy(ctr.ImagePullPolicy, idxPath.Child("imagePullPolicy"))...)
|
||||||
allErrs = append(allErrs, ValidateResourceRequirements(&ctr.Resources, idxPath.Child("resources"))...)
|
allErrs = append(allErrs, ValidateResourceRequirements(&ctr.Resources, idxPath.Child("resources"))...)
|
||||||
allErrs = append(allErrs, ValidateSecurityContext(ctr.SecurityContext, idxPath.Child("securityContext"))...)
|
allErrs = append(allErrs, ValidateSecurityContext(ctr.SecurityContext, idxPath.Child("securityContext"))...)
|
||||||
|
@ -3405,6 +3405,10 @@ func TestValidateEnvFrom(t *testing.T) {
|
|||||||
|
|
||||||
func TestValidateVolumeMounts(t *testing.T) {
|
func TestValidateVolumeMounts(t *testing.T) {
|
||||||
volumes := sets.NewString("abc", "123", "abc-123")
|
volumes := sets.NewString("abc", "123", "abc-123")
|
||||||
|
container := api.Container{
|
||||||
|
SecurityContext: nil,
|
||||||
|
}
|
||||||
|
propagation := api.MountPropagationBidirectional
|
||||||
|
|
||||||
successCase := []api.VolumeMount{
|
successCase := []api.VolumeMount{
|
||||||
{Name: "abc", MountPath: "/foo"},
|
{Name: "abc", MountPath: "/foo"},
|
||||||
@ -3415,28 +3419,154 @@ func TestValidateVolumeMounts(t *testing.T) {
|
|||||||
{Name: "abc-123", MountPath: "/bac", SubPath: ".baz"},
|
{Name: "abc-123", MountPath: "/bac", SubPath: ".baz"},
|
||||||
{Name: "abc-123", MountPath: "/bad", SubPath: "..baz"},
|
{Name: "abc-123", MountPath: "/bad", SubPath: "..baz"},
|
||||||
}
|
}
|
||||||
if errs := ValidateVolumeMounts(successCase, volumes, field.NewPath("field")); len(errs) != 0 {
|
if errs := ValidateVolumeMounts(successCase, volumes, &container, field.NewPath("field")); len(errs) != 0 {
|
||||||
t.Errorf("expected success: %v", errs)
|
t.Errorf("expected success: %v", errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
errorCases := map[string][]api.VolumeMount{
|
errorCases := map[string][]api.VolumeMount{
|
||||||
"empty name": {{Name: "", MountPath: "/foo"}},
|
"empty name": {{Name: "", MountPath: "/foo"}},
|
||||||
"name not found": {{Name: "", MountPath: "/foo"}},
|
"name not found": {{Name: "", MountPath: "/foo"}},
|
||||||
"empty mountpath": {{Name: "abc", MountPath: ""}},
|
"empty mountpath": {{Name: "abc", MountPath: ""}},
|
||||||
"relative mountpath": {{Name: "abc", MountPath: "bar"}},
|
"relative mountpath": {{Name: "abc", MountPath: "bar"}},
|
||||||
"mountpath collision": {{Name: "foo", MountPath: "/path/a"}, {Name: "bar", MountPath: "/path/a"}},
|
"mountpath collision": {{Name: "foo", MountPath: "/path/a"}, {Name: "bar", MountPath: "/path/a"}},
|
||||||
"absolute subpath": {{Name: "abc", MountPath: "/bar", SubPath: "/baz"}},
|
"absolute subpath": {{Name: "abc", MountPath: "/bar", SubPath: "/baz"}},
|
||||||
"subpath in ..": {{Name: "abc", MountPath: "/bar", SubPath: "../baz"}},
|
"subpath in ..": {{Name: "abc", MountPath: "/bar", SubPath: "../baz"}},
|
||||||
"subpath contains ..": {{Name: "abc", MountPath: "/bar", SubPath: "baz/../bat"}},
|
"subpath contains ..": {{Name: "abc", MountPath: "/bar", SubPath: "baz/../bat"}},
|
||||||
"subpath ends in ..": {{Name: "abc", MountPath: "/bar", SubPath: "./.."}},
|
"subpath ends in ..": {{Name: "abc", MountPath: "/bar", SubPath: "./.."}},
|
||||||
|
"disabled MountPropagation feature gate": {{Name: "abc", MountPath: "/bar", MountPropagation: &propagation}},
|
||||||
}
|
}
|
||||||
for k, v := range errorCases {
|
for k, v := range errorCases {
|
||||||
if errs := ValidateVolumeMounts(v, volumes, field.NewPath("field")); len(errs) == 0 {
|
if errs := ValidateVolumeMounts(v, volumes, &container, field.NewPath("field")); len(errs) == 0 {
|
||||||
t.Errorf("expected failure for %s", k)
|
t.Errorf("expected failure for %s", k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateMountPropagation(t *testing.T) {
|
||||||
|
bTrue := true
|
||||||
|
bFalse := false
|
||||||
|
privilegedContainer := &api.Container{
|
||||||
|
SecurityContext: &api.SecurityContext{
|
||||||
|
Privileged: &bTrue,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
nonPrivilegedContainer := &api.Container{
|
||||||
|
SecurityContext: &api.SecurityContext{
|
||||||
|
Privileged: &bFalse,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
defaultContainer := &api.Container{}
|
||||||
|
|
||||||
|
propagationBidirectional := api.MountPropagationBidirectional
|
||||||
|
propagationHostToContainer := api.MountPropagationHostToContainer
|
||||||
|
propagationInvalid := api.MountPropagationMode("invalid")
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
mount api.VolumeMount
|
||||||
|
container *api.Container
|
||||||
|
expectError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
// implicitly non-privileged container + no propagation
|
||||||
|
api.VolumeMount{Name: "foo", MountPath: "/foo"},
|
||||||
|
defaultContainer,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// implicitly non-privileged container + HostToContainer
|
||||||
|
api.VolumeMount{Name: "foo", MountPath: "/foo", MountPropagation: &propagationHostToContainer},
|
||||||
|
defaultContainer,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// error: implicitly non-privileged container + Bidirectional
|
||||||
|
api.VolumeMount{Name: "foo", MountPath: "/foo", MountPropagation: &propagationBidirectional},
|
||||||
|
defaultContainer,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// explicitly non-privileged container + no propagation
|
||||||
|
api.VolumeMount{Name: "foo", MountPath: "/foo"},
|
||||||
|
nonPrivilegedContainer,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// explicitly non-privileged container + HostToContainer
|
||||||
|
api.VolumeMount{Name: "foo", MountPath: "/foo", MountPropagation: &propagationHostToContainer},
|
||||||
|
nonPrivilegedContainer,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// explicitly non-privileged container + HostToContainer
|
||||||
|
api.VolumeMount{Name: "foo", MountPath: "/foo", MountPropagation: &propagationBidirectional},
|
||||||
|
nonPrivilegedContainer,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// privileged container + no propagation
|
||||||
|
api.VolumeMount{Name: "foo", MountPath: "/foo"},
|
||||||
|
privilegedContainer,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// privileged container + HostToContainer
|
||||||
|
api.VolumeMount{Name: "foo", MountPath: "/foo", MountPropagation: &propagationHostToContainer},
|
||||||
|
privilegedContainer,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// privileged container + Bidirectional
|
||||||
|
api.VolumeMount{Name: "foo", MountPath: "/foo", MountPropagation: &propagationBidirectional},
|
||||||
|
privilegedContainer,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// error: privileged container + invalid mount propagation
|
||||||
|
api.VolumeMount{Name: "foo", MountPath: "/foo", MountPropagation: &propagationInvalid},
|
||||||
|
privilegedContainer,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// no container + Bidirectional
|
||||||
|
api.VolumeMount{Name: "foo", MountPath: "/foo", MountPropagation: &propagationBidirectional},
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable MountPropagation for this test
|
||||||
|
priorityEnabled := utilfeature.DefaultFeatureGate.Enabled("MountPropagation")
|
||||||
|
defer func() {
|
||||||
|
var err error
|
||||||
|
// restoring the old value
|
||||||
|
if priorityEnabled {
|
||||||
|
err = utilfeature.DefaultFeatureGate.Set("MountPropagation=true")
|
||||||
|
} else {
|
||||||
|
err = utilfeature.DefaultFeatureGate.Set("MountPropagation=false")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to restore feature gate for MountPropagation: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
err := utilfeature.DefaultFeatureGate.Set("MountPropagation=true")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to enable feature gate for MountPropagation: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range tests {
|
||||||
|
volumes := sets.NewString("foo")
|
||||||
|
errs := ValidateVolumeMounts([]api.VolumeMount{test.mount}, volumes, test.container, field.NewPath("field"))
|
||||||
|
if test.expectError && len(errs) == 0 {
|
||||||
|
t.Errorf("test %d expected error, got none", i)
|
||||||
|
}
|
||||||
|
if !test.expectError && len(errs) != 0 {
|
||||||
|
t.Errorf("test %d expected success, got error: %v", i, errs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestValidateProbe(t *testing.T) {
|
func TestValidateProbe(t *testing.T) {
|
||||||
handler := api.Handler{Exec: &api.ExecAction{Command: []string{"echo"}}}
|
handler := api.Handler{Exec: &api.ExecAction{Command: []string{"echo"}}}
|
||||||
// These fields must be positive.
|
// These fields must be positive.
|
||||||
|
@ -1409,7 +1409,9 @@ func (in *Container) DeepCopyInto(out *Container) {
|
|||||||
if in.VolumeMounts != nil {
|
if in.VolumeMounts != nil {
|
||||||
in, out := &in.VolumeMounts, &out.VolumeMounts
|
in, out := &in.VolumeMounts, &out.VolumeMounts
|
||||||
*out = make([]VolumeMount, len(*in))
|
*out = make([]VolumeMount, len(*in))
|
||||||
copy(*out, *in)
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if in.LivenessProbe != nil {
|
if in.LivenessProbe != nil {
|
||||||
in, out := &in.LivenessProbe, &out.LivenessProbe
|
in, out := &in.LivenessProbe, &out.LivenessProbe
|
||||||
@ -5931,6 +5933,15 @@ func (in *Volume) DeepCopy() *Volume {
|
|||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *VolumeMount) DeepCopyInto(out *VolumeMount) {
|
func (in *VolumeMount) DeepCopyInto(out *VolumeMount) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
if in.MountPropagation != nil {
|
||||||
|
in, out := &in.MountPropagation, &out.MountPropagation
|
||||||
|
if *in == nil {
|
||||||
|
*out = nil
|
||||||
|
} else {
|
||||||
|
*out = new(MountPropagationMode)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ func ValidatePodPresetSpec(spec *settings.PodPresetSpec, fldPath *field.Path) fi
|
|||||||
allErrs = append(allErrs, vErrs...)
|
allErrs = append(allErrs, vErrs...)
|
||||||
allErrs = append(allErrs, apivalidation.ValidateEnv(spec.Env, fldPath.Child("env"))...)
|
allErrs = append(allErrs, apivalidation.ValidateEnv(spec.Env, fldPath.Child("env"))...)
|
||||||
allErrs = append(allErrs, apivalidation.ValidateEnvFrom(spec.EnvFrom, fldPath.Child("envFrom"))...)
|
allErrs = append(allErrs, apivalidation.ValidateEnvFrom(spec.EnvFrom, fldPath.Child("envFrom"))...)
|
||||||
allErrs = append(allErrs, apivalidation.ValidateVolumeMounts(spec.VolumeMounts, volumes, fldPath.Child("volumeMounts"))...)
|
allErrs = append(allErrs, apivalidation.ValidateVolumeMounts(spec.VolumeMounts, volumes, nil, fldPath.Child("volumeMounts"))...)
|
||||||
|
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,9 @@ func (in *PodPresetSpec) DeepCopyInto(out *PodPresetSpec) {
|
|||||||
if in.VolumeMounts != nil {
|
if in.VolumeMounts != nil {
|
||||||
in, out := &in.VolumeMounts, &out.VolumeMounts
|
in, out := &in.VolumeMounts, &out.VolumeMounts
|
||||||
*out = make([]api.VolumeMount, len(*in))
|
*out = make([]api.VolumeMount, len(*in))
|
||||||
copy(*out, *in)
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1547,8 +1547,34 @@ type VolumeMount struct {
|
|||||||
// Defaults to "" (volume's root).
|
// Defaults to "" (volume's root).
|
||||||
// +optional
|
// +optional
|
||||||
SubPath string `json:"subPath,omitempty" protobuf:"bytes,4,opt,name=subPath"`
|
SubPath string `json:"subPath,omitempty" protobuf:"bytes,4,opt,name=subPath"`
|
||||||
|
// mountPropagation determines how mounts are propagated from the host
|
||||||
|
// to container and the other way around.
|
||||||
|
// When not set, MountPropagationHostToContainer is used.
|
||||||
|
// This field is alpha in 1.8 and can be reworked or removed in a future
|
||||||
|
// release.
|
||||||
|
// +optional
|
||||||
|
MountPropagation *MountPropagationMode `json:"mountPropagation,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MountPropagationMode describes mount propagation.
|
||||||
|
type MountPropagationMode string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MountPropagationHostToContainer means that the volume in a container will
|
||||||
|
// receive new mounts from the host or other containers, but filesystems
|
||||||
|
// mounted inside the container won't be propagated to the host or other
|
||||||
|
// containers.
|
||||||
|
// Note that this mode is recursively applied to all mounts in the volume
|
||||||
|
// ("rslave" in Linux terminology).
|
||||||
|
MountPropagationHostToContainer MountPropagationMode = "HostToContainer"
|
||||||
|
// MountPropagationBidirectional means that the volume in a container will
|
||||||
|
// receive new mounts from the host or other containers, and its own mounts
|
||||||
|
// will be propagated from the container to the host or other containers.
|
||||||
|
// Note that this mode is recursively applied to all mounts in the volume
|
||||||
|
// ("rshared" in Linux terminology).
|
||||||
|
MountPropagationBidirectional MountPropagationMode = "Bidirectional"
|
||||||
|
)
|
||||||
|
|
||||||
// EnvVar represents an environment variable present in a Container.
|
// EnvVar represents an environment variable present in a Container.
|
||||||
type EnvVar struct {
|
type EnvVar struct {
|
||||||
// Name of the environment variable. Must be a C_IDENTIFIER.
|
// Name of the environment variable. Must be a C_IDENTIFIER.
|
||||||
|
@ -1409,7 +1409,9 @@ func (in *Container) DeepCopyInto(out *Container) {
|
|||||||
if in.VolumeMounts != nil {
|
if in.VolumeMounts != nil {
|
||||||
in, out := &in.VolumeMounts, &out.VolumeMounts
|
in, out := &in.VolumeMounts, &out.VolumeMounts
|
||||||
*out = make([]VolumeMount, len(*in))
|
*out = make([]VolumeMount, len(*in))
|
||||||
copy(*out, *in)
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if in.LivenessProbe != nil {
|
if in.LivenessProbe != nil {
|
||||||
in, out := &in.LivenessProbe, &out.LivenessProbe
|
in, out := &in.LivenessProbe, &out.LivenessProbe
|
||||||
@ -5933,6 +5935,15 @@ func (in *Volume) DeepCopy() *Volume {
|
|||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *VolumeMount) DeepCopyInto(out *VolumeMount) {
|
func (in *VolumeMount) DeepCopyInto(out *VolumeMount) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
if in.MountPropagation != nil {
|
||||||
|
in, out := &in.MountPropagation, &out.MountPropagation
|
||||||
|
if *in == nil {
|
||||||
|
*out = nil
|
||||||
|
} else {
|
||||||
|
*out = new(MountPropagationMode)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,9 @@ func (in *PodPresetSpec) DeepCopyInto(out *PodPresetSpec) {
|
|||||||
if in.VolumeMounts != nil {
|
if in.VolumeMounts != nil {
|
||||||
in, out := &in.VolumeMounts, &out.VolumeMounts
|
in, out := &in.VolumeMounts, &out.VolumeMounts
|
||||||
*out = make([]v1.VolumeMount, len(*in))
|
*out = make([]v1.VolumeMount, len(*in))
|
||||||
copy(*out, *in)
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user