mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 05:27:21 +00:00
Merge pull request #70756 from msau42/add-io-exec-test
Add e2e test for file exec
This commit is contained in:
commit
0955c930be
@ -76,6 +76,16 @@ type DynamicPVTestDriver interface {
|
|||||||
GetDynamicProvisionStorageClass(fsType string) *storagev1.StorageClass
|
GetDynamicProvisionStorageClass(fsType string) *storagev1.StorageClass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Capability represents a feature that a volume plugin supports
|
||||||
|
type Capability string
|
||||||
|
|
||||||
|
const (
|
||||||
|
CapPersistence Capability = "persistence" // data is persisted across pod restarts
|
||||||
|
CapBlock Capability = "block" // raw block mode
|
||||||
|
CapFsGroup Capability = "fsGroup" // volume ownership via fsGroup
|
||||||
|
CapExec Capability = "exec" // exec a file in the volume
|
||||||
|
)
|
||||||
|
|
||||||
// DriverInfo represents a combination of parameters to be used in implementation of TestDriver
|
// DriverInfo represents a combination of parameters to be used in implementation of TestDriver
|
||||||
type DriverInfo struct {
|
type DriverInfo struct {
|
||||||
Name string // Name of the driver
|
Name string // Name of the driver
|
||||||
@ -85,9 +95,7 @@ type DriverInfo struct {
|
|||||||
SupportedFsType sets.String // Map of string for supported fs type
|
SupportedFsType sets.String // Map of string for supported fs type
|
||||||
SupportedMountOption sets.String // Map of string for supported mount option
|
SupportedMountOption sets.String // Map of string for supported mount option
|
||||||
RequiredMountOption sets.String // Map of string for required mount option (Optional)
|
RequiredMountOption sets.String // Map of string for required mount option (Optional)
|
||||||
IsPersistent bool // Flag to represent whether it provides persistency
|
Capabilities map[Capability]bool // Map that represents plugin capabilities
|
||||||
IsFsGroupSupported bool // Flag to represent whether it supports fsGroup
|
|
||||||
IsBlockSupported bool // Flag to represent whether it supports Block Volume
|
|
||||||
|
|
||||||
// Parameters below will be set inside test loop by using SetCommonDriverParameters.
|
// Parameters below will be set inside test loop by using SetCommonDriverParameters.
|
||||||
// Drivers that implement TestDriver is required to set all the above parameters
|
// Drivers that implement TestDriver is required to set all the above parameters
|
||||||
|
@ -67,9 +67,9 @@ func InitHostPathCSIDriver() TestDriver {
|
|||||||
SupportedFsType: sets.NewString(
|
SupportedFsType: sets.NewString(
|
||||||
"", // Default fsType
|
"", // Default fsType
|
||||||
),
|
),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: false,
|
CapPersistence: true,
|
||||||
IsBlockSupported: false,
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,9 +153,9 @@ func InitHostV0PathCSIDriver() TestDriver {
|
|||||||
SupportedFsType: sets.NewString(
|
SupportedFsType: sets.NewString(
|
||||||
"", // Default fsType
|
"", // Default fsType
|
||||||
),
|
),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: false,
|
CapPersistence: true,
|
||||||
IsBlockSupported: false,
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,9 +243,11 @@ func InitGcePDCSIDriver() TestDriver {
|
|||||||
"ext4",
|
"ext4",
|
||||||
"xfs",
|
"xfs",
|
||||||
),
|
),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: true,
|
CapPersistence: true,
|
||||||
IsBlockSupported: false,
|
CapFsGroup: true,
|
||||||
|
CapExec: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -334,9 +336,11 @@ func InitGcePDExternalCSIDriver() TestDriver {
|
|||||||
"ext4",
|
"ext4",
|
||||||
"xfs",
|
"xfs",
|
||||||
),
|
),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: true,
|
CapPersistence: true,
|
||||||
IsBlockSupported: false,
|
CapFsGroup: true,
|
||||||
|
CapExec: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,9 +90,10 @@ func InitNFSDriver() TestDriver {
|
|||||||
),
|
),
|
||||||
SupportedMountOption: sets.NewString("proto=tcp", "relatime"),
|
SupportedMountOption: sets.NewString("proto=tcp", "relatime"),
|
||||||
RequiredMountOption: sets.NewString("vers=4.1"),
|
RequiredMountOption: sets.NewString("vers=4.1"),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: false,
|
CapPersistence: true,
|
||||||
IsBlockSupported: false,
|
CapExec: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,9 +236,10 @@ func InitGlusterFSDriver() TestDriver {
|
|||||||
SupportedFsType: sets.NewString(
|
SupportedFsType: sets.NewString(
|
||||||
"", // Default fsType
|
"", // Default fsType
|
||||||
),
|
),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: false,
|
CapPersistence: true,
|
||||||
IsBlockSupported: false,
|
CapExec: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -356,9 +358,12 @@ func InitISCSIDriver() TestDriver {
|
|||||||
//"ext3",
|
//"ext3",
|
||||||
"ext4",
|
"ext4",
|
||||||
),
|
),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: true,
|
CapPersistence: true,
|
||||||
IsBlockSupported: true,
|
CapFsGroup: true,
|
||||||
|
CapBlock: true,
|
||||||
|
CapExec: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -465,9 +470,13 @@ func InitRbdDriver() TestDriver {
|
|||||||
//"ext3",
|
//"ext3",
|
||||||
"ext4",
|
"ext4",
|
||||||
),
|
),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: true,
|
CapPersistence: true,
|
||||||
IsBlockSupported: true},
|
CapFsGroup: true,
|
||||||
|
CapBlock: true,
|
||||||
|
CapExec: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,9 +594,10 @@ func InitCephFSDriver() TestDriver {
|
|||||||
SupportedFsType: sets.NewString(
|
SupportedFsType: sets.NewString(
|
||||||
"", // Default fsType
|
"", // Default fsType
|
||||||
),
|
),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: false,
|
CapPersistence: true,
|
||||||
IsBlockSupported: false,
|
CapExec: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -684,9 +694,9 @@ func InitHostPathDriver() TestDriver {
|
|||||||
SupportedFsType: sets.NewString(
|
SupportedFsType: sets.NewString(
|
||||||
"", // Default fsType
|
"", // Default fsType
|
||||||
),
|
),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: false,
|
CapPersistence: true,
|
||||||
IsBlockSupported: false,
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -756,9 +766,9 @@ func InitHostPathSymlinkDriver() TestDriver {
|
|||||||
SupportedFsType: sets.NewString(
|
SupportedFsType: sets.NewString(
|
||||||
"", // Default fsType
|
"", // Default fsType
|
||||||
),
|
),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: false,
|
CapPersistence: true,
|
||||||
IsBlockSupported: false,
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -896,9 +906,9 @@ func InitEmptydirDriver() TestDriver {
|
|||||||
SupportedFsType: sets.NewString(
|
SupportedFsType: sets.NewString(
|
||||||
"", // Default fsType
|
"", // Default fsType
|
||||||
),
|
),
|
||||||
IsPersistent: false,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: false,
|
CapExec: true,
|
||||||
IsBlockSupported: false,
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -963,9 +973,11 @@ func InitCinderDriver() TestDriver {
|
|||||||
"", // Default fsType
|
"", // Default fsType
|
||||||
"ext3",
|
"ext3",
|
||||||
),
|
),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: true,
|
CapPersistence: true,
|
||||||
IsBlockSupported: false,
|
CapFsGroup: true,
|
||||||
|
CapExec: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1121,9 +1133,12 @@ func InitGcePdDriver() TestDriver {
|
|||||||
"xfs",
|
"xfs",
|
||||||
),
|
),
|
||||||
SupportedMountOption: sets.NewString("debug", "nouid32"),
|
SupportedMountOption: sets.NewString("debug", "nouid32"),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: true,
|
CapPersistence: true,
|
||||||
IsBlockSupported: true,
|
CapFsGroup: true,
|
||||||
|
CapBlock: true,
|
||||||
|
CapExec: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1235,9 +1250,11 @@ func InitVSphereDriver() TestDriver {
|
|||||||
"", // Default fsType
|
"", // Default fsType
|
||||||
"ext4",
|
"ext4",
|
||||||
),
|
),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: true,
|
CapPersistence: true,
|
||||||
IsBlockSupported: false,
|
CapFsGroup: true,
|
||||||
|
CapExec: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1351,9 +1368,12 @@ func InitAzureDriver() TestDriver {
|
|||||||
"", // Default fsType
|
"", // Default fsType
|
||||||
"ext4",
|
"ext4",
|
||||||
),
|
),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: true,
|
CapPersistence: true,
|
||||||
IsBlockSupported: true,
|
CapFsGroup: true,
|
||||||
|
CapBlock: true,
|
||||||
|
CapExec: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1464,9 +1484,12 @@ func InitAwsDriver() TestDriver {
|
|||||||
"ext3",
|
"ext3",
|
||||||
),
|
),
|
||||||
SupportedMountOption: sets.NewString("debug", "nouid32"),
|
SupportedMountOption: sets.NewString("debug", "nouid32"),
|
||||||
IsPersistent: true,
|
Capabilities: map[Capability]bool{
|
||||||
IsFsGroupSupported: true,
|
CapPersistence: true,
|
||||||
IsBlockSupported: true,
|
CapFsGroup: true,
|
||||||
|
CapBlock: true,
|
||||||
|
CapExec: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ func testProvisioning(input *provisioningTestInput) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should create and delete block persistent volumes", func() {
|
It("should create and delete block persistent volumes", func() {
|
||||||
if !input.dInfo.IsBlockSupported {
|
if !input.dInfo.Capabilities[drivers.CapBlock] {
|
||||||
framework.Skipf("Driver %q does not support BlockVolume - skipping", input.dInfo.Name)
|
framework.Skipf("Driver %q does not support BlockVolume - skipping", input.dInfo.Name)
|
||||||
}
|
}
|
||||||
block := v1.PersistentVolumeBlock
|
block := v1.PersistentVolumeBlock
|
||||||
|
@ -90,7 +90,7 @@ func createVolumeIOTestInput(pattern testpatterns.TestPattern, resource genericV
|
|||||||
framework.Skipf("Driver %q does not define volumeSource - skipping", dInfo.Name)
|
framework.Skipf("Driver %q does not define volumeSource - skipping", dInfo.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dInfo.IsFsGroupSupported {
|
if dInfo.Capabilities[drivers.CapFsGroup] {
|
||||||
fsGroupVal := int64(1234)
|
fsGroupVal := int64(1234)
|
||||||
fsGroup = &fsGroupVal
|
fsGroup = &fsGroupVal
|
||||||
}
|
}
|
||||||
|
@ -78,13 +78,13 @@ func createVolumeModeTestInput(pattern testpatterns.TestPattern, resource volume
|
|||||||
testVolType: pattern.VolType,
|
testVolType: pattern.VolType,
|
||||||
nodeName: dInfo.Config.ClientNodeName,
|
nodeName: dInfo.Config.ClientNodeName,
|
||||||
volMode: pattern.VolMode,
|
volMode: pattern.VolMode,
|
||||||
isBlockSupported: dInfo.IsBlockSupported,
|
isBlockSupported: dInfo.Capabilities[drivers.CapBlock],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVolumeModeTestFunc(pattern testpatterns.TestPattern, driver drivers.TestDriver) func(*volumeModeTestInput) {
|
func getVolumeModeTestFunc(pattern testpatterns.TestPattern, driver drivers.TestDriver) func(*volumeModeTestInput) {
|
||||||
dInfo := driver.GetDriverInfo()
|
dInfo := driver.GetDriverInfo()
|
||||||
isBlockSupported := dInfo.IsBlockSupported
|
isBlockSupported := dInfo.Capabilities[drivers.CapBlock]
|
||||||
volMode := pattern.VolMode
|
volMode := pattern.VolMode
|
||||||
volType := pattern.VolType
|
volType := pattern.VolType
|
||||||
|
|
||||||
|
@ -23,11 +23,17 @@ package testsuites
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
"k8s.io/kubernetes/test/e2e/storage/drivers"
|
"k8s.io/kubernetes/test/e2e/storage/drivers"
|
||||||
"k8s.io/kubernetes/test/e2e/storage/testpatterns"
|
"k8s.io/kubernetes/test/e2e/storage/testpatterns"
|
||||||
|
imageutils "k8s.io/kubernetes/test/utils/image"
|
||||||
)
|
)
|
||||||
|
|
||||||
type volumesTestSuite struct {
|
type volumesTestSuite struct {
|
||||||
@ -68,12 +74,22 @@ func (t *volumesTestSuite) getTestSuiteInfo() TestSuiteInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *volumesTestSuite) skipUnsupportedTest(pattern testpatterns.TestPattern, driver drivers.TestDriver) {
|
func (t *volumesTestSuite) skipUnsupportedTest(pattern testpatterns.TestPattern, driver drivers.TestDriver) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func skipPersistenceTest(driver drivers.TestDriver) {
|
||||||
dInfo := driver.GetDriverInfo()
|
dInfo := driver.GetDriverInfo()
|
||||||
if !dInfo.IsPersistent {
|
if !dInfo.Capabilities[drivers.CapPersistence] {
|
||||||
framework.Skipf("Driver %q does not provide persistency - skipping", dInfo.Name)
|
framework.Skipf("Driver %q does not provide persistency - skipping", dInfo.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func skipExecTest(driver drivers.TestDriver) {
|
||||||
|
dInfo := driver.GetDriverInfo()
|
||||||
|
if !dInfo.Capabilities[drivers.CapExec] {
|
||||||
|
framework.Skipf("Driver %q does not support exec - skipping", dInfo.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func createVolumesTestInput(pattern testpatterns.TestPattern, resource genericVolumeTestResource) volumesTestInput {
|
func createVolumesTestInput(pattern testpatterns.TestPattern, resource genericVolumeTestResource) volumesTestInput {
|
||||||
var fsGroup *int64
|
var fsGroup *int64
|
||||||
driver := resource.driver
|
driver := resource.driver
|
||||||
@ -85,7 +101,7 @@ func createVolumesTestInput(pattern testpatterns.TestPattern, resource genericVo
|
|||||||
framework.Skipf("Driver %q does not define volumeSource - skipping", dInfo.Name)
|
framework.Skipf("Driver %q does not define volumeSource - skipping", dInfo.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dInfo.IsFsGroupSupported {
|
if dInfo.Capabilities[drivers.CapFsGroup] {
|
||||||
fsGroupVal := int64(1234)
|
fsGroupVal := int64(1234)
|
||||||
fsGroup = &fsGroupVal
|
fsGroup = &fsGroupVal
|
||||||
}
|
}
|
||||||
@ -95,6 +111,7 @@ func createVolumesTestInput(pattern testpatterns.TestPattern, resource genericVo
|
|||||||
name: dInfo.Name,
|
name: dInfo.Name,
|
||||||
config: dInfo.Config,
|
config: dInfo.Config,
|
||||||
fsGroup: fsGroup,
|
fsGroup: fsGroup,
|
||||||
|
resource: resource,
|
||||||
tests: []framework.VolumeTest{
|
tests: []framework.VolumeTest{
|
||||||
{
|
{
|
||||||
Volume: *volSource,
|
Volume: *volSource,
|
||||||
@ -145,6 +162,7 @@ type volumesTestInput struct {
|
|||||||
config framework.VolumeTestConfig
|
config framework.VolumeTestConfig
|
||||||
fsGroup *int64
|
fsGroup *int64
|
||||||
tests []framework.VolumeTest
|
tests []framework.VolumeTest
|
||||||
|
resource genericVolumeTestResource
|
||||||
}
|
}
|
||||||
|
|
||||||
func testVolumes(input *volumesTestInput) {
|
func testVolumes(input *volumesTestInput) {
|
||||||
@ -153,8 +171,62 @@ func testVolumes(input *volumesTestInput) {
|
|||||||
cs := f.ClientSet
|
cs := f.ClientSet
|
||||||
defer framework.VolumeTestCleanup(f, input.config)
|
defer framework.VolumeTestCleanup(f, input.config)
|
||||||
|
|
||||||
|
skipPersistenceTest(input.resource.driver)
|
||||||
|
|
||||||
volumeTest := input.tests
|
volumeTest := input.tests
|
||||||
framework.InjectHtml(cs, input.config, volumeTest[0].Volume, volumeTest[0].ExpectedContent)
|
framework.InjectHtml(cs, input.config, volumeTest[0].Volume, volumeTest[0].ExpectedContent)
|
||||||
framework.TestVolumeClient(cs, input.config, input.fsGroup, input.tests)
|
framework.TestVolumeClient(cs, input.config, input.fsGroup, input.tests)
|
||||||
})
|
})
|
||||||
|
It("should allow exec of files on the volume", func() {
|
||||||
|
f := input.f
|
||||||
|
skipExecTest(input.resource.driver)
|
||||||
|
|
||||||
|
testScriptInPod(f, input.resource.volType, input.resource.volSource)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testScriptInPod(f *framework.Framework, volumeType string, source *v1.VolumeSource) {
|
||||||
|
const (
|
||||||
|
volPath = "/vol1"
|
||||||
|
volName = "vol1"
|
||||||
|
)
|
||||||
|
suffix := generateSuffixForPodName(volumeType)
|
||||||
|
scriptName := fmt.Sprintf("test-%s.sh", suffix)
|
||||||
|
fullPath := filepath.Join(volPath, scriptName)
|
||||||
|
cmd := fmt.Sprintf("echo \"ls %s\" > %s; chmod u+x %s; %s", volPath, fullPath, fullPath, fullPath)
|
||||||
|
|
||||||
|
pod := &v1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: fmt.Sprintf("exec-volume-test-%s", suffix),
|
||||||
|
Namespace: f.Namespace.Name,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{
|
||||||
|
{
|
||||||
|
Name: fmt.Sprintf("exec-container-%s", suffix),
|
||||||
|
Image: imageutils.GetE2EImage(imageutils.Nginx),
|
||||||
|
Command: []string{"/bin/sh", "-ec", cmd},
|
||||||
|
VolumeMounts: []v1.VolumeMount{
|
||||||
|
{
|
||||||
|
Name: volName,
|
||||||
|
MountPath: volPath,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Volumes: []v1.Volume{
|
||||||
|
{
|
||||||
|
Name: volName,
|
||||||
|
VolumeSource: *source,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RestartPolicy: v1.RestartPolicyNever,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
By(fmt.Sprintf("Creating pod %s", pod.Name))
|
||||||
|
f.TestContainerOutput("exec-volume-test", pod, 0, []string{scriptName})
|
||||||
|
|
||||||
|
By(fmt.Sprintf("Deleting pod %s", pod.Name))
|
||||||
|
err := framework.DeletePodWithWait(f, f.ClientSet, pod)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "while deleting pod")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user