@@ -36,6 +36,10 @@ const (
36
36
PackageserverName = "v1.packages.operators.coreos.com"
37
37
)
38
38
39
+ func secretName (apiServiceName string ) string {
40
+ return apiServiceName + "-cert"
41
+ }
42
+
39
43
func (a * Operator ) shouldRotateCerts (csv * v1alpha1.ClusterServiceVersion ) bool {
40
44
now := metav1 .Now ()
41
45
if ! csv .Status .CertsRotateAt .IsZero () && csv .Status .CertsRotateAt .Before (& now ) {
@@ -339,6 +343,119 @@ func (a *Operator) installOwnedAPIServiceRequirements(csv *v1alpha1.ClusterServi
339
343
return strategyDetailsDeployment , nil
340
344
}
341
345
346
+ // updateDeploymentSpecsWithApiServiceData transforms an install strategy to include information about apiservices
347
+ // it is used in generating hashes for deployment specs to know when something in the spec has changed,
348
+ // but duplicates a lot of installAPIServiceRequirements and should be refactored.
349
+ func (a * Operator ) updateDeploymentSpecsWithApiServiceData (csv * v1alpha1.ClusterServiceVersion , strategy install.Strategy ) (install.Strategy , error ) {
350
+ // Assume the strategy is for a deployment
351
+ strategyDetailsDeployment , ok := strategy .(* v1alpha1.StrategyDetailsDeployment )
352
+ if ! ok {
353
+ return nil , fmt .Errorf ("unsupported InstallStrategy type" )
354
+ }
355
+
356
+ apiDescs := csv .GetOwnedAPIServiceDescriptions ()
357
+
358
+ // Return early if there are no owned APIServices
359
+ if len (apiDescs ) == 0 {
360
+ return strategyDetailsDeployment , nil
361
+ }
362
+
363
+ depSpecs := make (map [string ]appsv1.DeploymentSpec )
364
+ for _ , sddSpec := range strategyDetailsDeployment .DeploymentSpecs {
365
+ depSpecs [sddSpec .Name ] = sddSpec .Spec
366
+ }
367
+
368
+ for _ , desc := range apiDescs {
369
+ apiServiceName := desc .GetName ()
370
+ apiService , err := a .lister .APIRegistrationV1 ().APIServiceLister ().Get (apiServiceName )
371
+ if err != nil {
372
+ return nil , fmt .Errorf ("could not retrieve generated APIService: %v" , err )
373
+ }
374
+
375
+ caBundle := apiService .Spec .CABundle
376
+ caHash := certs .PEMSHA256 (caBundle )
377
+
378
+ depSpec , ok := depSpecs [desc .DeploymentName ]
379
+ if ! ok {
380
+ return nil , fmt .Errorf ("StrategyDetailsDeployment missing deployment %s for owned APIService %s" , desc .DeploymentName , fmt .Sprintf ("%s.%s" , desc .Version , desc .Group ))
381
+ }
382
+
383
+ if depSpec .Template .Spec .ServiceAccountName == "" {
384
+ depSpec .Template .Spec .ServiceAccountName = "default"
385
+ }
386
+
387
+ // Update deployment with secret volume mount.
388
+ secret , err := a .lister .CoreV1 ().SecretLister ().Secrets (csv .GetNamespace ()).Get (secretName (apiServiceName ))
389
+
390
+ volume := corev1.Volume {
391
+ Name : "apiservice-cert" ,
392
+ VolumeSource : corev1.VolumeSource {
393
+ Secret : & corev1.SecretVolumeSource {
394
+ SecretName : secret .GetName (),
395
+ Items : []corev1.KeyToPath {
396
+ {
397
+ Key : "tls.crt" ,
398
+ Path : "apiserver.crt" ,
399
+ },
400
+ {
401
+ Key : "tls.key" ,
402
+ Path : "apiserver.key" ,
403
+ },
404
+ },
405
+ },
406
+ },
407
+ }
408
+
409
+ replaced := false
410
+ for i , v := range depSpec .Template .Spec .Volumes {
411
+ if v .Name == volume .Name {
412
+ depSpec .Template .Spec .Volumes [i ] = volume
413
+ replaced = true
414
+ break
415
+ }
416
+ }
417
+ if ! replaced {
418
+ depSpec .Template .Spec .Volumes = append (depSpec .Template .Spec .Volumes , volume )
419
+ }
420
+
421
+ mount := corev1.VolumeMount {
422
+ Name : volume .Name ,
423
+ MountPath : "/apiserver.local.config/certificates" ,
424
+ }
425
+ for i , container := range depSpec .Template .Spec .Containers {
426
+ found := false
427
+ for j , m := range container .VolumeMounts {
428
+ if m .Name == mount .Name {
429
+ found = true
430
+ break
431
+ }
432
+
433
+ // Replace if mounting to the same location.
434
+ if m .MountPath == mount .MountPath {
435
+ container .VolumeMounts [j ] = mount
436
+ found = true
437
+ break
438
+ }
439
+ }
440
+ if ! found {
441
+ container .VolumeMounts = append (container .VolumeMounts , mount )
442
+ }
443
+
444
+ depSpec .Template .Spec .Containers [i ] = container
445
+ }
446
+ depSpec .Template .ObjectMeta .SetAnnotations (map [string ]string {OLMCAHashAnnotationKey : caHash })
447
+ depSpecs [desc .DeploymentName ] = depSpec
448
+ }
449
+
450
+ // Replace all matching DeploymentSpecs in the strategy
451
+ for i , sddSpec := range strategyDetailsDeployment .DeploymentSpecs {
452
+ if depSpec , ok := depSpecs [sddSpec .Name ]; ok {
453
+ strategyDetailsDeployment .DeploymentSpecs [i ].Spec = depSpec
454
+ }
455
+ }
456
+ return strategyDetailsDeployment , nil
457
+ }
458
+
342
459
func (a * Operator ) installAPIServiceRequirements (desc v1alpha1.APIServiceDescription , ca * certs.KeyPair , rotateAt time.Time , depSpec appsv1.DeploymentSpec , csv * v1alpha1.ClusterServiceVersion ) (* appsv1.DeploymentSpec , error ) {
343
460
apiServiceName := fmt .Sprintf ("%s.%s" , desc .Version , desc .Group )
344
461
logger := log .WithFields (log.Fields {
@@ -413,7 +530,7 @@ func (a *Operator) installAPIServiceRequirements(desc v1alpha1.APIServiceDescrip
413
530
},
414
531
Type : corev1 .SecretTypeTLS ,
415
532
}
416
- secret .SetName (apiServiceName + "-cert" )
533
+ secret .SetName (secretName ( apiServiceName ) )
417
534
secret .SetNamespace (csv .GetNamespace ())
418
535
419
536
// Add olmcasha hash as a label to the
@@ -526,7 +643,7 @@ func (a *Operator) installAPIServiceRequirements(desc v1alpha1.APIServiceDescrip
526
643
ownerutil .AddNonBlockingOwner (secretRoleBinding , csv )
527
644
_ , err = a .opClient .CreateRoleBinding (secretRoleBinding )
528
645
if err != nil {
529
- log .Warnf ("could not create secret rolebinding with dep spec: %+ v" , depSpec )
646
+ log .Warnf ("could not create secret rolebinding with dep spec: %# v" , depSpec )
530
647
return nil , err
531
648
}
532
649
} else {
0 commit comments