11package podtemplatespec
22
33import (
4- "sort "
4+ "github.com/mongodb/mongodb-kubernetes-operator/pkg/util/merge "
55
66 "github.com/imdario/mergo"
77 "github.com/mongodb/mongodb-kubernetes-operator/pkg/kube/container"
8- "github.com/mongodb/mongodb-kubernetes-operator/pkg/util/envvar"
98 corev1 "k8s.io/api/core/v1"
109 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1110)
@@ -229,27 +228,16 @@ func WithVolumeMounts(containerName string, volumeMounts ...corev1.VolumeMount)
229228}
230229
231230func MergePodTemplateSpecs (defaultTemplate , overrideTemplate corev1.PodTemplateSpec ) (corev1.PodTemplateSpec , error ) {
232- // Containers need to be merged manually
233- mergedContainers , err := mergeContainers (defaultTemplate .Spec .Containers , overrideTemplate .Spec .Containers )
234- if err != nil {
235- return corev1.PodTemplateSpec {}, err
236- }
237231
238- mergedTolerations := mergeTolerations (defaultTemplate .Spec .Tolerations , overrideTemplate .Spec .Tolerations )
239-
240- // InitContainers need to be merged manually
241- mergedInitContainers , err := mergeContainers (defaultTemplate .Spec .InitContainers , overrideTemplate .Spec .InitContainers )
242- if err != nil {
243- return corev1.PodTemplateSpec {}, err
244- }
245-
246- // Affinity needs to be merged manually
232+ mergedContainers := merge .Containers (defaultTemplate .Spec .Containers , overrideTemplate .Spec .Containers )
233+ mergedTolerations := merge .Tolerations (defaultTemplate .Spec .Tolerations , overrideTemplate .Spec .Tolerations )
234+ mergedInitContainers := merge .Containers (defaultTemplate .Spec .InitContainers , overrideTemplate .Spec .InitContainers )
247235 mergedAffinity , err := mergeAffinity (defaultTemplate .Spec .Affinity , overrideTemplate .Spec .Affinity )
248236 if err != nil {
249237 return corev1.PodTemplateSpec {}, err
250238 }
251239
252- mergedVolumes := mergeVolumes (defaultTemplate .Spec .Volumes , overrideTemplate .Spec .Volumes )
240+ mergedVolumes := merge . Volumes (defaultTemplate .Spec .Volumes , overrideTemplate .Spec .Volumes )
253241
254242 // Everything else can be merged with mergo
255243 mergedPodTemplateSpec := * defaultTemplate .DeepCopy ()
@@ -265,254 +253,6 @@ func MergePodTemplateSpecs(defaultTemplate, overrideTemplate corev1.PodTemplateS
265253 return mergedPodTemplateSpec , nil
266254}
267255
268- func createKeyToPathMap (items []corev1.KeyToPath ) map [string ]corev1.KeyToPath {
269- itemsMap := make (map [string ]corev1.KeyToPath )
270- for _ , v := range items {
271- itemsMap [v .Key ] = v
272- }
273- return itemsMap
274- }
275-
276- func mergeKeyToPath (defaultKey corev1.KeyToPath , overrideKey corev1.KeyToPath ) corev1.KeyToPath {
277- if defaultKey .Key != overrideKey .Key {
278- // This should not happen as we always merge by Key.
279- // If it does, we return the default as something's wrong
280- return defaultKey
281- }
282- if overrideKey .Path != "" {
283- defaultKey .Path = overrideKey .Path
284- }
285- if overrideKey .Mode != nil {
286- defaultKey .Mode = overrideKey .Mode
287- }
288- return defaultKey
289- }
290-
291- func mergeKeyToPathItems (defaultItems []corev1.KeyToPath , overrideItems []corev1.KeyToPath ) []corev1.KeyToPath {
292- // Merge Items array by KeyToPath.Key entry
293- defaultItemsMap := createKeyToPathMap (defaultItems )
294- overrideItemsMap := createKeyToPathMap (overrideItems )
295- var mergedItems []corev1.KeyToPath
296- for _ , defaultItem := range defaultItemsMap {
297- mergedKey := defaultItem
298- if overrideItem , ok := overrideItemsMap [defaultItem .Key ]; ok {
299- // Need to merge
300- mergedKey = mergeKeyToPath (defaultItem , overrideItem )
301- }
302- mergedItems = append (mergedItems , mergedKey )
303- }
304- for _ , overrideItem := range overrideItemsMap {
305- if _ , ok := defaultItemsMap [overrideItem .Key ]; ok {
306- // Already merged
307- continue
308- }
309- mergedItems = append (mergedItems , overrideItem )
310-
311- }
312- return mergedItems
313- }
314-
315- func mergeVolume (defaultVolume corev1.Volume , overrideVolume corev1.Volume ) corev1.Volume {
316- // Volume contains only Name and VolumeSource
317-
318- // Merge VolumeSource
319- overrideSource := overrideVolume .VolumeSource
320- defaultSource := defaultVolume .VolumeSource
321- mergedVolume := defaultVolume
322-
323- // Only one field must be non-nil.
324- // We merge if it is one of the ones we fill from the operator side:
325- // - EmptyDir
326- if overrideSource .EmptyDir != nil && defaultSource .EmptyDir != nil {
327- if overrideSource .EmptyDir .Medium != "" {
328- mergedVolume .EmptyDir .Medium = overrideSource .EmptyDir .Medium
329- }
330- if overrideSource .EmptyDir .SizeLimit != nil {
331- mergedVolume .EmptyDir .SizeLimit = overrideSource .EmptyDir .SizeLimit
332- }
333- return mergedVolume
334- }
335- // - Secret
336- if overrideSource .Secret != nil && defaultSource .Secret != nil {
337- if overrideSource .Secret .SecretName != "" {
338- mergedVolume .Secret .SecretName = overrideSource .Secret .SecretName
339- }
340- mergedVolume .Secret .Items = mergeKeyToPathItems (defaultSource .Secret .Items , overrideSource .Secret .Items )
341- if overrideSource .Secret .DefaultMode != nil {
342- mergedVolume .Secret .DefaultMode = overrideSource .Secret .DefaultMode
343- }
344- return mergedVolume
345- }
346- // - ConfigMap
347- if overrideSource .ConfigMap != nil && defaultSource .ConfigMap != nil {
348- if overrideSource .ConfigMap .LocalObjectReference .Name != "" {
349- mergedVolume .ConfigMap .LocalObjectReference .Name = overrideSource .ConfigMap .LocalObjectReference .Name
350- }
351- mergedVolume .ConfigMap .Items = mergeKeyToPathItems (defaultSource .ConfigMap .Items , overrideSource .ConfigMap .Items )
352- if overrideSource .ConfigMap .DefaultMode != nil {
353- mergedVolume .ConfigMap .DefaultMode = overrideSource .ConfigMap .DefaultMode
354- }
355- if overrideSource .ConfigMap .Optional != nil {
356- mergedVolume .ConfigMap .Optional = overrideSource .ConfigMap .Optional
357- }
358- return mergedVolume
359- }
360-
361- // Otherwise we assume that the user provides every field
362- // and we just assign it and nil every other field
363- // We also do that in the case the user provides one of the three listed above
364- // but our volume has a different non-nil entry.
365-
366- // this is effectively the same as just returning the overrideSource
367- mergedVolume .VolumeSource = overrideSource
368- return mergedVolume
369- }
370-
371- func createVolumesMap (volumes []corev1.Volume ) map [string ]corev1.Volume {
372- volumesMap := make (map [string ]corev1.Volume )
373- for _ , v := range volumes {
374- volumesMap [v .Name ] = v
375- }
376- return volumesMap
377- }
378-
379- func mergeVolumes (defaultVolumes []corev1.Volume , overrideVolumes []corev1.Volume ) []corev1.Volume {
380- defaultVolumesMap := createVolumesMap (defaultVolumes )
381- overrideVolumesMap := createVolumesMap (overrideVolumes )
382- mergedVolumes := []corev1.Volume {}
383-
384- for _ , defaultVolume := range defaultVolumes {
385- mergedVolume := defaultVolume
386- if overrideVolume , ok := overrideVolumesMap [defaultVolume .Name ]; ok {
387- mergedVolume = mergeVolume (defaultVolume , overrideVolume )
388- }
389- mergedVolumes = append (mergedVolumes , mergedVolume )
390- }
391-
392- for _ , overrideVolume := range overrideVolumes {
393- if _ , ok := defaultVolumesMap [overrideVolume .Name ]; ok {
394- // Already Merged
395- continue
396- }
397- mergedVolumes = append (mergedVolumes , overrideVolume )
398- }
399-
400- sort .SliceStable (mergedVolumes , func (i , j int ) bool {
401- return mergedVolumes [i ].Name < mergedVolumes [j ].Name
402- })
403- return mergedVolumes
404- }
405-
406- func mergeVolumeMounts (defaultMounts , overrideMounts []corev1.VolumeMount ) ([]corev1.VolumeMount , error ) {
407- defaultMountsMap := createMountsMap (defaultMounts )
408- overrideMountsMap := createMountsMap (overrideMounts )
409- mergedVolumeMounts := []corev1.VolumeMount {}
410- for _ , defaultMount := range defaultMounts {
411- if overrideMount , ok := overrideMountsMap [defaultMount .Name ]; ok {
412- // needs merge
413- if err := mergo .Merge (& defaultMount , overrideMount , mergo .WithAppendSlice ); err != nil { //nolint
414- return nil , err
415- }
416- }
417- mergedVolumeMounts = append (mergedVolumeMounts , defaultMount )
418- }
419- for _ , overrideMount := range overrideMounts {
420- if _ , ok := defaultMountsMap [overrideMount .Name ]; ok {
421- // already merged
422- continue
423- }
424- mergedVolumeMounts = append (mergedVolumeMounts , overrideMount )
425- }
426- return mergedVolumeMounts , nil
427- }
428-
429- func createMountsMap (volumeMounts []corev1.VolumeMount ) map [string ]corev1.VolumeMount {
430- mountMap := make (map [string ]corev1.VolumeMount )
431- for _ , m := range volumeMounts {
432- mountMap [m .Name ] = m
433- }
434- return mountMap
435- }
436-
437- func createTolerationsMap (tolerations []corev1.Toleration ) map [string ]corev1.Toleration {
438- tolerationsMap := make (map [string ]corev1.Toleration )
439- for _ , t := range tolerations {
440- tolerationsMap [t .Key ] = t
441- }
442- return tolerationsMap
443- }
444-
445- func mergeTolerations (defaultTolerations , overrideTolerations []corev1.Toleration ) []corev1.Toleration {
446- mergedTolerations := make ([]corev1.Toleration , 0 )
447- defaultMap := createTolerationsMap (defaultTolerations )
448- for _ , v := range overrideTolerations {
449- defaultMap [v .Key ] = v
450- }
451-
452- for _ , v := range defaultMap {
453- mergedTolerations = append (mergedTolerations , v )
454- }
455-
456- if len (mergedTolerations ) == 0 {
457- return nil
458- }
459-
460- sort .SliceStable (mergedTolerations , func (i , j int ) bool {
461- return mergedTolerations [i ].Key < mergedTolerations [j ].Key
462- })
463-
464- return mergedTolerations
465- }
466-
467- func mergeContainers (defaultContainers , customContainers []corev1.Container ) ([]corev1.Container , error ) {
468- defaultMap := createContainerMap (defaultContainers )
469- customMap := createContainerMap (customContainers )
470- mergedContainers := []corev1.Container {}
471- for _ , defaultContainer := range defaultContainers {
472- if customContainer , ok := customMap [defaultContainer .Name ]; ok {
473- // The container is present in both maps, so we need to merge
474- // MergeWithOverride mounts
475- mergedMounts , err := mergeVolumeMounts (defaultContainer .VolumeMounts , customContainer .VolumeMounts )
476- if err != nil {
477- return nil , err
478- }
479-
480- mergedEnvs := envvar .MergeWithOverride (defaultContainer .Env , customContainer .Env )
481-
482- if err := mergo .Merge (& defaultContainer , customContainer , mergo .WithOverride ); err != nil { //nolint
483- return nil , err
484- }
485- // completely override any resources that were provided
486- // this prevents issues with custom requests giving errors due
487- // to the defaulted limits
488- defaultContainer .Resources = customContainer .Resources
489- defaultContainer .VolumeMounts = mergedMounts
490- defaultContainer .Env = mergedEnvs
491- }
492- // The default container was not modified by the override, so just add it
493- mergedContainers = append (mergedContainers , defaultContainer )
494- }
495-
496- // Look for customContainers that were not merged into existing ones
497- for _ , customContainer := range customContainers {
498- if _ , ok := defaultMap [customContainer .Name ]; ok {
499- continue
500- }
501- // Need to add it
502- mergedContainers = append (mergedContainers , customContainer )
503- }
504-
505- return mergedContainers , nil
506- }
507-
508- func createContainerMap (containers []corev1.Container ) map [string ]corev1.Container {
509- containerMap := make (map [string ]corev1.Container )
510- for _ , c := range containers {
511- containerMap [c .Name ] = c
512- }
513- return containerMap
514- }
515-
516256func mergeAffinity (defaultAffinity , overrideAffinity * corev1.Affinity ) (* corev1.Affinity , error ) {
517257 if defaultAffinity == nil {
518258 return overrideAffinity , nil
0 commit comments