@@ -32,9 +32,12 @@ import (
3232 rbacv1 "k8s.io/api/rbac/v1"
3333 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
3434 apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
35+ apierrors "k8s.io/apimachinery/pkg/api/errors"
36+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3537 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3638 "k8s.io/apimachinery/pkg/runtime"
3739 "k8s.io/apimachinery/pkg/runtime/serializer"
40+ "k8s.io/utils/ptr"
3841
3942 "k8s.io/client-go/kubernetes"
4043 "k8s.io/client-go/rest"
@@ -90,7 +93,17 @@ type CapiInstallerController struct {
9093func (r * CapiInstallerController ) Reconcile (ctx context.Context , req ctrl.Request ) (ctrl.Result , error ) {
9194 log := ctrl .LoggerFrom (ctx ).WithName (controllerName )
9295
93- res , err := r .reconcile (ctx , log )
96+ clusterOperator := & configv1.ClusterOperator {}
97+ if err := r .Get (ctx , client.ObjectKey {Name : controllers .ClusterOperatorName }, clusterOperator ); err != nil {
98+ if apierrors .IsNotFound (err ) {
99+ log .Info ("Waiting for creation of cluster operator" )
100+ return ctrl.Result {}, nil
101+ }
102+
103+ return ctrl.Result {}, fmt .Errorf ("failed to get cluster operator: %w" , err )
104+ }
105+
106+ res , err := r .reconcile (ctx , log , clusterOperator )
94107 if err != nil {
95108 return ctrl.Result {}, fmt .Errorf ("error during reconcile: %w" , err )
96109 }
@@ -108,7 +121,7 @@ func (r *CapiInstallerController) Reconcile(ctx context.Context, req ctrl.Reques
108121// and it applies them to the cluster.
109122//
110123//nolint:unparam
111- func (r * CapiInstallerController ) reconcile (ctx context.Context , log logr.Logger ) (ctrl.Result , error ) {
124+ func (r * CapiInstallerController ) reconcile (ctx context.Context , log logr.Logger , clusterOperator * configv1. ClusterOperator ) (ctrl.Result , error ) {
112125 // Define the desired providers to be installed for this cluster.
113126 // We always want to install the core provider, which in our case is the default cluster-api core provider.
114127 // We also want to install the infrastructure provider that matches the currently detected platform the cluster is running on.
@@ -156,7 +169,7 @@ func (r *CapiInstallerController) reconcile(ctx context.Context, log logr.Logger
156169 }
157170
158171 // Apply all the collected provider components manifests.
159- if err := r .applyProviderComponents (ctx , providerComponents ); err != nil {
172+ if err := r .applyProviderComponents (ctx , providerComponents , clusterOperator ); err != nil {
160173 if err := r .setDegradedCondition (ctx , log ); err != nil {
161174 return ctrl.Result {}, fmt .Errorf ("failed to set conditions for CAPI Installer controller: %w" , err )
162175 }
@@ -172,7 +185,7 @@ func (r *CapiInstallerController) reconcile(ctx context.Context, log logr.Logger
172185
173186// applyProviderComponents applies the provider components to the cluster.
174187// It does so by differentiating between static components and dynamic components (i.e. Deployments).
175- func (r * CapiInstallerController ) applyProviderComponents (ctx context.Context , components []string ) error {
188+ func (r * CapiInstallerController ) applyProviderComponents (ctx context.Context , components []string , owner client. Object ) error {
176189 providerObjects , err := getProviderObjects (r .Scheme , components )
177190 if err != nil {
178191 return fmt .Errorf ("error getting provider components: %w" , err )
@@ -181,6 +194,17 @@ func (r *CapiInstallerController) applyProviderComponents(ctx context.Context, c
181194 var errs error
182195
183196 for i , providerObject := range providerObjects {
197+ // All objects created by cluster-capi-operator are owned by its cluster operator
198+ providerObject .SetOwnerReferences ([]metav1.OwnerReference {
199+ {
200+ APIVersion : owner .GetObjectKind ().GroupVersionKind ().Version ,
201+ Kind : owner .GetObjectKind ().GroupVersionKind ().Kind ,
202+ Name : owner .GetName (),
203+ UID : owner .GetUID (),
204+ Controller : ptr .To (true ),
205+ },
206+ })
207+
184208 err := r .Patch (ctx , providerObject , client .Apply , client .ForceOwnership , client .FieldOwner ("cluster-capi-operator.openshift.io/installer" ))
185209 if err != nil {
186210 gvk := providerObject .GroupVersionKind ()
@@ -268,41 +292,44 @@ func (r *CapiInstallerController) SetupWithManager(mgr ctrl.Manager) error {
268292 Watches (
269293 & corev1.ConfigMap {},
270294 handler .EnqueueRequestsFromMapFunc (toClusterOperator ),
271- builder .WithPredicates (configMapPredicate (r .ManagedNamespace , r .Platform )),
295+ builder .WithPredicates (transportConfigMapPredicate (r .ManagedNamespace , r .Platform )),
272296 )
273297
274- // All of the following watches share the ownedPlatformLabelPredicate.
275- watches := []struct {
298+ // All of the following ownsTypes share the ownedPlatformLabelPredicate.
299+ ownsTypes := []struct {
276300 obj client.Object
277301 namespace string
278302 }{
279- {& appsv1.Deployment {}, r .ManagedNamespace },
280- {& admissionregistrationv1.ValidatingWebhookConfiguration {}, notNamespaced },
281303 {& admissionregistrationv1.MutatingWebhookConfiguration {}, notNamespaced },
304+ {& admissionregistrationv1.ValidatingWebhookConfiguration {}, notNamespaced },
282305 {& admissionregistrationv1beta1.ValidatingAdmissionPolicy {}, notNamespaced },
283306 {& admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding {}, notNamespaced },
284- {& corev1.Service {}, r .ManagedNamespace },
285307 {& apiextensionsv1.CustomResourceDefinition {}, notNamespaced },
308+ {& appsv1.Deployment {}, r .ManagedNamespace },
309+ {& corev1.ConfigMap {}, r .ManagedNamespace },
310+ {& corev1.Service {}, r .ManagedNamespace },
286311 {& corev1.ServiceAccount {}, r .ManagedNamespace },
287- {& rbacv1.ClusterRoleBinding {}, notNamespaced },
288312 {& rbacv1.ClusterRole {}, notNamespaced },
313+ {& rbacv1.ClusterRoleBinding {}, notNamespaced },
289314 {& rbacv1.Role {}, r .ManagedNamespace },
290315 {& rbacv1.RoleBinding {}, r .ManagedNamespace },
291316 }
292317
293- for _ , w := range watches {
294- build = build .Watches (
295- w .obj ,
296- handler .EnqueueRequestsFromMapFunc (toClusterOperator ),
297- builder .WithPredicates (
298- ownedPlatformLabelPredicate (w .namespace , r .Platform ),
299-
300- // We're only interested in changes which affect an object's spec
301- predicate.AnnotationChangedPredicate {},
302- predicate.LabelChangedPredicate {},
303- predicate.GenerationChangedPredicate {},
304- ),
305- )
318+ for _ , owned := range ownsTypes {
319+ predicates := []predicate.Predicate {
320+ // We're only interested in changes which affect an object's spec
321+ predicate.AnnotationChangedPredicate {},
322+ predicate.LabelChangedPredicate {},
323+ predicate.GenerationChangedPredicate {},
324+ }
325+
326+ if owned .namespace != notNamespaced {
327+ predicates = append (predicates , predicate .NewPredicateFuncs (func (obj client.Object ) bool {
328+ return obj .GetNamespace () == owned .namespace
329+ }))
330+ }
331+
332+ build = build .Owns (owned .obj , builder .WithPredicates (predicates ... ))
306333 }
307334
308335 if err := build .Complete (r ); err != nil {
0 commit comments