@@ -31,6 +31,7 @@ import (
31
31
"k8s.io/kubernetes/pkg/features"
32
32
"k8s.io/kubernetes/pkg/kubelet/images"
33
33
"k8s.io/kubernetes/test/e2e/framework"
34
+ e2enode "k8s.io/kubernetes/test/e2e/framework/node"
34
35
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
35
36
e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
36
37
"k8s.io/kubernetes/test/e2e/nodefeature"
@@ -60,23 +61,14 @@ var _ = SIGDescribe("ImageVolume", nodefeature.ImageVolume, func() {
60
61
e2eskipper .SkipUnlessFeatureGateEnabled (features .ImageVolume )
61
62
})
62
63
63
- createPod := func (ctx context.Context , volumes []v1.Volume , volumeMounts []v1.VolumeMount ) {
64
- var selinuxOptions * v1.SELinuxOptions
65
- if selinux .GetEnabled () {
66
- selinuxOptions = & v1.SELinuxOptions {
67
- User : defaultSELinuxUser ,
68
- Role : defaultSELinuxRole ,
69
- Type : defaultSELinuxType ,
70
- Level : defaultSELinuxLevel ,
71
- }
72
- ginkgo .By (fmt .Sprintf ("Using SELinux on pod: %v" , selinuxOptions ))
73
- }
64
+ createPod := func (ctx context.Context , podName , nodeName string , volumes []v1.Volume , volumeMounts []v1.VolumeMount , selinuxOptions * v1.SELinuxOptions ) {
74
65
pod := & v1.Pod {
75
66
ObjectMeta : metav1.ObjectMeta {
76
67
Name : podName ,
77
68
Namespace : f .Namespace .Name ,
78
69
},
79
70
Spec : v1.PodSpec {
71
+ NodeName : nodeName ,
80
72
RestartPolicy : v1 .RestartPolicyAlways ,
81
73
SecurityContext : & v1.PodSecurityContext {
82
74
SELinuxOptions : selinuxOptions ,
@@ -93,20 +85,34 @@ var _ = SIGDescribe("ImageVolume", nodefeature.ImageVolume, func() {
93
85
},
94
86
}
95
87
96
- ginkgo .By (fmt .Sprintf ("Creating a pod (%v/%v )" , f .Namespace .Name , podName ))
88
+ ginkgo .By (fmt .Sprintf ("Creating a pod (%s/%s )" , f .Namespace .Name , podName ))
97
89
e2epod .NewPodClient (f ).Create (ctx , pod )
98
90
99
91
}
100
92
101
93
f .It ("should succeed with pod and pull policy of Always" , func (ctx context.Context ) {
94
+ var selinuxOptions * v1.SELinuxOptions
95
+ if selinux .GetEnabled () {
96
+ selinuxOptions = & v1.SELinuxOptions {
97
+ User : defaultSELinuxUser ,
98
+ Role : defaultSELinuxRole ,
99
+ Type : defaultSELinuxType ,
100
+ Level : defaultSELinuxLevel ,
101
+ }
102
+ ginkgo .By (fmt .Sprintf ("Using SELinux on pod: %v" , selinuxOptions ))
103
+ }
104
+
102
105
createPod (ctx ,
106
+ podName ,
107
+ "" ,
103
108
[]v1.Volume {{Name : volumeName , VolumeSource : v1.VolumeSource {Image : & v1.ImageVolumeSource {Reference : validImageRef , PullPolicy : v1 .PullAlways }}}},
104
109
[]v1.VolumeMount {{Name : volumeName , MountPath : volumePathPrefix }},
110
+ selinuxOptions ,
105
111
)
106
112
107
- ginkgo .By (fmt .Sprintf ("Waiting for the pod (%v/%v ) to be running" , f .Namespace .Name , podName ))
113
+ ginkgo .By (fmt .Sprintf ("Waiting for the pod (%s/%s ) to be running" , f .Namespace .Name , podName ))
108
114
err := e2epod .WaitForPodNameRunningInNamespace (ctx , f .ClientSet , podName , f .Namespace .Name )
109
- framework .ExpectNoError (err , "Failed to await for the pod to be running: (%v/%v )" , f .Namespace .Name , podName )
115
+ framework .ExpectNoError (err , "Failed to await for the pod to be running: (%s/%s )" , f .Namespace .Name , podName )
110
116
111
117
ginkgo .By (fmt .Sprintf ("Verifying the volume mount contents for path: %s" , volumePathPrefix ))
112
118
@@ -118,7 +124,20 @@ var _ = SIGDescribe("ImageVolume", nodefeature.ImageVolume, func() {
118
124
})
119
125
120
126
f .It ("should succeed with pod and multiple volumes" , func (ctx context.Context ) {
127
+ var selinuxOptions * v1.SELinuxOptions
128
+ if selinux .GetEnabled () {
129
+ selinuxOptions = & v1.SELinuxOptions {
130
+ User : defaultSELinuxUser ,
131
+ Role : defaultSELinuxRole ,
132
+ Type : defaultSELinuxType ,
133
+ Level : defaultSELinuxLevel ,
134
+ }
135
+ ginkgo .By (fmt .Sprintf ("Using SELinux on pod: %v" , selinuxOptions ))
136
+ }
137
+
121
138
createPod (ctx ,
139
+ podName ,
140
+ "" ,
122
141
[]v1.Volume {
123
142
{Name : volumeName + "-0" , VolumeSource : v1.VolumeSource {Image : & v1.ImageVolumeSource {Reference : validImageRef }}},
124
143
{Name : volumeName + "-1" , VolumeSource : v1.VolumeSource {Image : & v1.ImageVolumeSource {Reference : validImageRef }}},
@@ -127,11 +146,12 @@ var _ = SIGDescribe("ImageVolume", nodefeature.ImageVolume, func() {
127
146
{Name : volumeName + "-0" , MountPath : volumePathPrefix + "-0" },
128
147
{Name : volumeName + "-1" , MountPath : volumePathPrefix + "-1" },
129
148
},
149
+ selinuxOptions ,
130
150
)
131
151
132
- ginkgo .By (fmt .Sprintf ("Waiting for the pod (%v/%v ) to be running" , f .Namespace .Name , podName ))
152
+ ginkgo .By (fmt .Sprintf ("Waiting for the pod (%s/%s ) to be running" , f .Namespace .Name , podName ))
133
153
err := e2epod .WaitForPodNameRunningInNamespace (ctx , f .ClientSet , podName , f .Namespace .Name )
134
- framework .ExpectNoError (err , "Failed to await for the pod to be running: (%v/%v )" , f .Namespace .Name , podName )
154
+ framework .ExpectNoError (err , "Failed to await for the pod to be running: (%s/%s )" , f .Namespace .Name , podName )
135
155
136
156
for i := range 2 {
137
157
volumePath := fmt .Sprintf ("%s-%d" , volumePathPrefix , i )
@@ -146,29 +166,123 @@ var _ = SIGDescribe("ImageVolume", nodefeature.ImageVolume, func() {
146
166
})
147
167
148
168
f .It ("should fail if image volume is not existing" , func (ctx context.Context ) {
169
+ var selinuxOptions * v1.SELinuxOptions
170
+ if selinux .GetEnabled () {
171
+ selinuxOptions = & v1.SELinuxOptions {
172
+ User : defaultSELinuxUser ,
173
+ Role : defaultSELinuxRole ,
174
+ Type : defaultSELinuxType ,
175
+ Level : defaultSELinuxLevel ,
176
+ }
177
+ ginkgo .By (fmt .Sprintf ("Using SELinux on pod: %v" , selinuxOptions ))
178
+ }
179
+
149
180
createPod (ctx ,
181
+ podName ,
182
+ "" ,
150
183
[]v1.Volume {{Name : volumeName , VolumeSource : v1.VolumeSource {Image : & v1.ImageVolumeSource {Reference : invalidImageRef }}}},
151
184
[]v1.VolumeMount {{Name : volumeName , MountPath : volumePathPrefix }},
185
+ selinuxOptions ,
152
186
)
153
187
154
- ginkgo .By (fmt .Sprintf ("Waiting for the pod (%v/%v ) to fail" , f .Namespace .Name , podName ))
188
+ ginkgo .By (fmt .Sprintf ("Waiting for the pod (%s/%s ) to fail" , f .Namespace .Name , podName ))
155
189
err := e2epod .WaitForPodContainerToFail (ctx , f .ClientSet , f .Namespace .Name , podName , 0 , images .ErrImagePullBackOff .Error (), time .Minute )
156
- framework .ExpectNoError (err , "Failed to await for the pod to be running: (%v/%v )" , f .Namespace .Name , podName )
190
+ framework .ExpectNoError (err , "Failed to await for the pod to be running: (%s/%s )" , f .Namespace .Name , podName )
157
191
})
158
192
159
193
f .It ("should succeed if image volume is not existing but unused" , func (ctx context.Context ) {
194
+ var selinuxOptions * v1.SELinuxOptions
195
+ if selinux .GetEnabled () {
196
+ selinuxOptions = & v1.SELinuxOptions {
197
+ User : defaultSELinuxUser ,
198
+ Role : defaultSELinuxRole ,
199
+ Type : defaultSELinuxType ,
200
+ Level : defaultSELinuxLevel ,
201
+ }
202
+ ginkgo .By (fmt .Sprintf ("Using SELinux on pod: %v" , selinuxOptions ))
203
+ }
204
+
160
205
createPod (ctx ,
206
+ podName ,
207
+ "" ,
161
208
[]v1.Volume {{Name : volumeName , VolumeSource : v1.VolumeSource {Image : & v1.ImageVolumeSource {Reference : invalidImageRef }}}},
162
209
nil ,
210
+ selinuxOptions ,
163
211
)
164
212
165
- ginkgo .By (fmt .Sprintf ("Waiting for the pod (%v/%v ) to be running" , f .Namespace .Name , podName ))
213
+ ginkgo .By (fmt .Sprintf ("Waiting for the pod (%s/%s ) to be running" , f .Namespace .Name , podName ))
166
214
err := e2epod .WaitForPodNameRunningInNamespace (ctx , f .ClientSet , podName , f .Namespace .Name )
167
- framework .ExpectNoError (err , "Failed to await for the pod to be running: (%v/%v )" , f .Namespace .Name , podName )
215
+ framework .ExpectNoError (err , "Failed to await for the pod to be running: (%s/%s )" , f .Namespace .Name , podName )
168
216
169
217
ginkgo .By (fmt .Sprintf ("Verifying the volume mount is not used for path: %s" , volumePathPrefix ))
170
218
171
219
output := e2epod .ExecCommandInContainer (f , podName , containerName , "/bin/ls" , filepath .Dir (volumePathPrefix ))
172
220
gomega .Expect (output ).NotTo (gomega .ContainSubstring (strings .TrimPrefix (volumePathPrefix , "/" )))
173
221
})
222
+
223
+ f .It ("should succeed with multiple pods and same image on the same node" , func (ctx context.Context ) {
224
+ node , err := e2enode .GetRandomReadySchedulableNode (ctx , f .ClientSet )
225
+ framework .ExpectNoError (err , "Failed to get a ready schedulable node" )
226
+
227
+ baseName := "test-pod"
228
+ anotherSELinuxLevel := "s0:c100,c200"
229
+
230
+ for i := range 2 {
231
+ podName := fmt .Sprintf ("%s-%d" , baseName , i )
232
+
233
+ var selinuxOptions * v1.SELinuxOptions
234
+ if selinux .GetEnabled () {
235
+ if i == 0 {
236
+ selinuxOptions = & v1.SELinuxOptions {
237
+ User : defaultSELinuxUser ,
238
+ Role : defaultSELinuxRole ,
239
+ Type : defaultSELinuxType ,
240
+ Level : defaultSELinuxLevel ,
241
+ }
242
+ } else {
243
+ selinuxOptions = & v1.SELinuxOptions {
244
+ User : defaultSELinuxUser ,
245
+ Role : defaultSELinuxRole ,
246
+ Type : defaultSELinuxType ,
247
+ Level : anotherSELinuxLevel ,
248
+ }
249
+ }
250
+
251
+ ginkgo .By (fmt .Sprintf ("Using SELinux on pod %q: %v" , podName , selinuxOptions ))
252
+ }
253
+
254
+ createPod (ctx ,
255
+ podName ,
256
+ node .Name ,
257
+ []v1.Volume {{Name : volumeName , VolumeSource : v1.VolumeSource {Image : & v1.ImageVolumeSource {Reference : validImageRef }}}},
258
+ []v1.VolumeMount {{Name : volumeName , MountPath : volumePathPrefix }},
259
+ selinuxOptions ,
260
+ )
261
+
262
+ ginkgo .By (fmt .Sprintf ("Waiting for the pod (%s/%s) to be running" , f .Namespace .Name , podName ))
263
+ err := e2epod .WaitForPodNameRunningInNamespace (ctx , f .ClientSet , podName , f .Namespace .Name )
264
+ framework .ExpectNoError (err , "Failed to await for the pod to be running: (%s/%s)" , f .Namespace .Name , podName )
265
+
266
+ ginkgo .By (fmt .Sprintf ("Verifying the volume mount contents for path: %s" , volumePathPrefix ))
267
+
268
+ firstFileContents := e2epod .ExecCommandInContainer (f , podName , containerName , "/bin/cat" , filepath .Join (volumePathPrefix , "dir" , "file" ))
269
+ gomega .Expect (firstFileContents ).To (gomega .Equal ("1" ))
270
+
271
+ secondFileContents := e2epod .ExecCommandInContainer (f , podName , containerName , "/bin/cat" , filepath .Join (volumePathPrefix , "file" ))
272
+ gomega .Expect (secondFileContents ).To (gomega .Equal ("2" ))
273
+ }
274
+
275
+ podName := baseName + "-0"
276
+ ginkgo .By (fmt .Sprintf ("Rechecking the pod (%s/%s) after another pod is running as expected" , f .Namespace .Name , podName ))
277
+ err = e2epod .WaitForPodNameRunningInNamespace (ctx , f .ClientSet , podName , f .Namespace .Name )
278
+ framework .ExpectNoError (err , "Failed to await for the pod to be running: (%s/%s)" , f .Namespace .Name , podName )
279
+
280
+ ginkgo .By (fmt .Sprintf ("Verifying the volume mount contents for path: %s" , volumePathPrefix ))
281
+
282
+ firstFileContents := e2epod .ExecCommandInContainer (f , podName , containerName , "/bin/cat" , filepath .Join (volumePathPrefix , "dir" , "file" ))
283
+ gomega .Expect (firstFileContents ).To (gomega .Equal ("1" ))
284
+
285
+ secondFileContents := e2epod .ExecCommandInContainer (f , podName , containerName , "/bin/cat" , filepath .Join (volumePathPrefix , "file" ))
286
+ gomega .Expect (secondFileContents ).To (gomega .Equal ("2" ))
287
+ })
174
288
})
0 commit comments