Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -454,3 +454,7 @@ replace (
k8s.io/sample-cli-plugin => github.com/openshift/kubernetes/staging/src/k8s.io/sample-cli-plugin v0.0.0-20251028145634-9e794b89909a
k8s.io/sample-controller => github.com/openshift/kubernetes/staging/src/k8s.io/sample-controller v0.0.0-20251028145634-9e794b89909a
)

replace github.com/openshift/api => github.com/QiWang19/api v0.0.0-20251114203727-cc9c041a91b9

replace github.com/openshift/client-go => github.com/QiWang19/client-go v0.0.0-20251117173255-2694297c0f02
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJP
github.com/OpenPeeDeeP/depguard/v2 v2.2.0/go.mod h1:CIzddKRvLBC4Au5aYP/i3nyaWQ+ClszLIuVocRiCYFQ=
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
github.com/QiWang19/api v0.0.0-20251114203727-cc9c041a91b9 h1:MPT9b3vZEwR+TK18dqEOO1rJ0ZiRbVYUMh6CNz22X3g=
github.com/QiWang19/api v0.0.0-20251114203727-cc9c041a91b9/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY=
github.com/QiWang19/client-go v0.0.0-20251117173255-2694297c0f02 h1:ajKrS0qJ3BVoCpgRO2RGK0SlVOwkZpnVwWOG4M5QpVs=
github.com/QiWang19/client-go v0.0.0-20251117173255-2694297c0f02/go.mod h1:48IW9FiBV29MLOr9bVQQaXzgZuz/gAGoZcrt3PAzQAs=
github.com/ajeddeloh/go-json v0.0.0-20170920214419-6a2fe990e083/go.mod h1:otnto4/Icqn88WCcM4bhIJNSgsh9VLBuspyyCfvof9c=
github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559 h1:4SPQljF/GJ8Q+QlCWMWxRBepub4DresnOm4eI2ebFGc=
github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559/go.mod h1:otnto4/Icqn88WCcM4bhIJNSgsh9VLBuspyyCfvof9c=
Expand Down Expand Up @@ -609,10 +613,6 @@ github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplU
github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
github.com/openshift-eng/openshift-tests-extension v0.0.0-20250916161632-d81c09058835 h1:rkqIIfdYYkasXbF2XKVgh/3f1mhjSQK9By8WtVMgYo8=
github.com/openshift-eng/openshift-tests-extension v0.0.0-20250916161632-d81c09058835/go.mod h1:6gkP5f2HL0meusT0Aim8icAspcD1cG055xxBZ9yC68M=
github.com/openshift/api v0.0.0-20251104141128-d13e8c65d30f h1:xiSyW0ZZ0XWBiZ2ko7e/jI6N0m2DuwZqsSO4NHh/4T8=
github.com/openshift/api v0.0.0-20251104141128-d13e8c65d30f/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY=
github.com/openshift/client-go v0.0.0-20251015124057-db0dee36e235 h1:9JBeIXmnHlpXTQPi7LPmu1jdxznBhAE7bb1K+3D8gxY=
github.com/openshift/client-go v0.0.0-20251015124057-db0dee36e235/go.mod h1:L49W6pfrZkfOE5iC1PqEkuLkXG4W0BX4w8b+L2Bv7fM=
github.com/openshift/kubernetes v1.30.1-0.20251028145634-9e794b89909a h1:uaeiYAYOVlXChnGxvsziVTkzaSlBV7h8Y2U2Bc81UKM=
github.com/openshift/kubernetes v1.30.1-0.20251028145634-9e794b89909a/go.mod h1:w3+IfrXNp5RosdDXg3LB55yijJqR/FwouvVntYHQf0o=
github.com/openshift/kubernetes/staging/src/k8s.io/api v0.0.0-20251028145634-9e794b89909a h1:hZUZg/qpvT23oUoCkFWe/Q4VNu5zOeqmDOl3f/F6uRk=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package containerruntimeconfig
import (
"context"
"fmt"
"path/filepath"
"reflect"
"strconv"
"strings"
Expand All @@ -18,6 +19,7 @@ import (
configinformers "github.com/openshift/client-go/config/informers/externalversions"
cligoinformersv1 "github.com/openshift/client-go/config/informers/externalversions/config/v1"
cligolistersv1 "github.com/openshift/client-go/config/listers/config/v1"
cligolistersv1alpha1 "github.com/openshift/client-go/config/listers/config/v1alpha1"
runtimeutils "github.com/openshift/runtime-utils/pkg/registries"

operatorinformersv1alpha1 "github.com/openshift/client-go/operator/informers/externalversions/operator/v1alpha1"
Expand Down Expand Up @@ -84,6 +86,7 @@ type Controller struct {

syncHandler func(mcp string) error
syncImgHandler func(mcp string) error
syncCRIOCPHandler func(key string) error
enqueueContainerRuntimeConfig func(*mcfgv1.ContainerRuntimeConfig)

ccLister mcfglistersv1.ControllerConfigLister
Expand All @@ -104,6 +107,10 @@ type Controller struct {
itmsLister cligolistersv1.ImageTagMirrorSetLister
itmsListerSynced cache.InformerSynced

criocpLister cligolistersv1alpha1.CRIOCredentialProviderConfigLister
criocpListerSynced cache.InformerSynced
addedCRIOCPObservers bool

configInformerFactory configinformers.SharedInformerFactory
clusterImagePolicyLister cligolistersv1.ClusterImagePolicyLister
clusterImagePolicyListerSynced cache.InformerSynced
Expand All @@ -120,8 +127,9 @@ type Controller struct {

fgHandler ctrlcommon.FeatureGatesHandler

queue workqueue.TypedRateLimitingInterface[string]
imgQueue workqueue.TypedRateLimitingInterface[string]
queue workqueue.TypedRateLimitingInterface[string]
imgQueue workqueue.TypedRateLimitingInterface[string]
criocpQueue workqueue.TypedRateLimitingInterface[string]
}

// New returns a new container runtime config controller
Expand Down Expand Up @@ -188,6 +196,7 @@ func New(

ctrl.syncHandler = ctrl.syncContainerRuntimeConfig
ctrl.syncImgHandler = ctrl.syncImageConfig
ctrl.syncCRIOCPHandler = ctrl.syncCRIOCredentialProviderConfig
ctrl.enqueueContainerRuntimeConfig = ctrl.enqueue

ctrl.mcpLister = mcpInformer.Lister()
Expand Down Expand Up @@ -226,6 +235,7 @@ func (ctrl *Controller) Run(workers int, stopCh <-chan struct{}) {
defer utilruntime.HandleCrash()
defer ctrl.queue.ShutDown()
defer ctrl.imgQueue.ShutDown()
defer ctrl.criocpQueue.ShutDown()
listerCaches := []cache.InformerSynced{ctrl.mcpListerSynced, ctrl.mccrListerSynced, ctrl.ccListerSynced,
ctrl.imgListerSynced, ctrl.icspListerSynced, ctrl.idmsListerSynced, ctrl.itmsListerSynced, ctrl.clusterVersionListerSynced}

Expand All @@ -237,6 +247,14 @@ func (ctrl *Controller) Run(workers int, stopCh <-chan struct{}) {
ctrl.addedPolicyObservers = true
}

if ctrl.criocpEnabled() {
ctrl.addCRIOCPObservers()
klog.Info("added CRIOCredentialProviderConfig observers with CRIOCredentialProviderConfig featuregate enabled")
ctrl.configInformerFactory.Start(stopCh)
listerCaches = append(listerCaches, ctrl.criocpListerSynced)
ctrl.addedCRIOCPObservers = true
}

if !cache.WaitForCacheSync(stopCh, listerCaches...) {
return
}
Expand All @@ -251,6 +269,9 @@ func (ctrl *Controller) Run(workers int, stopCh <-chan struct{}) {
// Just need one worker for the image config
go wait.Until(ctrl.imgWorker, time.Second, stopCh)

// Just need one worker for the CRIOCredentialProviderConfig
go wait.Until(ctrl.criocpWorker, time.Second, stopCh)

<-stopCh
}

Expand Down Expand Up @@ -312,6 +333,28 @@ func (ctrl *Controller) itmsConfDeleted(_ interface{}) {
ctrl.imgQueue.Add("openshift-config")
}

func (ctrl *Controller) addCRIOCPObservers() {
ctrl.configInformerFactory.Config().V1alpha1().CRIOCredentialProviderConfigs().Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: ctrl.criocpConfAdded,
UpdateFunc: ctrl.criocpConfUpdated,
DeleteFunc: ctrl.criocpConfDeleted,
})
ctrl.criocpLister = ctrl.configInformerFactory.Config().V1alpha1().CRIOCredentialProviderConfigs().Lister()
ctrl.criocpListerSynced = ctrl.configInformerFactory.Config().V1alpha1().CRIOCredentialProviderConfigs().Informer().HasSynced
}

func (ctrl *Controller) criocpConfAdded(_ interface{}) {
ctrl.criocpQueue.Add("openshift-config")
}

func (ctrl *Controller) criocpConfUpdated(_, _ interface{}) {
ctrl.criocpQueue.Add("openshift-config")
}

func (ctrl *Controller) criocpConfDeleted(_ interface{}) {
ctrl.criocpQueue.Add("openshift-config")
}

func (ctrl *Controller) addImagePolicyObservers() {
ctrl.configInformerFactory.Config().V1().ClusterImagePolicies().Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: ctrl.clusterImagePolicyAdded,
Expand Down Expand Up @@ -358,6 +401,10 @@ func (ctrl *Controller) sigstoreAPIEnabled() bool {
return ctrl.fgHandler.Enabled(features.FeatureGateSigstoreImageVerification)
}

func (ctrl *Controller) criocpEnabled() bool {
return ctrl.fgHandler.Enabled(features.FeatureGateCRIOCredentialProviderConfig)
}

func (ctrl *Controller) updateContainerRuntimeConfig(oldObj, newObj interface{}) {
oldCtrCfg := oldObj.(*mcfgv1.ContainerRuntimeConfig)
newCtrCfg := newObj.(*mcfgv1.ContainerRuntimeConfig)
Expand Down Expand Up @@ -437,6 +484,11 @@ func (ctrl *Controller) imgWorker() {
}
}

func (ctrl *Controller) criocpWorker() {
for ctrl.processNextCRIOCPWorkItem() {
}
}

func (ctrl *Controller) processNextWorkItem() bool {
key, quit := ctrl.queue.Get()
if quit {
Expand All @@ -463,6 +515,19 @@ func (ctrl *Controller) processNextImgWorkItem() bool {
return true
}

func (ctrl *Controller) processNextCRIOCPWorkItem() bool {
key, quit := ctrl.criocpQueue.Get()
if quit {
return false
}
defer ctrl.criocpQueue.Done(key)

err := ctrl.syncCRIOCPHandler(key)
ctrl.handleCRIOCPErr(err, key)

return true
}

func (ctrl *Controller) handleErr(err error, key string) {
if err == nil {
ctrl.queue.Forget(key)
Expand Down Expand Up @@ -499,6 +564,24 @@ func (ctrl *Controller) handleImgErr(err error, key string) {
ctrl.imgQueue.AddAfter(key, 1*time.Minute)
}

func (ctrl *Controller) handleCRIOCPErr(err error, key string) {
if err == nil {
ctrl.criocpQueue.Forget(key)
return
}

if ctrl.criocpQueue.NumRequeues(key) < maxRetries {
klog.V(2).Infof("Error syncing CRIOCredentialProviderConfig %v: %v", key, err)
ctrl.criocpQueue.AddRateLimited(key)
return
}

utilruntime.HandleError(err)
klog.V(2).Infof("Dropping CRIOCredentialProviderConfig %q out of the queue: %v", key, err)
ctrl.criocpQueue.Forget(key)
ctrl.criocpQueue.AddAfter(key, 1*time.Minute)
}

// generateOriginalContainerRuntimeConfigs returns rendered default storage, registries and policy config files
func generateOriginalContainerRuntimeConfigs(templateDir string, cc *mcfgv1.ControllerConfig, role string) (*ign3types.File, *ign3types.File, *ign3types.File, error) {
// Render the default templates
Expand Down Expand Up @@ -546,6 +629,53 @@ func generateOriginalContainerRuntimeConfigs(templateDir string, cc *mcfgv1.Cont
return gmcStorageConfig, gmcRegistriesConfig, gmcPolicyJSON, nil
}

func generateOriginalCredentialProviderConfig(templateDir string, cc *mcfgv1.ControllerConfig, role string) (*ign3types.File, error) {

// Render the default templates
rc := &mtmpl.RenderConfig{
ControllerConfigSpec: &cc.Spec,
}
generatedConfigs, err := mtmpl.GenerateMachineConfigsForRole(rc, role, templateDir)
if err != nil {
return nil, fmt.Errorf("generateMachineConfigsforRole failed with error %w", err)
}
// Find generated provider.yaml
var (
config, gmcCredProviderConfig *ign3types.File
errCredProvider error
credProviderConfigPath string
)

// Determine credential provider config path based on platform
// staying consistent with path used in pkg/controller/template/render.go
credProviderConfigPathFormat := filepath.FromSlash("/etc/kubernetes/credential-providers/%s-credential-provider.yaml")
switch cc.Spec.Infra.Status.PlatformStatus.Type {
case apicfgv1.AWSPlatformType:
credProviderConfigPath = fmt.Sprintf(credProviderConfigPathFormat, "ecr")
case apicfgv1.GCPPlatformType:
credProviderConfigPath = fmt.Sprintf(credProviderConfigPathFormat, "gcr")
case apicfgv1.AzurePlatformType:
credProviderConfigPath = fmt.Sprintf(credProviderConfigPathFormat, "acr")
default:
return nil, fmt.Errorf("unsupported platform type: %s", cc.Spec.Infra.Status.PlatformStatus.Type)
}
klog.Infof("credential provider config path set to: %s", credProviderConfigPath)

// Find credential provider config
for _, gmc := range generatedConfigs {
config, errCredProvider = findCredProviderConfig(gmc, credProviderConfigPath)
if errCredProvider != nil {
klog.V(4).Infof("could not find credential provider config in generated config %s: %v", gmc.Name, errCredProvider)
return nil, fmt.Errorf("could not generate original credential provider configs: %w", errCredProvider)
}

gmcCredProviderConfig = config

}

return gmcCredProviderConfig, nil
}

func (ctrl *Controller) syncStatusOnly(cfg *mcfgv1.ContainerRuntimeConfig, err error, args ...interface{}) error {
statusUpdateErr := retry.RetryOnConflict(updateBackoff, func() error {
newcfg, getErr := ctrl.mccrLister.Get(cfg.Name)
Expand Down Expand Up @@ -958,6 +1088,45 @@ func (ctrl *Controller) syncImageConfig(key string) error {
return nil
}

func (ctrl *Controller) syncCRIOCredentialProviderConfig(key string) error {
startTime := time.Now()
klog.V(4).Infof("Started syncing CRIOCredentialProvider config %q (%v)", key, startTime)
defer func() {
klog.V(4).Infof("Finished syncing CRIOCredentialProvider config %q (%v)", key, time.Since(startTime))
}()

// Get ControllerConfig
controllerConfig, err := ctrl.ccLister.Get(ctrlcommon.ControllerConfigName)
if err != nil {
return fmt.Errorf("could not get ControllerConfig %w", err)
}

sel, err := metav1.LabelSelectorAsSelector(metav1.AddLabelToSelector(&metav1.LabelSelector{}, builtInLabelKey, ""))
if err != nil {
return err
}
// Find all the MCO built in MachineConfigPools
mcpPools, err := ctrl.mcpLister.List(sel)
if err != nil {
return err
}

for _, pool := range mcpPools {
role := pool.Name
credProviderConfigIgn, err := generateOriginalCredentialProviderConfig(ctrl.templatesDir, controllerConfig, role)
if err != nil {
return fmt.Errorf("could not generate original CRIO credential provider config for role %s: %w", role, err)
}
contents, err := ctrlcommon.DecodeIgnitionFileContents(credProviderConfigIgn.Contents.Source, credProviderConfigIgn.Contents.Compression)
if err != nil {
return fmt.Errorf("could not decode CRIO credential provider config for role %s: %w", role, err)
}
klog.Infof("Decoded CRIO credential provider config contents successfully for role %s: %s", role, string(contents))
}

return nil
}

func (ctrl *Controller) syncIgnitionConfig(managedKey string, ignFile *ign3types.Config, pool *mcfgv1.MachineConfigPool, ownerRef metav1.OwnerReference) (bool, error) {
rawIgn, err := json.Marshal(ignFile)
if err != nil {
Expand Down
15 changes: 15 additions & 0 deletions pkg/controller/container-runtime-config/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,21 @@ func findPolicyJSON(mc *mcfgv1.MachineConfig) (*ign3types.File, error) {
return nil, fmt.Errorf("could not find Policy JSON")
}

func findCredProviderConfig(mc *mcfgv1.MachineConfig, credProviderConfigPath string) (*ign3types.File, error) {
ignCfg, err := ctrlcommon.ParseAndConvertConfig(mc.Spec.Config.Raw)
if err != nil {
return nil, fmt.Errorf("parsing Credential Provider Ignition config failed with error: %w", err)
}
for _, c := range ignCfg.Storage.Files {
klog.Infof("Checking file path : %s", c.Path)
if c.Path == credProviderConfigPath {
c := c
return &c, nil
}
}
return nil, fmt.Errorf("could not find Credential Provider Config")
}

// Deprecated: use getManagedKeyCtrCfg
func getManagedKeyCtrCfgDeprecated(pool *mcfgv1.MachineConfigPool) string {
return fmt.Sprintf("99-%s-%s-containerruntime", pool.Name, pool.ObjectMeta.UID)
Expand Down
2 changes: 2 additions & 0 deletions vendor/github.com/openshift/api/config/v1alpha1/register.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading