@@ -26,6 +26,7 @@ import (
2626 corev1 "k8s.io/api/core/v1"
2727 apierrors "k8s.io/apimachinery/pkg/api/errors"
2828 "k8s.io/apimachinery/pkg/runtime"
29+ "k8s.io/utils/ptr"
2930 ctrl "sigs.k8s.io/controller-runtime"
3031 "sigs.k8s.io/controller-runtime/pkg/builder"
3132 "sigs.k8s.io/controller-runtime/pkg/client"
@@ -36,7 +37,8 @@ import (
3637)
3738
3839const (
39- managedUserDataSecretName = "worker-user-data"
40+ workerUserDataSecretName = "worker-user-data"
41+ masterUserDataSecretName = "master-user-data"
4042
4143 // SecretSourceNamespace is the source namespace to copy the user data secret from.
4244 SecretSourceNamespace = "openshift-machine-api"
@@ -63,86 +65,87 @@ type UserDataSecretController struct {
6365// Reconcile reconciles the user data secret.
6466func (r * UserDataSecretController ) Reconcile (ctx context.Context , req ctrl.Request ) (ctrl.Result , error ) {
6567 log := ctrl .LoggerFrom (ctx ).WithName (controllerName )
66- log .Info ("reconciling worker user data secret" )
68+ secretName := req .Name
69+ log .Info ("reconciling user data secret" , "secretName" , secretName )
6770
68- defaultSourceSecretObjectKey := client.ObjectKey {
69- Name : managedUserDataSecretName , Namespace : SecretSourceNamespace ,
71+ if ! isValidUserDataSecretName (secretName ) {
72+ log .Info ("ignoring request for unknown secret" , "secretName" , secretName )
73+ return ctrl.Result {}, nil
7074 }
71- sourceSecret := & corev1.Secret {}
72-
73- if err := r .Get (ctx , defaultSourceSecretObjectKey , sourceSecret ); err != nil {
74- log .Error (err , "unable to get source secret for sync" )
7575
76+ if err := r .reconcileUserDataSecret (ctx , log , secretName ); err != nil {
7677 if err := r .setDegradedCondition (ctx , log ); err != nil {
7778 return ctrl.Result {}, fmt .Errorf ("failed to set conditions for secret sync controller: %w" , err )
7879 }
7980
80- return ctrl.Result {}, fmt . Errorf ( "failed to get source secret: %w" , err )
81+ return ctrl.Result {}, err
8182 }
8283
83- targetSecret := & corev1.Secret {}
84- targetSecretKey := client.ObjectKey {
85- Namespace : r .ManagedNamespace ,
86- Name : managedUserDataSecretName ,
84+ if err := r .setAvailableCondition (ctx , log ); err != nil {
85+ return ctrl.Result {}, fmt .Errorf ("failed to set conditions for user data secret controller: %w" , err )
8786 }
8887
89- // If the secret does not exist, it will be created later, so we can ignore a Not Found error
90- if err := r .Get (ctx , targetSecretKey , targetSecret ); err != nil && ! apierrors .IsNotFound (err ) {
91- log .Error (err , "unable to get target secret for sync" )
88+ return ctrl.Result {}, nil
89+ }
9290
93- if err := r .setDegradedCondition (ctx , log ); err != nil {
94- return ctrl.Result {}, fmt .Errorf ("failed to set conditions for secret controller: %w" , err )
95- }
91+ // reconcileUserDataSecret performs the actual reconciliation for a specific user data secret.
92+ func (r * UserDataSecretController ) reconcileUserDataSecret (ctx context.Context , log logr.Logger , secretName string ) error {
93+ sourceSecret := & corev1.Secret {}
94+ targetSecret := & corev1.Secret {}
9695
97- return ctrl.Result {}, fmt .Errorf ("failed to get target secret: %w" , err )
96+ sourceSecretObjectKey := client.ObjectKey {
97+ Name : secretName , Namespace : SecretSourceNamespace ,
9898 }
99-
100- if r .areSecretsEqual (sourceSecret , targetSecret ) {
101- log .Info ("user data in source and target secrets is the same, no sync needed" )
102-
103- if err := r .setAvailableCondition (ctx , log ); err != nil {
104- return ctrl.Result {}, fmt .Errorf ("failed to set conditions for user data secret controller: %w" , err )
105- }
106-
107- return ctrl.Result {}, nil
99+ if err := r .Get (ctx , sourceSecretObjectKey , sourceSecret ); err != nil {
100+ log .Error (err , "unable to get source secret for sync" , "secretName" , secretName )
101+ return fmt .Errorf ("failed to get source secret %s: %w" , secretName , err )
108102 }
109103
110- if err := r .syncSecretData (ctx , sourceSecret , targetSecret ); err != nil {
111- log .Error (err , "unable to sync user data secret" )
112-
113- if err := r .setDegradedCondition (ctx , log ); err != nil {
114- return ctrl.Result {}, fmt .Errorf ("failed to set conditions for user data secret controller: %w" , err )
115- }
104+ targetSecretObjectKey := client.ObjectKey {
105+ Namespace : r .ManagedNamespace ,
106+ Name : secretName ,
107+ }
108+ // If the secret does not exist, it will be created later, so we can ignore a Not Found error
109+ if err := r .Get (ctx , targetSecretObjectKey , targetSecret ); err != nil && ! apierrors .IsNotFound (err ) {
110+ log .Error (err , "unable to get target secret for sync" , "secretName" , secretName )
111+ return fmt .Errorf ("failed to get target secret %s: %w" , secretName , err )
112+ }
116113
117- return ctrl.Result {}, err
114+ if r .areSecretsEqual (sourceSecret , targetSecret ) {
115+ log .Info ("user data in source and target secrets is the same, no sync needed" , "secretName" , secretName )
116+ return nil
118117 }
119118
120- if err := r .setAvailableCondition (ctx , log ); err != nil {
121- return ctrl.Result {}, fmt .Errorf ("failed to set conditions for user data secret controller: %w" , err )
119+ if err := r .syncSecretData (ctx , sourceSecret , targetSecret , secretName ); err != nil {
120+ log .Error (err , "unable to sync user data secret" , "secretName" , secretName )
121+ return fmt .Errorf ("failed to sync secret %s: %w" , secretName , err )
122122 }
123123
124- return ctrl.Result {}, nil
124+ log .Info ("user data secret synced successfully" , "secretName" , secretName )
125+
126+ return nil
125127}
126128
127- func (r * UserDataSecretController ) areSecretsEqual (source * corev1.Secret , target * corev1.Secret ) bool {
128- return source .Immutable == target .Immutable &&
129- reflect .DeepEqual (source .Data [mapiUserDataKey ], target .Data [capiUserDataKey ]) && reflect .DeepEqual (source .StringData , target .StringData ) &&
129+ func (r * UserDataSecretController ) areSecretsEqual (source , target * corev1.Secret ) bool {
130+ immutableEqual := ptr .Deref (source .Immutable , false ) == ptr .Deref (target .Immutable , false )
131+
132+ return immutableEqual &&
133+ reflect .DeepEqual (source .Data [mapiUserDataKey ], target .Data [capiUserDataKey ]) &&
130134 source .Type == target .Type
131135}
132136
133- func (r * UserDataSecretController ) syncSecretData (ctx context.Context , source * corev1.Secret , target * corev1.Secret ) error {
137+ func (r * UserDataSecretController ) syncSecretData (ctx context.Context , source * corev1.Secret , target * corev1.Secret , secretName string ) error {
134138 userData := source .Data [mapiUserDataKey ]
135139 if userData == nil {
136140 return errSourceSecretMissingUserData
137141 }
138142
139- target .SetName (managedUserDataSecretName )
143+ target .SetName (secretName )
140144 target .SetNamespace (r .ManagedNamespace )
141145 target .Data = map [string ][]byte {
142- "value" : userData ,
143- "format" : []byte ("ignition" ),
146+ capiUserDataKey : userData ,
147+ "format" : []byte ("ignition" ),
144148 }
145- target .StringData = source .StringData
146149 target .Immutable = source .Immutable
147150 target .Type = source .Type
148151
@@ -175,7 +178,7 @@ func (r *UserDataSecretController) SetupWithManager(mgr ctrl.Manager) error {
175178 ).
176179 Watches (
177180 & corev1.Secret {},
178- handler .EnqueueRequestsFromMapFunc (toUserDataSecret ),
181+ handler .EnqueueRequestsFromMapFunc (toUserDataSecret ( r . ManagedNamespace ) ),
179182 builder .WithPredicates (userDataSecretPredicate (SecretSourceNamespace )),
180183 ).
181184 Complete (r ); err != nil {
@@ -185,6 +188,11 @@ func (r *UserDataSecretController) SetupWithManager(mgr ctrl.Manager) error {
185188 return nil
186189}
187190
191+ // isValidUserDataSecretName checks if the given secret name is a user data secret we should sync.
192+ func isValidUserDataSecretName (secretName string ) bool {
193+ return secretName == workerUserDataSecretName || secretName == masterUserDataSecretName
194+ }
195+
188196func (r * UserDataSecretController ) setAvailableCondition (ctx context.Context , log logr.Logger ) error {
189197 co , err := r .GetOrCreateClusterOperator (ctx )
190198 if err != nil {
0 commit comments