Skip to content

Commit

Permalink
Add interface for SELinuxOptionsToFileLabel
Browse files Browse the repository at this point in the history
github.com/opencontainers/selinux/go-selinux needs OS that supports SELinux
and SELinux enabled in it to return useful data, therefore add an interface
in front of it, so we can mock its behavior in unit tests.
  • Loading branch information
jsafrane committed Aug 4, 2022
1 parent d9f7926 commit 17d850e
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 42 deletions.
18 changes: 13 additions & 5 deletions pkg/kubelet/volumemanager/cache/desired_state_of_world.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,15 @@ type VolumeToMount struct {
}

// NewDesiredStateOfWorld returns a new instance of DesiredStateOfWorld.
func NewDesiredStateOfWorld(volumePluginMgr *volume.VolumePluginMgr) DesiredStateOfWorld {
func NewDesiredStateOfWorld(volumePluginMgr *volume.VolumePluginMgr, seLinuxTranslator util.SELinuxLabelTranslator) DesiredStateOfWorld {
if feature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
registerSELinuxMetrics()
}
return &desiredStateOfWorld{
volumesToMount: make(map[v1.UniqueVolumeName]volumeToMount),
volumePluginMgr: volumePluginMgr,
podErrors: make(map[types.UniquePodName]sets.String),
volumesToMount: make(map[v1.UniqueVolumeName]volumeToMount),
volumePluginMgr: volumePluginMgr,
podErrors: make(map[types.UniquePodName]sets.String),
seLinuxTranslator: seLinuxTranslator,
}
}

Expand All @@ -164,6 +165,8 @@ type desiredStateOfWorld struct {
volumePluginMgr *volume.VolumePluginMgr
// podErrors are errors caught by desiredStateOfWorldPopulator about volumes for a given pod.
podErrors map[types.UniquePodName]sets.String
// seLinuxTranslator translates v1.SELinuxOptions to a file SELinux label.
seLinuxTranslator util.SELinuxLabelTranslator

sync.RWMutex
}
Expand Down Expand Up @@ -373,6 +376,11 @@ func (dsw *desiredStateOfWorld) getSELinuxLabel(volumeSpec *volume.Spec, seLinux

if feature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
var err error

if !dsw.seLinuxTranslator.SELinuxEnabled() {
return "", false, nil
}

pluginSupportsSELinuxContextMount, err = dsw.getSELinuxMountSupport(volumeSpec)
if err != nil {
return "", false, err
Expand All @@ -382,7 +390,7 @@ func (dsw *desiredStateOfWorld) getSELinuxLabel(volumeSpec *volume.Spec, seLinux
// Ensure that a volume that can be mounted with "-o context=XYZ" is
// used only by containers with the same SELinux contexts.
for _, containerContext := range seLinuxContainerContexts {
newLabel, err := util.SELinuxOptionsToFileLabel(containerContext)
newLabel, err := dsw.seLinuxTranslator.SELinuxOptionsToFileLabel(containerContext)
if err != nil {
fullErr := fmt.Errorf("failed to construct SELinux label from context %q: %s", containerContext, err)
if err := handlerSELinuxMetricError(fullErr, isRWOP, seLinuxContainerContextWarnings, seLinuxContainerContextErrors); err != nil {
Expand Down
30 changes: 20 additions & 10 deletions pkg/kubelet/volumemanager/cache/desired_state_of_world_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ import (
func Test_AddPodToVolume_Positive_NewPodNewVolume(t *testing.T) {
// Arrange
volumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
dsw := NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod3",
Expand Down Expand Up @@ -82,7 +83,8 @@ func Test_AddPodToVolume_Positive_NewPodNewVolume(t *testing.T) {
func Test_AddPodToVolume_Positive_ExistingPodExistingVolume(t *testing.T) {
// Arrange
volumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
dsw := NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod3",
Expand Down Expand Up @@ -156,7 +158,8 @@ func Test_AddPodToVolume_Positive_NamesForDifferentPodsAndDifferentVolumes(t *te
}
volumePluginMgr := volume.VolumePluginMgr{}
volumePluginMgr.InitPlugins(plugins, nil /* prober */, fakeVolumeHost)
dsw := NewDesiredStateOfWorld(&volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := NewDesiredStateOfWorld(&volumePluginMgr, seLinuxTranslator)

testcases := map[string]struct {
pod1 *v1.Pod
Expand Down Expand Up @@ -289,7 +292,8 @@ func Test_AddPodToVolume_Positive_NamesForDifferentPodsAndDifferentVolumes(t *te
func Test_DeletePodFromVolume_Positive_PodExistsVolumeExists(t *testing.T) {
// Arrange
volumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
dsw := NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod3",
Expand Down Expand Up @@ -341,7 +345,8 @@ func Test_DeletePodFromVolume_Positive_PodExistsVolumeExists(t *testing.T) {
func Test_MarkVolumesReportedInUse_Positive_NewPodNewVolume(t *testing.T) {
// Arrange
volumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
dsw := NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)

pod1 := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -466,7 +471,8 @@ func Test_MarkVolumesReportedInUse_Positive_NewPodNewVolume(t *testing.T) {

func Test_AddPodToVolume_WithEmptyDirSizeLimit(t *testing.T) {
volumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
dsw := NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
quantity1Gi := resource.MustParse("1Gi")
quantity2Gi := resource.MustParse("2Gi")
quantity3Gi := resource.MustParse("3Gi")
Expand Down Expand Up @@ -621,7 +627,8 @@ func Test_AddPodToVolume_Positive_SELinuxNoRWOP(t *testing.T) {
nil, /* plugins */
)
volumePluginMgr.InitPlugins(plugins, nil /* prober */, fakeVolumeHost)
dsw := NewDesiredStateOfWorld(&volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := NewDesiredStateOfWorld(&volumePluginMgr, seLinuxTranslator)
seLinux := v1.SELinuxOptions{
User: "system_u",
Role: "object_r",
Expand Down Expand Up @@ -701,7 +708,8 @@ func Test_AddPodToVolume_Positive_NoSELinuxPlugin(t *testing.T) {
nil, /* plugins */
)
volumePluginMgr.InitPlugins(plugins, nil /* prober */, fakeVolumeHost)
dsw := NewDesiredStateOfWorld(&volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := NewDesiredStateOfWorld(&volumePluginMgr, seLinuxTranslator)
seLinux := v1.SELinuxOptions{
User: "system_u",
Role: "object_r",
Expand Down Expand Up @@ -782,7 +790,8 @@ func Test_AddPodToVolume_Positive_ExistingPodSameSELinuxRWOP(t *testing.T) {
nil, /* plugins */
)
volumePluginMgr.InitPlugins(plugins, nil /* prober */, fakeVolumeHost)
dsw := NewDesiredStateOfWorld(&volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := NewDesiredStateOfWorld(&volumePluginMgr, seLinuxTranslator)
seLinux := v1.SELinuxOptions{
User: "system_u",
Role: "object_r",
Expand Down Expand Up @@ -882,7 +891,8 @@ func Test_AddPodToVolume_Negative_ExistingPodDifferentSELinuxRWOP(t *testing.T)
nil, /* plugins */
)
volumePluginMgr.InitPlugins(plugins, nil /* prober */, fakeVolumeHost)
dsw := NewDesiredStateOfWorld(&volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := NewDesiredStateOfWorld(&volumePluginMgr, seLinuxTranslator)
seLinux1 := v1.SELinuxOptions{
User: "system_u",
Role: "object_r",
Expand Down
3 changes: 2 additions & 1 deletion pkg/kubelet/volumemanager/metrics/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ import (

func TestMetricCollection(t *testing.T) {
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(k8stypes.NodeName("node-name"), volumePluginMgr)
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1308,7 +1308,8 @@ func createDswpWithVolumeWithCustomPluginMgr(t *testing.T, pv *v1.PersistentVolu
fakePodManager := kubepod.NewBasicPodManager(
podtest.NewFakeMirrorClient(), fakeSecretManager, fakeConfigMapManager)

fakesDSW := cache.NewDesiredStateOfWorld(fakeVolumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
fakesDSW := cache.NewDesiredStateOfWorld(fakeVolumePluginMgr, seLinuxTranslator)
fakeASW := cache.NewActualStateOfWorld("fake", fakeVolumePluginMgr)
fakeRuntime := &containertest.FakeRuntime{}
fakeStateProvider := &fakePodStateProvider{}
Expand Down
48 changes: 32 additions & 16 deletions pkg/kubelet/volumemanager/reconciler/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ func hasAddedPods() bool { return true }
func Test_Run_Positive_DoNothing(t *testing.T) {
// Arrange
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createTestClient()
fakeRecorder := &record.FakeRecorder{}
Expand Down Expand Up @@ -114,7 +115,8 @@ func Test_Run_Positive_DoNothing(t *testing.T) {
func Test_Run_Positive_VolumeAttachAndMount(t *testing.T) {
// Arrange
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createTestClient()
fakeRecorder := &record.FakeRecorder{}
Expand Down Expand Up @@ -204,7 +206,8 @@ func Test_Run_Positive_VolumeAttachAndMountMigrationEnabled(t *testing.T) {
},
}
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgrWithNode(t, node)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)

asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createTestClient(v1.AttachedVolume{
Expand Down Expand Up @@ -309,7 +312,8 @@ func Test_Run_Positive_VolumeMountControllerAttachEnabled(t *testing.T) {
},
}
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgrWithNode(t, node)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createTestClient()
fakeRecorder := &record.FakeRecorder{}
Expand Down Expand Up @@ -388,7 +392,8 @@ func Test_Run_Positive_VolumeMountControllerAttachEnabled(t *testing.T) {
func Test_Run_Negative_VolumeMountControllerAttachEnabled(t *testing.T) {
// Arrange
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createTestClient()
fakeRecorder := &record.FakeRecorder{}
Expand Down Expand Up @@ -466,7 +471,8 @@ func Test_Run_Negative_VolumeMountControllerAttachEnabled(t *testing.T) {
func Test_Run_Positive_VolumeAttachMountUnmountDetach(t *testing.T) {
// Arrange
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createTestClient()
fakeRecorder := &record.FakeRecorder{}
Expand Down Expand Up @@ -568,7 +574,8 @@ func Test_Run_Positive_VolumeUnmountControllerAttachEnabled(t *testing.T) {
},
}
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgrWithNode(t, node)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createTestClient()
fakeRecorder := &record.FakeRecorder{}
Expand Down Expand Up @@ -691,7 +698,8 @@ func Test_Run_Positive_VolumeAttachAndMap(t *testing.T) {

// Arrange
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createtestClientWithPVPVC(gcepv, gcepvc)
fakeRecorder := &record.FakeRecorder{}
Expand Down Expand Up @@ -803,7 +811,8 @@ func Test_Run_Positive_BlockVolumeMapControllerAttachEnabled(t *testing.T) {

// Arrange
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgrWithNode(t, node)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createtestClientWithPVPVC(gcepv, gcepvc, v1.AttachedVolume{
Name: "fake-plugin/fake-device1",
Expand Down Expand Up @@ -903,7 +912,8 @@ func Test_Run_Positive_BlockVolumeAttachMapUnmapDetach(t *testing.T) {

// Arrange
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createtestClientWithPVPVC(gcepv, gcepvc)
fakeRecorder := &record.FakeRecorder{}
Expand Down Expand Up @@ -1024,7 +1034,8 @@ func Test_Run_Positive_VolumeUnmapControllerAttachEnabled(t *testing.T) {

// Arrange
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgrWithNode(t, node)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createtestClientWithPVPVC(gcepv, gcepvc, v1.AttachedVolume{
Name: "fake-plugin/fake-device1",
Expand Down Expand Up @@ -1293,7 +1304,8 @@ func Test_Run_Positive_VolumeFSResizeControllerAttachEnabled(t *testing.T) {
},
}
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgrWithNode(t, node)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createtestClientWithPVPVC(pv, pvc, v1.AttachedVolume{
Name: v1.UniqueVolumeName(fmt.Sprintf("fake-plugin/%s", tc.pvName)),
Expand Down Expand Up @@ -1547,8 +1559,9 @@ func Test_UncertainDeviceGlobalMounts(t *testing.T) {
}
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgrWithNode(t, node)
fakePlugin.SupportsRemount = tc.supportRemount
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()

dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createtestClientWithPVPVC(pv, pvc, v1.AttachedVolume{
Name: v1.UniqueVolumeName(fmt.Sprintf("fake-plugin/%s", tc.volumeName)),
Expand Down Expand Up @@ -1770,7 +1783,8 @@ func Test_UncertainVolumeMountState(t *testing.T) {

volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgrWithNode(t, node)
fakePlugin.SupportsRemount = tc.supportRemount
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createtestClientWithPVPVC(pv, pvc, v1.AttachedVolume{
Name: v1.UniqueVolumeName(fmt.Sprintf("fake-plugin/%s", tc.volumeName)),
Expand Down Expand Up @@ -2087,8 +2101,9 @@ func Test_Run_Positive_VolumeMountControllerAttachEnabledRace(t *testing.T) {
},
}
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgrWithNode(t, node)
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()

dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createTestClient()
fakeRecorder := &record.FakeRecorder{}
Expand Down Expand Up @@ -2234,8 +2249,9 @@ func getReconciler(kubeletDir string, t *testing.T, volumePaths []string) (Recon
node := getFakeNode()
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgrWithNodeAndRoot(t, node, kubeletDir)
tmpKubeletPodDir := filepath.Join(kubeletDir, "pods")
seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()

dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
dsw := cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr)
kubeClient := createTestClient()
fakeRecorder := &record.FakeRecorder{}
Expand Down
3 changes: 2 additions & 1 deletion pkg/kubelet/volumemanager/volume_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,11 @@ func NewVolumeManager(
keepTerminatedPodVolumes bool,
blockVolumePathHandler volumepathhandler.BlockVolumePathHandler) VolumeManager {

seLinuxTranslator := util.NewSELinuxLabelTranslator()
vm := &volumeManager{
kubeClient: kubeClient,
volumePluginMgr: volumePluginMgr,
desiredStateOfWorld: cache.NewDesiredStateOfWorld(volumePluginMgr),
desiredStateOfWorld: cache.NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator),
actualStateOfWorld: cache.NewActualStateOfWorld(nodeName, volumePluginMgr),
operationExecutor: operationexecutor.NewOperationExecutor(operationexecutor.NewOperationGenerator(
kubeClient,
Expand Down

0 comments on commit 17d850e

Please sign in to comment.