Skip to content

Commit dfba334

Browse files
authored
Merge pull request kubernetes#128242 from jsafrane/selinux-controller
1710: Add SELinux warning controller
2 parents 983dd07 + df88b1a commit dfba334

File tree

23 files changed

+2702
-121
lines changed

23 files changed

+2702
-121
lines changed

cmd/kube-controller-manager/app/controllermanager.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ func NewControllerDescriptors() map[string]*ControllerDescriptor {
580580
register(newTaintEvictionControllerDescriptor())
581581
register(newServiceCIDRsControllerDescriptor())
582582
register(newStorageVersionMigratorControllerDescriptor())
583+
register(newSELinuxWarningControllerDescriptor())
583584

584585
for _, alias := range aliases.UnsortedList() {
585586
if _, ok := controllers[alias]; ok {

cmd/kube-controller-manager/app/controllermanager_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ func TestControllerNamesDeclaration(t *testing.T) {
9696
names.ValidatingAdmissionPolicyStatusController,
9797
names.ServiceCIDRController,
9898
names.StorageVersionMigratorController,
99+
names.SELinuxWarningController,
99100
)
100101

101102
for _, name := range KnownControllers() {

cmd/kube-controller-manager/app/core.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ import (
2727
"strings"
2828
"time"
2929

30-
"k8s.io/klog/v2"
31-
3230
v1 "k8s.io/api/core/v1"
3331
genericfeatures "k8s.io/apiserver/pkg/features"
3432
"k8s.io/apiserver/pkg/quota/v1/generic"
@@ -40,6 +38,7 @@ import (
4038
"k8s.io/component-base/featuregate"
4139
"k8s.io/controller-manager/controller"
4240
csitrans "k8s.io/csi-translation-lib"
41+
"k8s.io/klog/v2"
4342
"k8s.io/kubernetes/cmd/kube-controller-manager/names"
4443
pkgcontroller "k8s.io/kubernetes/pkg/controller"
4544
endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint"
@@ -64,6 +63,7 @@ import (
6463
persistentvolumecontroller "k8s.io/kubernetes/pkg/controller/volume/persistentvolume"
6564
"k8s.io/kubernetes/pkg/controller/volume/pvcprotection"
6665
"k8s.io/kubernetes/pkg/controller/volume/pvprotection"
66+
"k8s.io/kubernetes/pkg/controller/volume/selinuxwarning"
6767
"k8s.io/kubernetes/pkg/controller/volume/vacprotection"
6868
"k8s.io/kubernetes/pkg/features"
6969
quotainstall "k8s.io/kubernetes/pkg/quota/v1/install"
@@ -141,7 +141,7 @@ func startNodeIpamController(ctx context.Context, controllerContext ControllerCo
141141
// should be dual stack (from different IPFamilies)
142142
dualstackServiceCIDR, err := netutils.IsDualStackCIDRs([]*net.IPNet{serviceCIDR, secondaryServiceCIDR})
143143
if err != nil {
144-
return nil, false, fmt.Errorf("failed to perform dualstack check on serviceCIDR and secondaryServiceCIDR error:%v", err)
144+
return nil, false, fmt.Errorf("failed to perform dualstack check on serviceCIDR and secondaryServiceCIDR error: %w", err)
145145
}
146146
if !dualstackServiceCIDR {
147147
return nil, false, fmt.Errorf("serviceCIDR and secondaryServiceCIDR are not dualstack (from different IPfamiles)")
@@ -891,3 +891,44 @@ func startStorageVersionGarbageCollectorController(ctx context.Context, controll
891891
).Run(ctx)
892892
return nil, true, nil
893893
}
894+
895+
func newSELinuxWarningControllerDescriptor() *ControllerDescriptor {
896+
return &ControllerDescriptor{
897+
name: names.SELinuxWarningController,
898+
initFunc: startSELinuxWarningController,
899+
isDisabledByDefault: true,
900+
requiredFeatureGates: []featuregate.Feature{
901+
features.SELinuxChangePolicy,
902+
},
903+
}
904+
}
905+
906+
func startSELinuxWarningController(ctx context.Context, controllerContext ControllerContext, controllerName string) (controller.Interface, bool, error) {
907+
if !utilfeature.DefaultFeatureGate.Enabled(features.SELinuxChangePolicy) {
908+
return nil, false, nil
909+
}
910+
911+
logger := klog.FromContext(ctx)
912+
csiDriverInformer := controllerContext.InformerFactory.Storage().V1().CSIDrivers()
913+
plugins, err := ProbePersistentVolumePlugins(logger, controllerContext.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration)
914+
if err != nil {
915+
return nil, true, fmt.Errorf("failed to probe volume plugins when starting SELinux warning controller: %w", err)
916+
}
917+
918+
seLinuxController, err :=
919+
selinuxwarning.NewController(
920+
ctx,
921+
controllerContext.ClientBuilder.ClientOrDie(controllerName),
922+
controllerContext.InformerFactory.Core().V1().Pods(),
923+
controllerContext.InformerFactory.Core().V1().PersistentVolumeClaims(),
924+
controllerContext.InformerFactory.Core().V1().PersistentVolumes(),
925+
csiDriverInformer,
926+
plugins,
927+
GetDynamicPluginProber(controllerContext.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration),
928+
)
929+
if err != nil {
930+
return nil, true, fmt.Errorf("failed to start SELinux warning controller: %w", err)
931+
}
932+
go seLinuxController.Run(ctx, 1)
933+
return nil, true, nil
934+
}

cmd/kube-controller-manager/app/plugins.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ func ProbeProvisionableRecyclableVolumePlugins(logger klog.Logger, config persis
7979
})
8080
}
8181

82+
// ProbePersistentVolumePlugins collects all volume plugins that are actually persistent.
83+
func ProbePersistentVolumePlugins(logger klog.Logger, config persistentvolumeconfig.VolumeConfiguration) ([]volume.VolumePlugin, error) {
84+
return probeControllerVolumePlugins(logger, config, nil)
85+
}
86+
8287
// probeControllerVolumePlugins collects all persistent volume plugins
8388
// used by KCM controllers into an easy to use list.
8489
func probeControllerVolumePlugins(logger klog.Logger, config persistentvolumeconfig.VolumeConfiguration, filter func(plugin volume.VolumePlugin) bool) ([]volume.VolumePlugin, error) {

cmd/kube-controller-manager/names/controller_names.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,5 @@ const (
8585
VolumeAttributesClassProtectionController = "volumeattributesclass-protection-controller"
8686
ServiceCIDRController = "service-cidr-controller"
8787
StorageVersionMigratorController = "storage-version-migrator-controller"
88+
SELinuxWarningController = "selinux-warning-controller"
8889
)

pkg/controller/volume/attachdetach/attach_detach_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ func (adc *attachDetachController) populateDesiredStateOfWorld(logger klog.Logge
437437
// The volume specs present in the ActualStateOfWorld are nil, let's replace those
438438
// with the correct ones found on pods. The present in the ASW with no corresponding
439439
// pod will be detached and the spec is irrelevant.
440-
volumeSpec, err := util.CreateVolumeSpec(logger, podVolume, podToAdd, nodeName, &adc.volumePluginMgr, adc.pvcLister, adc.pvLister, adc.csiMigratedPluginManager, adc.intreeToCSITranslator)
440+
volumeSpec, err := util.CreateVolumeSpecWithNodeMigration(logger, podVolume, podToAdd, nodeName, &adc.volumePluginMgr, adc.pvcLister, adc.pvLister, adc.csiMigratedPluginManager, adc.intreeToCSITranslator)
441441
if err != nil {
442442
logger.Error(
443443
err,

pkg/controller/volume/attachdetach/metrics/metrics.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ func (collector *attachDetachStateCollector) getVolumeInUseCount(logger klog.Log
181181
continue
182182
}
183183
for _, podVolume := range pod.Spec.Volumes {
184-
volumeSpec, err := util.CreateVolumeSpec(logger, podVolume, pod, types.NodeName(pod.Spec.NodeName), collector.volumePluginMgr, collector.pvcLister, collector.pvLister, collector.csiMigratedPluginManager, collector.intreeToCSITranslator)
184+
volumeSpec, err := util.CreateVolumeSpecWithNodeMigration(logger, podVolume, pod, types.NodeName(pod.Spec.NodeName), collector.volumePluginMgr, collector.pvcLister, collector.pvLister, collector.csiMigratedPluginManager, collector.intreeToCSITranslator)
185185
if err != nil {
186186
continue
187187
}

pkg/controller/volume/attachdetach/util/util.go

Lines changed: 83 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,7 @@ import (
3333
"k8s.io/kubernetes/pkg/volume/util"
3434
)
3535

36-
// CreateVolumeSpec creates and returns a mutatable volume.Spec object for the
37-
// specified volume. It dereference any PVC to get PV objects, if needed.
38-
// A volume.Spec that refers to an in-tree plugin spec is translated to refer
39-
// to a migrated CSI plugin spec if all conditions for CSI migration on a node
40-
// for the in-tree plugin is satisfied.
41-
func CreateVolumeSpec(logger klog.Logger, podVolume v1.Volume, pod *v1.Pod, nodeName types.NodeName, vpm *volume.VolumePluginMgr, pvcLister corelisters.PersistentVolumeClaimLister, pvLister corelisters.PersistentVolumeLister, csiMigratedPluginManager csimigration.PluginManager, csiTranslator csimigration.InTreeToCSITranslator) (*volume.Spec, error) {
36+
func createInTreeVolumeSpec(logger klog.Logger, podVolume *v1.Volume, pod *v1.Pod, vpm *volume.VolumePluginMgr, pvcLister corelisters.PersistentVolumeClaimLister, pvLister corelisters.PersistentVolumeLister, csiMigratedPluginManager csimigration.PluginManager, csiTranslator csimigration.InTreeToCSITranslator) (*volume.Spec, string, error) {
4237
claimName := ""
4338
readOnly := false
4439
if pvcSource := podVolume.VolumeSource.PersistentVolumeClaim; pvcSource != nil {
@@ -47,67 +42,83 @@ func CreateVolumeSpec(logger klog.Logger, podVolume v1.Volume, pod *v1.Pod, node
4742
}
4843
isEphemeral := podVolume.VolumeSource.Ephemeral != nil
4944
if isEphemeral {
50-
claimName = ephemeral.VolumeClaimName(pod, &podVolume)
45+
claimName = ephemeral.VolumeClaimName(pod, podVolume)
46+
}
47+
if claimName == "" {
48+
// In-line volume
49+
return volume.NewSpecFromVolume(podVolume), "", nil
5150
}
52-
if claimName != "" {
53-
logger.V(10).Info("Found PVC", "PVC", klog.KRef(pod.Namespace, claimName))
51+
// The volume is a PVC, dereference the PVC + PV
52+
logger.V(10).Info("Found PVC", "PVC", klog.KRef(pod.Namespace, claimName))
5453

55-
// If podVolume is a PVC, fetch the real PV behind the claim
56-
pvc, err := getPVCFromCache(pod.Namespace, claimName, pvcLister)
57-
if err != nil {
58-
return nil, fmt.Errorf(
59-
"error processing PVC %q/%q: %v",
60-
pod.Namespace,
61-
claimName,
62-
err)
63-
}
64-
if isEphemeral {
65-
if err := ephemeral.VolumeIsForPod(pod, pvc); err != nil {
66-
return nil, err
67-
}
54+
// If podVolume is a PVC, fetch the real PV behind the claim
55+
pvc, err := getPVCFromCache(pod.Namespace, claimName, pvcLister)
56+
if err != nil {
57+
return nil, claimName, fmt.Errorf(
58+
"error processing PVC %q/%q: %w",
59+
pod.Namespace,
60+
claimName,
61+
err)
62+
}
63+
if isEphemeral {
64+
if err := ephemeral.VolumeIsForPod(pod, pvc); err != nil {
65+
return nil, claimName, err
6866
}
67+
}
6968

70-
pvName, pvcUID := pvc.Spec.VolumeName, pvc.UID
71-
logger.V(10).Info("Found bound PV for PVC", "PVC", klog.KRef(pod.Namespace, claimName), "pvcUID", pvcUID, "PV", klog.KRef("", pvName))
72-
73-
// Fetch actual PV object
74-
volumeSpec, err := getPVSpecFromCache(
75-
pvName, readOnly, pvcUID, pvLister)
76-
if err != nil {
77-
return nil, fmt.Errorf(
78-
"error processing PVC %q/%q: %v",
79-
pod.Namespace,
80-
claimName,
81-
err)
82-
}
69+
pvName, pvcUID := pvc.Spec.VolumeName, pvc.UID
70+
logger.V(10).Info("Found bound PV for PVC", "PVC", klog.KRef(pod.Namespace, claimName), "pvcUID", pvcUID, "PV", klog.KRef("", pvName))
8371

84-
volumeSpec, err = translateInTreeSpecToCSIIfNeeded(logger, volumeSpec, nodeName, vpm, csiMigratedPluginManager, csiTranslator, pod.Namespace)
85-
if err != nil {
86-
return nil, fmt.Errorf(
87-
"error performing CSI migration checks and translation for PVC %q/%q: %v",
88-
pod.Namespace,
89-
claimName,
90-
err)
91-
}
72+
// Fetch actual PV object
73+
volumeSpec, err := getPVSpecFromCache(
74+
pvName, readOnly, pvcUID, pvLister)
75+
if err != nil {
76+
return nil, claimName, fmt.Errorf(
77+
"error processing PVC %q/%q: %w",
78+
pod.Namespace,
79+
claimName,
80+
err)
81+
}
9282

93-
logger.V(10).Info("Extracted volumeSpec from bound PV and PVC", "PVC", klog.KRef(pod.Namespace, claimName), "pvcUID", pvcUID, "PV", klog.KRef("", pvName), "volumeSpecName", volumeSpec.Name())
83+
logger.V(10).Info("Extracted volumeSpec from bound PV and PVC", "PVC", klog.KRef(pod.Namespace, claimName), "pvcUID", pvcUID, "PV", klog.KRef("", pvName), "volumeSpecName", volumeSpec.Name())
84+
return volumeSpec, claimName, nil
85+
}
9486

95-
return volumeSpec, nil
87+
func CreateVolumeSpec(logger klog.Logger, podVolume v1.Volume, pod *v1.Pod, vpm *volume.VolumePluginMgr, pvcLister corelisters.PersistentVolumeClaimLister, pvLister corelisters.PersistentVolumeLister, csiMigratedPluginManager csimigration.PluginManager, csiTranslator csimigration.InTreeToCSITranslator) (*volume.Spec, error) {
88+
volumeSpec, claimName, err := createInTreeVolumeSpec(logger, &podVolume, pod, vpm, pvcLister, pvLister, csiMigratedPluginManager, csiTranslator)
89+
if err != nil {
90+
return nil, err
9691
}
92+
volumeSpec, err = translateInTreeSpecToCSIIfNeeded(logger, volumeSpec, vpm, csiMigratedPluginManager, csiTranslator, pod.Namespace)
93+
if err != nil {
94+
return nil, fmt.Errorf(
95+
"error performing CSI migration checks and translation for PVC %q/%q: %w",
96+
pod.Namespace,
97+
claimName,
98+
err)
99+
}
100+
return volumeSpec, nil
101+
}
97102

98-
// Do not return the original volume object, since it's from the shared
99-
// informer it may be mutated by another consumer.
100-
clonedPodVolume := podVolume.DeepCopy()
101-
102-
origspec := volume.NewSpecFromVolume(clonedPodVolume)
103-
spec, err := translateInTreeSpecToCSIIfNeeded(logger, origspec, nodeName, vpm, csiMigratedPluginManager, csiTranslator, pod.Namespace)
103+
// CreateVolumeSpec creates and returns a mutatable volume.Spec object for the
104+
// specified volume. It dereference any PVC to get PV objects, if needed.
105+
// A volume.Spec that refers to an in-tree plugin spec is translated to refer
106+
// to a migrated CSI plugin spec if all conditions for CSI migration on a node
107+
// for the in-tree plugin is satisfied.
108+
func CreateVolumeSpecWithNodeMigration(logger klog.Logger, podVolume v1.Volume, pod *v1.Pod, nodeName types.NodeName, vpm *volume.VolumePluginMgr, pvcLister corelisters.PersistentVolumeClaimLister, pvLister corelisters.PersistentVolumeLister, csiMigratedPluginManager csimigration.PluginManager, csiTranslator csimigration.InTreeToCSITranslator) (*volume.Spec, error) {
109+
volumeSpec, claimName, err := createInTreeVolumeSpec(logger, &podVolume, pod, vpm, pvcLister, pvLister, csiMigratedPluginManager, csiTranslator)
110+
if err != nil {
111+
return nil, err
112+
}
113+
volumeSpec, err = translateInTreeSpecToCSIOnNodeIfNeeded(logger, volumeSpec, nodeName, vpm, csiMigratedPluginManager, csiTranslator, pod.Namespace)
104114
if err != nil {
105115
return nil, fmt.Errorf(
106-
"error performing CSI migration checks and translation for inline volume %q: %v",
107-
podVolume.Name,
116+
"error performing CSI migration checks and translation for PVC %q/%q: %w",
117+
pod.Namespace,
118+
claimName,
108119
err)
109120
}
110-
return spec, nil
121+
return volumeSpec, nil
111122
}
112123

113124
// getPVCFromCache fetches the PVC object with the given namespace and
@@ -144,7 +155,6 @@ func getPVSpecFromCache(name string, pvcReadOnly bool, expectedClaimUID types.UI
144155
if err != nil {
145156
return nil, fmt.Errorf("failed to find PV %q in PVInformer cache: %v", name, err)
146157
}
147-
148158
if pv.Spec.ClaimRef == nil {
149159
return nil, fmt.Errorf(
150160
"found PV object %q but it has a nil pv.Spec.ClaimRef indicating it is not yet bound to the claim",
@@ -204,7 +214,7 @@ func ProcessPodVolumes(logger klog.Logger, pod *v1.Pod, addVolumes bool, desired
204214

205215
// Process volume spec for each volume defined in pod
206216
for _, podVolume := range pod.Spec.Volumes {
207-
volumeSpec, err := CreateVolumeSpec(logger, podVolume, pod, nodeName, volumePluginMgr, pvcLister, pvLister, csiMigratedPluginManager, csiTranslator)
217+
volumeSpec, err := CreateVolumeSpecWithNodeMigration(logger, podVolume, pod, nodeName, volumePluginMgr, pvcLister, pvLister, csiMigratedPluginManager, csiTranslator)
208218
if err != nil {
209219
logger.V(10).Info("Error processing volume for pod", "pod", klog.KObj(pod), "volumeName", podVolume.Name, "err", err)
210220
continue
@@ -240,7 +250,7 @@ func ProcessPodVolumes(logger klog.Logger, pod *v1.Pod, addVolumes bool, desired
240250
}
241251
}
242252

243-
func translateInTreeSpecToCSIIfNeeded(logger klog.Logger, spec *volume.Spec, nodeName types.NodeName, vpm *volume.VolumePluginMgr, csiMigratedPluginManager csimigration.PluginManager, csiTranslator csimigration.InTreeToCSITranslator, podNamespace string) (*volume.Spec, error) {
253+
func translateInTreeSpecToCSIOnNodeIfNeeded(logger klog.Logger, spec *volume.Spec, nodeName types.NodeName, vpm *volume.VolumePluginMgr, csiMigratedPluginManager csimigration.PluginManager, csiTranslator csimigration.InTreeToCSITranslator, podNamespace string) (*volume.Spec, error) {
244254
translatedSpec := spec
245255
migratable, err := csiMigratedPluginManager.IsMigratable(spec)
246256
if err != nil {
@@ -263,6 +273,22 @@ func translateInTreeSpecToCSIIfNeeded(logger klog.Logger, spec *volume.Spec, nod
263273
return translatedSpec, nil
264274
}
265275

276+
func translateInTreeSpecToCSIIfNeeded(logger klog.Logger, spec *volume.Spec, vpm *volume.VolumePluginMgr, csiMigratedPluginManager csimigration.PluginManager, csiTranslator csimigration.InTreeToCSITranslator, podNamespace string) (*volume.Spec, error) {
277+
migratable, err := csiMigratedPluginManager.IsMigratable(spec)
278+
if err != nil {
279+
return nil, err
280+
}
281+
if !migratable {
282+
// Jump out of translation fast so we don't check the node if the spec itself is not migratable
283+
return spec, nil
284+
}
285+
translatedSpec, err := csimigration.TranslateInTreeSpecToCSI(logger, spec, podNamespace, csiTranslator)
286+
if err != nil {
287+
return nil, err
288+
}
289+
return translatedSpec, nil
290+
}
291+
266292
func isCSIMigrationSupportedOnNode(nodeName types.NodeName, spec *volume.Spec, vpm *volume.VolumePluginMgr, csiMigratedPluginManager csimigration.PluginManager) (bool, error) {
267293
pluginName, err := csiMigratedPluginManager.GetInTreePluginNameFromSpec(spec.PersistentVolume, spec.Volume)
268294
if err != nil {

pkg/controller/volume/attachdetach/util/util_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ func Test_CreateVolumeSpec(t *testing.T) {
243243
t.Run(test.desc, func(t *testing.T) {
244244
logger, _ := ktesting.NewTestContext(t)
245245
plugMgr, intreeToCSITranslator, csiTranslator, pvLister, pvcLister := setup(testNodeName, t)
246-
actualSpec, err := CreateVolumeSpec(logger, test.pod.Spec.Volumes[0], test.pod, test.createNodeName, plugMgr, pvcLister, pvLister, intreeToCSITranslator, csiTranslator)
246+
actualSpec, err := CreateVolumeSpecWithNodeMigration(logger, test.pod.Spec.Volumes[0], test.pod, test.createNodeName, plugMgr, pvcLister, pvLister, intreeToCSITranslator, csiTranslator)
247247

248248
if actualSpec == nil && (test.wantPersistentVolume != nil || test.wantVolume != nil) {
249249
t.Errorf("got volume spec is nil")
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package cache
18+
19+
import (
20+
"fmt"
21+
22+
"k8s.io/client-go/tools/cache"
23+
)
24+
25+
// A single conflict between two Pods using the same volume with different SELinux labels or policies.
26+
// Event should be sent to both of them.
27+
type Conflict struct {
28+
// Human-readable name of the conflicting property + value of "property" label of selinux_volume_conflict metric.
29+
PropertyName string
30+
// Reason for the event, to be set as the Event.Reason field.
31+
EventReason string
32+
33+
// Pod to generate the event on
34+
Pod cache.ObjectName
35+
PropertyValue string
36+
// only for logging / messaging
37+
OtherPod cache.ObjectName
38+
OtherPropertyValue string
39+
}
40+
41+
// Generate a message about this conflict.
42+
func (c *Conflict) EventMessage() string {
43+
// Quote the values for better readability.
44+
value := "\"" + c.PropertyValue + "\""
45+
otherValue := "\"" + c.OtherPropertyValue + "\""
46+
if c.Pod.Namespace == c.OtherPod.Namespace {
47+
// In the same namespace, be very specific about the pod names.
48+
return fmt.Sprint(c.PropertyName, " ", value, " conflicts with pod ", c.OtherPod.Name, " that uses the same volume as this pod with ", c.PropertyName, " ", otherValue, ". If both pods land on the same node, only one of them may access the volume.")
49+
}
50+
// Pods are in different namespaces, do not reveal the other namespace or pod name.
51+
return fmt.Sprint(c.PropertyName, value, " conflicts with another pod that uses the same volume as this pod with a different ", c.PropertyName, ". If both pods land on the same node, only one of them may access the volume.")
52+
}

0 commit comments

Comments
 (0)