@@ -3,6 +3,7 @@ package containerruntimeconfig
33import (
44 "context"
55 "fmt"
6+ "path/filepath"
67 "reflect"
78 "strconv"
89 "strings"
@@ -18,6 +19,7 @@ import (
1819 configinformers "github.com/openshift/client-go/config/informers/externalversions"
1920 cligoinformersv1 "github.com/openshift/client-go/config/informers/externalversions/config/v1"
2021 cligolistersv1 "github.com/openshift/client-go/config/listers/config/v1"
22+ cligolistersv1alpha1 "github.com/openshift/client-go/config/listers/config/v1alpha1"
2123 runtimeutils "github.com/openshift/runtime-utils/pkg/registries"
2224
2325 operatorinformersv1alpha1 "github.com/openshift/client-go/operator/informers/externalversions/operator/v1alpha1"
@@ -84,6 +86,7 @@ type Controller struct {
8486
8587 syncHandler func (mcp string ) error
8688 syncImgHandler func (mcp string ) error
89+ syncCRIOCPHandler func (key string ) error
8790 enqueueContainerRuntimeConfig func (* mcfgv1.ContainerRuntimeConfig )
8891
8992 ccLister mcfglistersv1.ControllerConfigLister
@@ -104,6 +107,10 @@ type Controller struct {
104107 itmsLister cligolistersv1.ImageTagMirrorSetLister
105108 itmsListerSynced cache.InformerSynced
106109
110+ criocpLister cligolistersv1alpha1.CRIOCredentialProviderConfigLister
111+ criocpListerSynced cache.InformerSynced
112+ addedCRIOCPObservers bool
113+
107114 configInformerFactory configinformers.SharedInformerFactory
108115 clusterImagePolicyLister cligolistersv1.ClusterImagePolicyLister
109116 clusterImagePolicyListerSynced cache.InformerSynced
@@ -120,8 +127,9 @@ type Controller struct {
120127
121128 fgHandler ctrlcommon.FeatureGatesHandler
122129
123- queue workqueue.TypedRateLimitingInterface [string ]
124- imgQueue workqueue.TypedRateLimitingInterface [string ]
130+ queue workqueue.TypedRateLimitingInterface [string ]
131+ imgQueue workqueue.TypedRateLimitingInterface [string ]
132+ criocpQueue workqueue.TypedRateLimitingInterface [string ]
125133}
126134
127135// New returns a new container runtime config controller
@@ -188,6 +196,7 @@ func New(
188196
189197 ctrl .syncHandler = ctrl .syncContainerRuntimeConfig
190198 ctrl .syncImgHandler = ctrl .syncImageConfig
199+ ctrl .syncCRIOCPHandler = ctrl .syncCRIOCredentialProviderConfig
191200 ctrl .enqueueContainerRuntimeConfig = ctrl .enqueue
192201
193202 ctrl .mcpLister = mcpInformer .Lister ()
@@ -226,6 +235,7 @@ func (ctrl *Controller) Run(workers int, stopCh <-chan struct{}) {
226235 defer utilruntime .HandleCrash ()
227236 defer ctrl .queue .ShutDown ()
228237 defer ctrl .imgQueue .ShutDown ()
238+ defer ctrl .criocpQueue .ShutDown ()
229239 listerCaches := []cache.InformerSynced {ctrl .mcpListerSynced , ctrl .mccrListerSynced , ctrl .ccListerSynced ,
230240 ctrl .imgListerSynced , ctrl .icspListerSynced , ctrl .idmsListerSynced , ctrl .itmsListerSynced , ctrl .clusterVersionListerSynced }
231241
@@ -237,6 +247,14 @@ func (ctrl *Controller) Run(workers int, stopCh <-chan struct{}) {
237247 ctrl .addedPolicyObservers = true
238248 }
239249
250+ if ctrl .criocpEnabled () {
251+ ctrl .addCRIOCPObservers ()
252+ klog .Info ("added CRIOCredentialProviderConfig observers with CRIOCredentialProviderConfig featuregate enabled" )
253+ ctrl .configInformerFactory .Start (stopCh )
254+ listerCaches = append (listerCaches , ctrl .criocpListerSynced )
255+ ctrl .addedCRIOCPObservers = true
256+ }
257+
240258 if ! cache .WaitForCacheSync (stopCh , listerCaches ... ) {
241259 return
242260 }
@@ -251,6 +269,9 @@ func (ctrl *Controller) Run(workers int, stopCh <-chan struct{}) {
251269 // Just need one worker for the image config
252270 go wait .Until (ctrl .imgWorker , time .Second , stopCh )
253271
272+ // Just need one worker for the CRIOCredentialProviderConfig
273+ go wait .Until (ctrl .criocpWorker , time .Second , stopCh )
274+
254275 <- stopCh
255276}
256277
@@ -312,6 +333,28 @@ func (ctrl *Controller) itmsConfDeleted(_ interface{}) {
312333 ctrl .imgQueue .Add ("openshift-config" )
313334}
314335
336+ func (ctrl * Controller ) addCRIOCPObservers () {
337+ ctrl .configInformerFactory .Config ().V1alpha1 ().CRIOCredentialProviderConfigs ().Informer ().AddEventHandler (cache.ResourceEventHandlerFuncs {
338+ AddFunc : ctrl .criocpConfAdded ,
339+ UpdateFunc : ctrl .criocpConfUpdated ,
340+ DeleteFunc : ctrl .criocpConfDeleted ,
341+ })
342+ ctrl .criocpLister = ctrl .configInformerFactory .Config ().V1alpha1 ().CRIOCredentialProviderConfigs ().Lister ()
343+ ctrl .criocpListerSynced = ctrl .configInformerFactory .Config ().V1alpha1 ().CRIOCredentialProviderConfigs ().Informer ().HasSynced
344+ }
345+
346+ func (ctrl * Controller ) criocpConfAdded (_ interface {}) {
347+ ctrl .criocpQueue .Add ("openshift-config" )
348+ }
349+
350+ func (ctrl * Controller ) criocpConfUpdated (_ , _ interface {}) {
351+ ctrl .criocpQueue .Add ("openshift-config" )
352+ }
353+
354+ func (ctrl * Controller ) criocpConfDeleted (_ interface {}) {
355+ ctrl .criocpQueue .Add ("openshift-config" )
356+ }
357+
315358func (ctrl * Controller ) addImagePolicyObservers () {
316359 ctrl .configInformerFactory .Config ().V1 ().ClusterImagePolicies ().Informer ().AddEventHandler (cache.ResourceEventHandlerFuncs {
317360 AddFunc : ctrl .clusterImagePolicyAdded ,
@@ -358,6 +401,10 @@ func (ctrl *Controller) sigstoreAPIEnabled() bool {
358401 return ctrl .fgHandler .Enabled (features .FeatureGateSigstoreImageVerification )
359402}
360403
404+ func (ctrl * Controller ) criocpEnabled () bool {
405+ return ctrl .fgHandler .Enabled (features .FeatureGateCRIOCredentialProviderConfig )
406+ }
407+
361408func (ctrl * Controller ) updateContainerRuntimeConfig (oldObj , newObj interface {}) {
362409 oldCtrCfg := oldObj .(* mcfgv1.ContainerRuntimeConfig )
363410 newCtrCfg := newObj .(* mcfgv1.ContainerRuntimeConfig )
@@ -437,6 +484,11 @@ func (ctrl *Controller) imgWorker() {
437484 }
438485}
439486
487+ func (ctrl * Controller ) criocpWorker () {
488+ for ctrl .processNextCRIOCPWorkItem () {
489+ }
490+ }
491+
440492func (ctrl * Controller ) processNextWorkItem () bool {
441493 key , quit := ctrl .queue .Get ()
442494 if quit {
@@ -463,6 +515,19 @@ func (ctrl *Controller) processNextImgWorkItem() bool {
463515 return true
464516}
465517
518+ func (ctrl * Controller ) processNextCRIOCPWorkItem () bool {
519+ key , quit := ctrl .criocpQueue .Get ()
520+ if quit {
521+ return false
522+ }
523+ defer ctrl .criocpQueue .Done (key )
524+
525+ err := ctrl .syncCRIOCPHandler (key )
526+ ctrl .handleCRIOCPErr (err , key )
527+
528+ return true
529+ }
530+
466531func (ctrl * Controller ) handleErr (err error , key string ) {
467532 if err == nil {
468533 ctrl .queue .Forget (key )
@@ -499,6 +564,24 @@ func (ctrl *Controller) handleImgErr(err error, key string) {
499564 ctrl .imgQueue .AddAfter (key , 1 * time .Minute )
500565}
501566
567+ func (ctrl * Controller ) handleCRIOCPErr (err error , key string ) {
568+ if err == nil {
569+ ctrl .criocpQueue .Forget (key )
570+ return
571+ }
572+
573+ if ctrl .criocpQueue .NumRequeues (key ) < maxRetries {
574+ klog .V (2 ).Infof ("Error syncing CRIOCredentialProviderConfig %v: %v" , key , err )
575+ ctrl .criocpQueue .AddRateLimited (key )
576+ return
577+ }
578+
579+ utilruntime .HandleError (err )
580+ klog .V (2 ).Infof ("Dropping CRIOCredentialProviderConfig %q out of the queue: %v" , key , err )
581+ ctrl .criocpQueue .Forget (key )
582+ ctrl .criocpQueue .AddAfter (key , 1 * time .Minute )
583+ }
584+
502585// generateOriginalContainerRuntimeConfigs returns rendered default storage, registries and policy config files
503586func generateOriginalContainerRuntimeConfigs (templateDir string , cc * mcfgv1.ControllerConfig , role string ) (* ign3types.File , * ign3types.File , * ign3types.File , error ) {
504587 // Render the default templates
@@ -546,6 +629,53 @@ func generateOriginalContainerRuntimeConfigs(templateDir string, cc *mcfgv1.Cont
546629 return gmcStorageConfig , gmcRegistriesConfig , gmcPolicyJSON , nil
547630}
548631
632+ func generateOriginalCredentialProviderConfig (templateDir string , cc * mcfgv1.ControllerConfig , role string ) (* ign3types.File , error ) {
633+
634+ // Render the default templates
635+ rc := & mtmpl.RenderConfig {
636+ ControllerConfigSpec : & cc .Spec ,
637+ }
638+ generatedConfigs , err := mtmpl .GenerateMachineConfigsForRole (rc , role , templateDir )
639+ if err != nil {
640+ return nil , fmt .Errorf ("generateMachineConfigsforRole failed with error %w" , err )
641+ }
642+ // Find generated provider.yaml
643+ var (
644+ config , gmcCredProviderConfig * ign3types.File
645+ errCredProvider error
646+ credProviderConfigPath string
647+ )
648+
649+ // Determine credential provider config path based on platform
650+ // staying consistent with path used in pkg/controller/template/render.go
651+ credProviderConfigPathFormat := filepath .FromSlash ("/etc/kubernetes/credential-providers/%s-credential-provider.yaml" )
652+ switch cc .Spec .Infra .Status .PlatformStatus .Type {
653+ case apicfgv1 .AWSPlatformType :
654+ credProviderConfigPath = fmt .Sprintf (credProviderConfigPathFormat , "ecr" )
655+ case apicfgv1 .GCPPlatformType :
656+ credProviderConfigPath = fmt .Sprintf (credProviderConfigPathFormat , "gcr" )
657+ case apicfgv1 .AzurePlatformType :
658+ credProviderConfigPath = fmt .Sprintf (credProviderConfigPathFormat , "acr" )
659+ default :
660+ return nil , fmt .Errorf ("unsupported platform type: %s" , cc .Spec .Infra .Status .PlatformStatus .Type )
661+ }
662+ klog .Infof ("credential provider config path set to: %s" , credProviderConfigPath )
663+
664+ // Find credential provider config
665+ for _ , gmc := range generatedConfigs {
666+ config , errCredProvider = findCredProviderConfig (gmc , credProviderConfigPath )
667+ if errCredProvider != nil {
668+ klog .V (4 ).Infof ("could not find credential provider config in generated config %s: %v" , gmc .Name , errCredProvider )
669+ return nil , fmt .Errorf ("could not generate original credential provider configs: %w" , errCredProvider )
670+ }
671+
672+ gmcCredProviderConfig = config
673+
674+ }
675+
676+ return gmcCredProviderConfig , nil
677+ }
678+
549679func (ctrl * Controller ) syncStatusOnly (cfg * mcfgv1.ContainerRuntimeConfig , err error , args ... interface {}) error {
550680 statusUpdateErr := retry .RetryOnConflict (updateBackoff , func () error {
551681 newcfg , getErr := ctrl .mccrLister .Get (cfg .Name )
@@ -958,6 +1088,45 @@ func (ctrl *Controller) syncImageConfig(key string) error {
9581088 return nil
9591089}
9601090
1091+ func (ctrl * Controller ) syncCRIOCredentialProviderConfig (key string ) error {
1092+ startTime := time .Now ()
1093+ klog .V (4 ).Infof ("Started syncing CRIOCredentialProvider config %q (%v)" , key , startTime )
1094+ defer func () {
1095+ klog .V (4 ).Infof ("Finished syncing CRIOCredentialProvider config %q (%v)" , key , time .Since (startTime ))
1096+ }()
1097+
1098+ // Get ControllerConfig
1099+ controllerConfig , err := ctrl .ccLister .Get (ctrlcommon .ControllerConfigName )
1100+ if err != nil {
1101+ return fmt .Errorf ("could not get ControllerConfig %w" , err )
1102+ }
1103+
1104+ sel , err := metav1 .LabelSelectorAsSelector (metav1 .AddLabelToSelector (& metav1.LabelSelector {}, builtInLabelKey , "" ))
1105+ if err != nil {
1106+ return err
1107+ }
1108+ // Find all the MCO built in MachineConfigPools
1109+ mcpPools , err := ctrl .mcpLister .List (sel )
1110+ if err != nil {
1111+ return err
1112+ }
1113+
1114+ for _ , pool := range mcpPools {
1115+ role := pool .Name
1116+ credProviderConfigIgn , err := generateOriginalCredentialProviderConfig (ctrl .templatesDir , controllerConfig , role )
1117+ if err != nil {
1118+ return fmt .Errorf ("could not generate original CRIO credential provider config for role %s: %w" , role , err )
1119+ }
1120+ contents , err := ctrlcommon .DecodeIgnitionFileContents (credProviderConfigIgn .Contents .Source , credProviderConfigIgn .Contents .Compression )
1121+ if err != nil {
1122+ return fmt .Errorf ("could not decode CRIO credential provider config for role %s: %w" , role , err )
1123+ }
1124+ klog .Infof ("Decoded CRIO credential provider config contents successfully for role %s: %s" , role , string (contents ))
1125+ }
1126+
1127+ return nil
1128+ }
1129+
9611130func (ctrl * Controller ) syncIgnitionConfig (managedKey string , ignFile * ign3types.Config , pool * mcfgv1.MachineConfigPool , ownerRef metav1.OwnerReference ) (bool , error ) {
9621131 rawIgn , err := json .Marshal (ignFile )
9631132 if err != nil {
0 commit comments