16
16
package generator
17
17
18
18
import (
19
+ "errors"
19
20
"fmt"
20
21
21
22
"github.com/devfile/api/v2/pkg/attributes"
@@ -34,6 +35,7 @@ import (
34
35
networkingv1 "k8s.io/api/networking/v1"
35
36
"k8s.io/apimachinery/pkg/api/resource"
36
37
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
38
+ psaapi "k8s.io/pod-security-admission/api"
37
39
)
38
40
39
41
const (
@@ -74,6 +76,8 @@ func GetObjectMeta(name, namespace string, labels, annotations map[string]string
74
76
}
75
77
76
78
// GetContainers iterates through all container components, filters out init containers and returns corresponding containers
79
+ //
80
+ // Deprecated: in favor of GetPodTemplateSpec
77
81
func GetContainers (devfileObj parser.DevfileObj , options common.DevfileOptions ) ([]corev1.Container , error ) {
78
82
allContainers , err := getAllContainers (devfileObj , options )
79
83
if err != nil {
@@ -120,6 +124,8 @@ func GetContainers(devfileObj parser.DevfileObj, options common.DevfileOptions)
120
124
}
121
125
122
126
// GetInitContainers gets the init container for every preStart devfile event
127
+ //
128
+ // Deprecated: in favor of GetPodTemplateSpec
123
129
func GetInitContainers (devfileObj parser.DevfileObj ) ([]corev1.Container , error ) {
124
130
containers , err := getAllContainers (devfileObj , common.DevfileOptions {})
125
131
if err != nil {
@@ -170,23 +176,93 @@ func GetInitContainers(devfileObj parser.DevfileObj) ([]corev1.Container, error)
170
176
171
177
// DeploymentParams is a struct that contains the required data to create a deployment object
172
178
type DeploymentParams struct {
173
- TypeMeta metav1.TypeMeta
174
- ObjectMeta metav1.ObjectMeta
175
- InitContainers []corev1.Container
176
- Containers []corev1.Container
179
+ TypeMeta metav1.TypeMeta
180
+ ObjectMeta metav1.ObjectMeta
181
+ // Deprecated: InitContainers, Containers and Volumes are deprecated and are replaced by PodTemplateSpec.
182
+ // A PodTemplateSpec value can be obtained calling GetPodTemplateSpec function, instead of calling GetContainers and GetInitContainers
183
+ InitContainers []corev1.Container
184
+ // Deprecated: see InitContainers
185
+ Containers []corev1.Container
186
+ // Deprecated: see InitContainers
177
187
Volumes []corev1.Volume
188
+ PodTemplateSpec * corev1.PodTemplateSpec
178
189
PodSelectorLabels map [string ]string
179
190
Replicas * int32
180
191
}
181
192
182
193
// GetDeployment gets a deployment object
183
194
func GetDeployment (devfileObj parser.DevfileObj , deployParams DeploymentParams ) (* appsv1.Deployment , error ) {
184
195
196
+ deploySpecParams := deploymentSpecParams {
197
+ PodSelectorLabels : deployParams .PodSelectorLabels ,
198
+ Replicas : deployParams .Replicas ,
199
+ }
200
+ if deployParams .PodTemplateSpec == nil {
201
+ // Deprecated
202
+ podTemplateSpecParams := podTemplateSpecParams {
203
+ ObjectMeta : deployParams .ObjectMeta ,
204
+ InitContainers : deployParams .InitContainers ,
205
+ Containers : deployParams .Containers ,
206
+ Volumes : deployParams .Volumes ,
207
+ }
208
+ podTemplateSpec , err := getPodTemplateSpec (podTemplateSpecParams )
209
+ if err != nil {
210
+ return nil , err
211
+ }
212
+ deploySpecParams .PodTemplateSpec = * podTemplateSpec
213
+ } else {
214
+ if len (deployParams .InitContainers ) > 0 ||
215
+ len (deployParams .Containers ) > 0 ||
216
+ len (deployParams .Volumes ) > 0 {
217
+ return nil , errors .New ("InitContainers, Containers and Volumes cannot be set when PodTemplateSpec is set in parameters" )
218
+ }
219
+
220
+ deploySpecParams .PodTemplateSpec = * deployParams .PodTemplateSpec
221
+ }
222
+
223
+ containerAnnotations , err := getContainerAnnotations (devfileObj , common.DevfileOptions {})
224
+ if err != nil {
225
+ return nil , err
226
+ }
227
+ deployParams .ObjectMeta .Annotations = mergeMaps (deployParams .ObjectMeta .Annotations , containerAnnotations .Deployment )
228
+
229
+ deployment := & appsv1.Deployment {
230
+ TypeMeta : deployParams .TypeMeta ,
231
+ ObjectMeta : deployParams .ObjectMeta ,
232
+ Spec : * getDeploymentSpec (deploySpecParams ),
233
+ }
234
+
235
+ return deployment , nil
236
+ }
237
+
238
+ // PodTemplateParams is a struct that contains the required data to create a podtemplatespec object
239
+ type PodTemplateParams struct {
240
+ ObjectMeta metav1.ObjectMeta
241
+ // PodSecurityAdmissionPolicy is the policy to be respected by the created pod
242
+ // The pod will be patched, if necessary, to respect the policies
243
+ PodSecurityAdmissionPolicy psaapi.Policy
244
+ }
245
+
246
+ // GetPodTemplateSpec returns a pod template
247
+ // The function:
248
+ // - iterates through all container components, filters out init containers and gets corresponding containers
249
+ // - gets the init container for every preStart devfile event
250
+ // - patches the pod template and containers to satisfy PodSecurityAdmissionPolicy
251
+ // - patches the pod template and containers to apply pod and container overrides
252
+ func GetPodTemplateSpec (devfileObj parser.DevfileObj , podTemplateParams PodTemplateParams ) (* corev1.PodTemplateSpec , error ) {
253
+ containers , err := GetContainers (devfileObj , common.DevfileOptions {})
254
+ if err != nil {
255
+ return nil , err
256
+ }
257
+ initContainers , err := GetInitContainers (devfileObj )
258
+ if err != nil {
259
+ return nil , err
260
+ }
261
+
185
262
podTemplateSpecParams := podTemplateSpecParams {
186
- ObjectMeta : deployParams .ObjectMeta ,
187
- InitContainers : deployParams .InitContainers ,
188
- Containers : deployParams .Containers ,
189
- Volumes : deployParams .Volumes ,
263
+ ObjectMeta : podTemplateParams .ObjectMeta ,
264
+ InitContainers : initContainers ,
265
+ Containers : containers ,
190
266
}
191
267
var globalAttributes attributes.Attributes
192
268
// attributes is not supported in versions less than 2.1.0, so we skip it
@@ -199,29 +275,74 @@ func GetDeployment(devfileObj parser.DevfileObj, deployParams DeploymentParams)
199
275
if err != nil {
200
276
return nil , err
201
277
}
202
- podTemplateSpec , err := getPodTemplateSpec (globalAttributes , components , podTemplateSpecParams )
278
+
279
+ podTemplateSpec , err := getPodTemplateSpec (podTemplateSpecParams )
203
280
if err != nil {
204
281
return nil , err
205
282
}
206
- deploySpecParams := deploymentSpecParams {
207
- PodTemplateSpec : * podTemplateSpec ,
208
- PodSelectorLabels : deployParams . PodSelectorLabels ,
209
- Replicas : deployParams . Replicas ,
283
+
284
+ podTemplateSpec , err = patchForPolicy ( podTemplateSpec , podTemplateParams . PodSecurityAdmissionPolicy )
285
+ if err != nil {
286
+ return nil , err
210
287
}
211
288
212
- containerAnnotations , err := getContainerAnnotations (devfileObj , common.DevfileOptions {})
289
+ if needsPodOverrides (globalAttributes , components ) {
290
+ patchedPodTemplateSpec , err := applyPodOverrides (globalAttributes , components , podTemplateSpec )
291
+ if err != nil {
292
+ return nil , err
293
+ }
294
+ patchedPodTemplateSpec .ObjectMeta = podTemplateSpecParams .ObjectMeta
295
+ podTemplateSpec = patchedPodTemplateSpec
296
+ }
297
+
298
+ podTemplateSpec .Spec .Containers , err = applyContainerOverrides (devfileObj , podTemplateSpec .Spec .Containers )
299
+ if err != nil {
300
+ return nil , err
301
+ }
302
+ podTemplateSpec .Spec .InitContainers , err = applyContainerOverrides (devfileObj , podTemplateSpec .Spec .InitContainers )
213
303
if err != nil {
214
304
return nil , err
215
305
}
216
- deployParams .ObjectMeta .Annotations = mergeMaps (deployParams .ObjectMeta .Annotations , containerAnnotations .Deployment )
217
306
218
- deployment := & appsv1.Deployment {
219
- TypeMeta : deployParams .TypeMeta ,
220
- ObjectMeta : deployParams .ObjectMeta ,
221
- Spec : * getDeploymentSpec (deploySpecParams ),
307
+ return podTemplateSpec , nil
308
+ }
309
+
310
+ func applyContainerOverrides (devfileObj parser.DevfileObj , containers []corev1.Container ) ([]corev1.Container , error ) {
311
+ containerComponents , err := devfileObj .Data .GetComponents (common.DevfileOptions {
312
+ ComponentOptions : common.ComponentOptions {
313
+ ComponentType : v1 .ContainerComponentType ,
314
+ },
315
+ })
316
+ if err != nil {
317
+ return nil , err
222
318
}
223
319
224
- return deployment , nil
320
+ getContainerByName := func (name string ) (* corev1.Container , bool ) {
321
+ for _ , container := range containers {
322
+ if container .Name == name {
323
+ return & container , true
324
+ }
325
+ }
326
+ return nil , false
327
+ }
328
+
329
+ result := make ([]corev1.Container , 0 , len (containers ))
330
+ for _ , comp := range containerComponents {
331
+ container , found := getContainerByName (comp .Name )
332
+ if ! found {
333
+ continue
334
+ }
335
+ if comp .Attributes .Exists (ContainerOverridesAttribute ) {
336
+ patched , err := containerOverridesHandler (comp , container )
337
+ if err != nil {
338
+ return nil , err
339
+ }
340
+ result = append (result , * patched )
341
+ } else {
342
+ result = append (result , * container )
343
+ }
344
+ }
345
+ return result , nil
225
346
}
226
347
227
348
// PVCParams is a struct to create PVC
0 commit comments