@@ -2,11 +2,14 @@ package templateagent
2
2
3
3
import (
4
4
"fmt"
5
+ "path"
5
6
"strings"
6
7
7
8
corev1 "k8s.io/api/core/v1"
9
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8
10
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
9
11
"k8s.io/apimachinery/pkg/runtime"
12
+ "k8s.io/klog/v2"
10
13
11
14
"open-cluster-management.io/addon-framework/pkg/addonfactory"
12
15
"open-cluster-management.io/addon-framework/pkg/utils"
@@ -84,22 +87,25 @@ func setUnstructuredNestedField(obj interface{}, val string, paths []string) err
84
87
}
85
88
86
89
type deploymentDecorator struct {
90
+ logger klog.Logger
87
91
decorators []podTemplateSpecDecorator
88
92
}
89
93
90
94
func newDeploymentDecorator (
95
+ logger klog.Logger ,
91
96
addonName string ,
92
97
template * addonapiv1alpha1.AddOnTemplate ,
93
98
orderedValues orderedValues ,
94
99
privateValues addonfactory.Values ,
95
100
) decorator {
96
101
return & deploymentDecorator {
102
+ logger : logger ,
97
103
decorators : []podTemplateSpecDecorator {
98
104
newEnvironmentDecorator (orderedValues ),
99
105
newVolumeDecorator (addonName , template ),
100
106
newNodePlacementDecorator (privateValues ),
101
107
newImageDecorator (privateValues ),
102
- newProxyDecorator ( privateValues ),
108
+ newProxyHandler ( logger , addonName , privateValues ),
103
109
},
104
110
}
105
111
}
@@ -127,22 +133,25 @@ func (d *deploymentDecorator) decorate(obj *unstructured.Unstructured) (*unstruc
127
133
}
128
134
129
135
type daemonSetDecorator struct {
136
+ logger klog.Logger
130
137
decorators []podTemplateSpecDecorator
131
138
}
132
139
133
140
func newDaemonSetDecorator (
141
+ logger klog.Logger ,
134
142
addonName string ,
135
143
template * addonapiv1alpha1.AddOnTemplate ,
136
144
orderedValues orderedValues ,
137
145
privateValues addonfactory.Values ,
138
146
) decorator {
139
147
return & daemonSetDecorator {
148
+ logger : logger ,
140
149
decorators : []podTemplateSpecDecorator {
141
150
newEnvironmentDecorator (orderedValues ),
142
151
newVolumeDecorator (addonName , template ),
143
152
newNodePlacementDecorator (privateValues ),
144
153
newImageDecorator (privateValues ),
145
- newProxyDecorator ( privateValues ),
154
+ newProxyHandler ( logger , addonName , privateValues ),
146
155
},
147
156
}
148
157
}
@@ -331,27 +340,40 @@ func (d *imageDecorator) decorate(pod *corev1.PodTemplateSpec) error {
331
340
return nil
332
341
}
333
342
334
- type proxyDecorator struct {
343
+ // objectsInjector injects additional runtime objects to the manifests, these objects will be created
344
+ // in the managed clusters
345
+ type objectsInjector interface {
346
+ // inject returns a list of runtime objects to be created in the managed cluster
347
+ inject () ([]runtime.Object , error )
348
+ }
349
+
350
+ // podTemplateHandler is a combination of podTemplateSpecDecorator and objectsInjector, it can decorate
351
+ // the pod in the deployments/daemonsets and inject additional runtime objects into the manifests
352
+ type podTemplateHandler interface {
353
+ podTemplateSpecDecorator
354
+ objectsInjector
355
+ }
356
+
357
+ type proxyHandler struct {
358
+ logger klog.Logger
359
+ addonName string
335
360
privateValues addonfactory.Values
336
361
}
337
362
338
- func newProxyDecorator (privateValues addonfactory.Values ) podTemplateSpecDecorator {
339
- return & proxyDecorator {
363
+ func newProxyHandler (logger klog.Logger , addonName string , privateValues addonfactory.Values ) podTemplateHandler {
364
+ return & proxyHandler {
365
+ logger : logger ,
366
+ addonName : addonName ,
340
367
privateValues : privateValues ,
341
368
}
342
369
}
343
370
344
- func (d * proxyDecorator ) decorate (pod * corev1.PodTemplateSpec ) error {
345
- proxyConfig , ok := d .privateValues [ ProxyPrivateValueKey ]
371
+ func (d * proxyHandler ) decorate (pod * corev1.PodTemplateSpec ) error {
372
+ pc , ok := d .getProxyConfig ()
346
373
if ! ok {
347
374
return nil
348
375
}
349
376
350
- pc , ok := proxyConfig .(addonapiv1alpha1.ProxyConfig )
351
- if ! ok {
352
- return fmt .Errorf ("proxy config value is invalid" )
353
- }
354
-
355
377
keyValues := []keyValuePair {}
356
378
if len (pc .HTTPProxy ) > 0 {
357
379
keyValues = append (keyValues ,
@@ -376,8 +398,114 @@ func (d *proxyDecorator) decorate(pod *corev1.PodTemplateSpec) error {
376
398
return nil
377
399
}
378
400
379
- return newEnvironmentDecorator (keyValues ).decorate (pod )
380
- // TODO: consider to create a configmap to store the proxyConfig.CABundle and mount it to the Deployment/DaemonSet
401
+ err := newEnvironmentDecorator (keyValues ).decorate (pod )
402
+ if err != nil {
403
+ return err
404
+ }
405
+
406
+ if len (pc .CABundle ) == 0 {
407
+ return nil
408
+ }
409
+
410
+ return newCABundleDecorator (d .addonName , pc .CABundle ).decorate (pod )
411
+ }
412
+
413
+ func (d * proxyHandler ) getProxyConfig () (addonapiv1alpha1.ProxyConfig , bool ) {
414
+ proxyConfig , ok := d .privateValues [ProxyPrivateValueKey ]
415
+ if ! ok {
416
+ return addonapiv1alpha1.ProxyConfig {}, false
417
+ }
418
+
419
+ pc , ok := proxyConfig .(addonapiv1alpha1.ProxyConfig )
420
+ if ! ok {
421
+ d .logger .Error (nil , "proxy config value is invalid" , "value" , proxyConfig )
422
+ return addonapiv1alpha1.ProxyConfig {}, false
423
+ }
424
+
425
+ return pc , true
426
+ }
427
+
428
+ func (d * proxyHandler ) inject () ([]runtime.Object , error ) {
429
+ pc , ok := d .getProxyConfig ()
430
+ if ! ok {
431
+ return nil , nil
432
+ }
433
+
434
+ if len (pc .CABundle ) == 0 {
435
+ return nil , nil
436
+ }
437
+
438
+ return []runtime.Object {
439
+ & corev1.ConfigMap {
440
+ // add TypeMeta to prevent error:
441
+ // "failed to generate required mapper.err got empty kind/version from object"
442
+ TypeMeta : metav1.TypeMeta {
443
+ Kind : "ConfigMap" ,
444
+ APIVersion : "v1" ,
445
+ },
446
+ ObjectMeta : metav1.ObjectMeta {
447
+ Name : proxyCABundleConfigMapName (d .addonName ),
448
+ // use the default namespace, will be decorated by the namespaceDecorator
449
+ Namespace : "open-cluster-management-agent-addon" ,
450
+ },
451
+ Data : map [string ]string {
452
+ proxyCABundleConfigMapDataKey (): string (pc .CABundle ),
453
+ },
454
+ },
455
+ }, nil
456
+ }
457
+
458
+ type caBundleDecorator struct {
459
+ addonName string
460
+ caBundle []byte
461
+ envDecorator podTemplateSpecDecorator
462
+ }
463
+
464
+ func newCABundleDecorator (addonName string , caBundle []byte ) podTemplateSpecDecorator {
465
+ keyValues := []keyValuePair {}
466
+ keyValues = append (keyValues ,
467
+ keyValuePair {name : "CA_BUNDLE_FILE_PATH" , value : proxyCABundleFilePath ()},
468
+ )
469
+
470
+ return & caBundleDecorator {
471
+ addonName : addonName ,
472
+ caBundle : caBundle ,
473
+ envDecorator : newEnvironmentDecorator (keyValues ),
474
+ }
475
+ }
476
+
477
+ func (d * caBundleDecorator ) decorate (pod * corev1.PodTemplateSpec ) error {
478
+ err := d .envDecorator .decorate (pod )
479
+ if err != nil {
480
+ return err
481
+ }
482
+
483
+ volumeMounts := []corev1.VolumeMount {
484
+ {
485
+ Name : "proxy-ca-bundle" ,
486
+ MountPath : proxyCABundleConfigMapMountPath (),
487
+ },
488
+ }
489
+ volumes := []corev1.Volume {
490
+ {
491
+ Name : "proxy-ca-bundle" ,
492
+ VolumeSource : corev1.VolumeSource {
493
+ ConfigMap : & corev1.ConfigMapVolumeSource {
494
+ LocalObjectReference : corev1.LocalObjectReference {
495
+ Name : proxyCABundleConfigMapName (d .addonName ),
496
+ },
497
+ },
498
+ },
499
+ },
500
+ }
501
+
502
+ for j := range pod .Spec .Containers {
503
+ pod .Spec .Containers [j ].VolumeMounts = append (
504
+ pod .Spec .Containers [j ].VolumeMounts , volumeMounts ... )
505
+ }
506
+
507
+ pod .Spec .Volumes = append (pod .Spec .Volumes , volumes ... )
508
+ return nil
381
509
}
382
510
383
511
func hubKubeconfigSecretMountPath () string {
@@ -395,3 +523,19 @@ func CustomSignedSecretName(addonName, signerName string) string {
395
523
func customSignedSecretMountPath (signerName string ) string {
396
524
return fmt .Sprintf ("/managed/%s" , strings .ReplaceAll (signerName , "/" , "-" ))
397
525
}
526
+
527
+ func proxyCABundleConfigMapMountPath () string {
528
+ return "/managed/proxy-ca"
529
+ }
530
+
531
+ func proxyCABundleConfigMapName (addonName string ) string {
532
+ return fmt .Sprintf ("%s-proxy-ca" , addonName )
533
+ }
534
+
535
+ func proxyCABundleConfigMapDataKey () string {
536
+ return "ca-bundle.crt"
537
+ }
538
+
539
+ func proxyCABundleFilePath () string {
540
+ return path .Join (proxyCABundleConfigMapMountPath (), proxyCABundleConfigMapDataKey ())
541
+ }
0 commit comments