PodSecurity: restrictedVolumes: cleanup

Updated forbidden reason/details
Added unit test to exercise all volume types
Consolidated fixtures
This commit is contained in:
Jordan Liggitt 2021-07-07 22:24:48 -04:00
parent 4a69c57992
commit 676240a342
3 changed files with 199 additions and 296 deletions

View File

@ -27,7 +27,15 @@ import (
/*
In addition to restricting HostPath volumes, the restricted profile
limits usage of non-core volume types to those defined through PersistentVolumes.
limits usage of inline pod volume sources to:
* configMap
* downwardAPI
* emptyDir
* projected
* secret
* csi
* persistentVolumeClaim
* ephemeral
**Restricted Fields:**
@ -41,7 +49,7 @@ spec.volumes[*].glusterfs
spec.volumes[*].rbd
spec.volumes[*].flexVolume
spec.volumes[*].cinder
spec.volumes[*].cephFS
spec.volumes[*].cephfs
spec.volumes[*].flocker
spec.volumes[*].fc
spec.volumes[*].azureFile
@ -49,11 +57,11 @@ spec.volumes[*].vsphereVolume
spec.volumes[*].quobyte
spec.volumes[*].azureDisk
spec.volumes[*].portworxVolume
spec.volumes[*].photonPersistentDisk
spec.volumes[*].scaleIO
spec.volumes[*].storageos
spec.volumes[*].csi
**Allowed Values:** undefined/nil
**Allowed Values:** undefined/null
*/
func init() {
@ -76,7 +84,8 @@ func CheckRestrictedVolumes() Check {
}
func restrictedVolumes_1_0(podMetadata *metav1.ObjectMeta, podSpec *corev1.PodSpec) CheckResult {
restrictedVolumeNames := sets.NewString()
var badVolumes []string
badVolumeTypes := sets.NewString()
for _, volume := range podSpec.Volumes {
switch {
@ -89,16 +98,71 @@ func restrictedVolumes_1_0(podMetadata *metav1.ObjectMeta, podSpec *corev1.PodSp
volume.Projected != nil,
volume.Secret != nil:
continue
default:
restrictedVolumeNames.Insert(volume.Name)
badVolumes = append(badVolumes, volume.Name)
switch {
case volume.HostPath != nil:
badVolumeTypes.Insert("hostPath")
case volume.GCEPersistentDisk != nil:
badVolumeTypes.Insert("gcePersistentDisk")
case volume.AWSElasticBlockStore != nil:
badVolumeTypes.Insert("awsElasticBlockStore")
case volume.GitRepo != nil:
badVolumeTypes.Insert("gitRepo")
case volume.NFS != nil:
badVolumeTypes.Insert("nfs")
case volume.ISCSI != nil:
badVolumeTypes.Insert("iscsi")
case volume.Glusterfs != nil:
badVolumeTypes.Insert("glusterfs")
case volume.RBD != nil:
badVolumeTypes.Insert("rbd")
case volume.FlexVolume != nil:
badVolumeTypes.Insert("flexVolume")
case volume.Cinder != nil:
badVolumeTypes.Insert("cinder")
case volume.CephFS != nil:
badVolumeTypes.Insert("cephfs")
case volume.Flocker != nil:
badVolumeTypes.Insert("flocker")
case volume.FC != nil:
badVolumeTypes.Insert("fc")
case volume.AzureFile != nil:
badVolumeTypes.Insert("azureFile")
case volume.VsphereVolume != nil:
badVolumeTypes.Insert("vsphereVolume")
case volume.Quobyte != nil:
badVolumeTypes.Insert("quobyte")
case volume.AzureDisk != nil:
badVolumeTypes.Insert("azureDisk")
case volume.PhotonPersistentDisk != nil:
badVolumeTypes.Insert("photonPersistentDisk")
case volume.PortworxVolume != nil:
badVolumeTypes.Insert("portworxVolume")
case volume.ScaleIO != nil:
badVolumeTypes.Insert("scaleIO")
case volume.StorageOS != nil:
badVolumeTypes.Insert("storageos")
default:
badVolumeTypes.Insert("unknown")
}
}
}
if len(restrictedVolumeNames) > 0 {
if len(badVolumes) > 0 {
return CheckResult{
Allowed: false,
ForbiddenReason: "restricted volume types",
ForbiddenDetail: fmt.Sprintf("volumes %q have restricted types", restrictedVolumeNames.List()),
ForbiddenDetail: fmt.Sprintf(
"%s %s %s %s %s",
pluralize("volume", "volumes", len(badVolumes)),
joinQuote(badVolumes),
pluralize("uses", "use", len(badVolumes)),
pluralize("restricted volume type", "restricted volume types", len(badVolumeTypes)),
joinQuote(badVolumeTypes.List()),
),
}
}

View File

@ -0,0 +1,96 @@
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package policy
import (
"testing"
corev1 "k8s.io/api/core/v1"
)
func TestRestrictedVolumes(t *testing.T) {
tests := []struct {
name string
pod *corev1.Pod
expectReason string
expectDetail string
}{
{
name: "host path volumes",
pod: &corev1.Pod{Spec: corev1.PodSpec{
Volumes: []corev1.Volume{
// allowed types
{Name: "a1", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}},
{Name: "a2", VolumeSource: corev1.VolumeSource{Secret: &corev1.SecretVolumeSource{}}},
{Name: "a3", VolumeSource: corev1.VolumeSource{PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{}}},
{Name: "a4", VolumeSource: corev1.VolumeSource{DownwardAPI: &corev1.DownwardAPIVolumeSource{}}},
{Name: "a5", VolumeSource: corev1.VolumeSource{ConfigMap: &corev1.ConfigMapVolumeSource{}}},
{Name: "a6", VolumeSource: corev1.VolumeSource{Projected: &corev1.ProjectedVolumeSource{}}},
{Name: "a7", VolumeSource: corev1.VolumeSource{CSI: &corev1.CSIVolumeSource{}}},
{Name: "a8", VolumeSource: corev1.VolumeSource{Ephemeral: &corev1.EphemeralVolumeSource{}}},
// known restricted types
{Name: "b1", VolumeSource: corev1.VolumeSource{HostPath: &corev1.HostPathVolumeSource{}}},
{Name: "b2", VolumeSource: corev1.VolumeSource{GCEPersistentDisk: &corev1.GCEPersistentDiskVolumeSource{}}},
{Name: "b3", VolumeSource: corev1.VolumeSource{AWSElasticBlockStore: &corev1.AWSElasticBlockStoreVolumeSource{}}},
{Name: "b4", VolumeSource: corev1.VolumeSource{GitRepo: &corev1.GitRepoVolumeSource{}}},
{Name: "b5", VolumeSource: corev1.VolumeSource{NFS: &corev1.NFSVolumeSource{}}},
{Name: "b6", VolumeSource: corev1.VolumeSource{ISCSI: &corev1.ISCSIVolumeSource{}}},
{Name: "b7", VolumeSource: corev1.VolumeSource{Glusterfs: &corev1.GlusterfsVolumeSource{}}},
{Name: "b8", VolumeSource: corev1.VolumeSource{RBD: &corev1.RBDVolumeSource{}}},
{Name: "b9", VolumeSource: corev1.VolumeSource{FlexVolume: &corev1.FlexVolumeSource{}}},
{Name: "b10", VolumeSource: corev1.VolumeSource{Cinder: &corev1.CinderVolumeSource{}}},
{Name: "b11", VolumeSource: corev1.VolumeSource{CephFS: &corev1.CephFSVolumeSource{}}},
{Name: "b12", VolumeSource: corev1.VolumeSource{Flocker: &corev1.FlockerVolumeSource{}}},
{Name: "b13", VolumeSource: corev1.VolumeSource{FC: &corev1.FCVolumeSource{}}},
{Name: "b14", VolumeSource: corev1.VolumeSource{AzureFile: &corev1.AzureFileVolumeSource{}}},
{Name: "b15", VolumeSource: corev1.VolumeSource{VsphereVolume: &corev1.VsphereVirtualDiskVolumeSource{}}},
{Name: "b16", VolumeSource: corev1.VolumeSource{Quobyte: &corev1.QuobyteVolumeSource{}}},
{Name: "b17", VolumeSource: corev1.VolumeSource{AzureDisk: &corev1.AzureDiskVolumeSource{}}},
{Name: "b18", VolumeSource: corev1.VolumeSource{PhotonPersistentDisk: &corev1.PhotonPersistentDiskVolumeSource{}}},
{Name: "b19", VolumeSource: corev1.VolumeSource{PortworxVolume: &corev1.PortworxVolumeSource{}}},
{Name: "b20", VolumeSource: corev1.VolumeSource{ScaleIO: &corev1.ScaleIOVolumeSource{}}},
{Name: "b21", VolumeSource: corev1.VolumeSource{StorageOS: &corev1.StorageOSVolumeSource{}}},
// unknown type
{Name: "c1", VolumeSource: corev1.VolumeSource{}},
},
}},
expectReason: `restricted volume types`,
expectDetail: `volumes ` +
`"b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "b10", "b11", "b12", "b13", "b14", "b15", "b16", "b17", "b18", "b19", "b20", "b21", "c1"` +
` use restricted volume types ` +
`"awsElasticBlockStore", "azureDisk", "azureFile", "cephfs", "cinder", "fc", "flexVolume", "flocker", "gcePersistentDisk", "gitRepo", "glusterfs", ` +
`"hostPath", "iscsi", "nfs", "photonPersistentDisk", "portworxVolume", "quobyte", "rbd", "scaleIO", "storageos", "unknown", "vsphereVolume"`,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
result := restrictedVolumes_1_0(&tc.pod.ObjectMeta, &tc.pod.Spec)
if result.Allowed {
t.Fatal("expected disallowed")
}
if e, a := tc.expectReason, result.ForbiddenReason; e != a {
t.Errorf("expected\n%s\ngot\n%s", e, a)
}
if e, a := tc.expectDetail, result.ForbiddenDetail; e != a {
t.Errorf("expected\n%s\ngot\n%s", e, a)
}
})
}
}

View File

@ -30,85 +30,19 @@ func init() {
// pod that has all allowed volume types
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-configmap",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "volume-configmap-test",
},
},
},
},
{
Name: "volume-downwardapi",
VolumeSource: corev1.VolumeSource{
DownwardAPI: &corev1.DownwardAPIVolumeSource{
Items: []corev1.DownwardAPIVolumeFile{
{
Path: "labels",
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.labels",
},
},
},
},
},
},
{
Name: "volume-emptydir",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
},
{
Name: "volume-pvc",
VolumeSource: corev1.VolumeSource{
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
ClaimName: "test",
},
},
},
{
Name: "volume-projects",
VolumeSource: corev1.VolumeSource{
Projected: &corev1.ProjectedVolumeSource{
Sources: []corev1.VolumeProjection{},
},
},
},
{
Name: "volume-secret",
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: "test",
},
},
},
{Name: "volume0", VolumeSource: corev1.VolumeSource{}}, // implicit empty dir
{Name: "volume1", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}},
{Name: "volume2", VolumeSource: corev1.VolumeSource{Secret: &corev1.SecretVolumeSource{SecretName: "test"}}},
{Name: "volume3", VolumeSource: corev1.VolumeSource{PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ClaimName: "test"}}},
{Name: "volume4", VolumeSource: corev1.VolumeSource{DownwardAPI: &corev1.DownwardAPIVolumeSource{Items: []corev1.DownwardAPIVolumeFile{{Path: "labels", FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.labels"}}}}}},
{Name: "volume5", VolumeSource: corev1.VolumeSource{ConfigMap: &corev1.ConfigMapVolumeSource{LocalObjectReference: corev1.LocalObjectReference{Name: "test"}}}},
{Name: "volume6", VolumeSource: corev1.VolumeSource{Projected: &corev1.ProjectedVolumeSource{Sources: []corev1.VolumeProjection{}}}},
// TODO: Uncomment this volume when CSIInlineVolume hits GA.
//
// {
// Name: "volume-csi",
// VolumeSource: corev1.VolumeSource{
// CSI: &corev1.CSIVolumeSource{
// Driver: "inline.storage.kubernetes.io",
// VolumeAttributes: map[string]string{
// "foo": "bar",
// },
// },
// },
// },
//
// {Name: "volume7", VolumeSource: corev1.VolumeSource{CSI: &corev1.CSIVolumeSource{Driver: "inline.storage.kubernetes.io",VolumeAttributes: map[string]string{"foo": "bar"}}}},
// TODO: Uncomment this volume when Ephemeral hits GA.
//
// {
// Name: "volume-ephemeral",
// VolumeSource: corev1.VolumeSource{
// Ephemeral: &corev1.EphemeralVolumeSource{
// VolumeClaimTemplate: nil, // exercise for reader
// },
// },
// },
// {Name: "volume8", VolumeSource: corev1.VolumeSource{Ephemeral: &corev1.EphemeralVolumeSource{VolumeClaimTemplate: nil}}},
}
}),
}
@ -116,255 +50,64 @@ func init() {
generateFail: func(p *corev1.Pod) []*corev1.Pod {
return []*corev1.Pod{
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-gcepersistentdisk",
VolumeSource: corev1.VolumeSource{
GCEPersistentDisk: &corev1.GCEPersistentDiskVolumeSource{
PDName: "testing",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{GCEPersistentDisk: &corev1.GCEPersistentDiskVolumeSource{PDName: "test"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-awselasticblockstore",
VolumeSource: corev1.VolumeSource{
AWSElasticBlockStore: &corev1.AWSElasticBlockStoreVolumeSource{
VolumeID: "testing",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{AWSElasticBlockStore: &corev1.AWSElasticBlockStoreVolumeSource{VolumeID: "test"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-gitrepo",
VolumeSource: corev1.VolumeSource{
GitRepo: &corev1.GitRepoVolumeSource{
Repository: "github.com/kubernetes/kubernetes",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{GitRepo: &corev1.GitRepoVolumeSource{Repository: "github.com/kubernetes/kubernetes"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-nfs",
VolumeSource: corev1.VolumeSource{
NFS: &corev1.NFSVolumeSource{
Server: "testing",
Path: "/testing",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{NFS: &corev1.NFSVolumeSource{Server: "test", Path: "/test"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-iscsi",
VolumeSource: corev1.VolumeSource{
ISCSI: &corev1.ISCSIVolumeSource{
TargetPortal: "testing",
IQN: "iqn.2001-04.com.example:storage.kube.sys1.xyz",
Lun: 0,
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{ISCSI: &corev1.ISCSIVolumeSource{TargetPortal: "test", IQN: "iqn.2001-04.com.example:storage.kube.sys1.xyz", Lun: 0}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-glusterfs",
VolumeSource: corev1.VolumeSource{
Glusterfs: &corev1.GlusterfsVolumeSource{
Path: "testing",
EndpointsName: "testing",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{Glusterfs: &corev1.GlusterfsVolumeSource{Path: "test", EndpointsName: "test"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-rbd",
VolumeSource: corev1.VolumeSource{
RBD: &corev1.RBDVolumeSource{
CephMonitors: []string{"testing"},
RBDImage: "testing",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{RBD: &corev1.RBDVolumeSource{CephMonitors: []string{"test"}, RBDImage: "test"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-flexvolume",
VolumeSource: corev1.VolumeSource{
FlexVolume: &corev1.FlexVolumeSource{
Driver: "testing",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{FlexVolume: &corev1.FlexVolumeSource{Driver: "test"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-cinder",
VolumeSource: corev1.VolumeSource{
Cinder: &corev1.CinderVolumeSource{
VolumeID: "testing",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{Cinder: &corev1.CinderVolumeSource{VolumeID: "test"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-cephfs",
VolumeSource: corev1.VolumeSource{
CephFS: &corev1.CephFSVolumeSource{
Monitors: []string{"testing"},
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{CephFS: &corev1.CephFSVolumeSource{Monitors: []string{"test"}}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-flocker",
VolumeSource: corev1.VolumeSource{
Flocker: &corev1.FlockerVolumeSource{
DatasetName: "testing",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{Flocker: &corev1.FlockerVolumeSource{DatasetName: "test"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-fc",
VolumeSource: corev1.VolumeSource{
FC: &corev1.FCVolumeSource{
WWIDs: []string{"testing"},
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{FC: &corev1.FCVolumeSource{WWIDs: []string{"test"}}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-azurefile",
VolumeSource: corev1.VolumeSource{
AzureFile: &corev1.AzureFileVolumeSource{
SecretName: "testing",
ShareName: "testing",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{AzureFile: &corev1.AzureFileVolumeSource{SecretName: "test", ShareName: "test"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-vsphere",
VolumeSource: corev1.VolumeSource{
VsphereVolume: &corev1.VsphereVirtualDiskVolumeSource{
VolumePath: "testing",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{VsphereVolume: &corev1.VsphereVirtualDiskVolumeSource{VolumePath: "test"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-quobyte",
VolumeSource: corev1.VolumeSource{
Quobyte: &corev1.QuobyteVolumeSource{
Registry: "localhost:1234",
Volume: "testing",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{Quobyte: &corev1.QuobyteVolumeSource{Registry: "localhost:1234", Volume: "test"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-azuredisk",
VolumeSource: corev1.VolumeSource{
AzureDisk: &corev1.AzureDiskVolumeSource{
DiskName: "testing",
DataDiskURI: "https://test.blob.core.windows.net/test/test.vhd",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{AzureDisk: &corev1.AzureDiskVolumeSource{DiskName: "test", DataDiskURI: "https://test.blob.core.windows.net/test/test.vhd"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-portworxvolume",
VolumeSource: corev1.VolumeSource{
PortworxVolume: &corev1.PortworxVolumeSource{
VolumeID: "testing",
FSType: "ext4",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{PortworxVolume: &corev1.PortworxVolumeSource{VolumeID: "test", FSType: "ext4"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-scaleio",
VolumeSource: corev1.VolumeSource{
ScaleIO: &corev1.ScaleIOVolumeSource{
VolumeName: "testing",
Gateway: "localhost",
System: "testing",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{ScaleIO: &corev1.ScaleIOVolumeSource{VolumeName: "test", Gateway: "localhost", System: "test"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-storageos",
VolumeSource: corev1.VolumeSource{
StorageOS: &corev1.StorageOSVolumeSource{
VolumeName: "test",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{StorageOS: &corev1.StorageOSVolumeSource{VolumeName: "test"}}}}
}),
tweak(p, func(p *corev1.Pod) {
p.Spec.Volumes = []corev1.Volume{
{
Name: "volume-hostpath",
VolumeSource: corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/dev/null",
},
},
},
}
p.Spec.Volumes = []corev1.Volume{{Name: "volume1", VolumeSource: corev1.VolumeSource{HostPath: &corev1.HostPathVolumeSource{Path: "/dev/null"}}}}
}),
}
},