github.com/verrazzano/verrazzano@v1.7.0/platform-operator/controllers/configmaps/overrides/controller.go (about) 1 // Copyright (c) 2022, 2023, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package overrides 5 6 import ( 7 "context" 8 "github.com/verrazzano/verrazzano/platform-operator/constants" 9 vzstatus "github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/healthcheck" 10 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 11 "time" 12 13 corev1 "k8s.io/api/core/v1" 14 "k8s.io/apimachinery/pkg/api/errors" 15 "k8s.io/apimachinery/pkg/runtime" 16 ctrl "sigs.k8s.io/controller-runtime" 17 "sigs.k8s.io/controller-runtime/pkg/client" 18 "sigs.k8s.io/controller-runtime/pkg/reconcile" 19 20 vzctrl "github.com/verrazzano/verrazzano/pkg/controller" 21 "github.com/verrazzano/verrazzano/pkg/log/vzlog" 22 installv1alpha1 "github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1alpha1" 23 "github.com/verrazzano/verrazzano/platform-operator/controllers" 24 "github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/component/spi" 25 26 "go.uber.org/zap" 27 ) 28 29 // OverridesConfigMapsReconciler reconciles ConfigMaps. 30 // This controller manages install override sources from the Verrazzano CR 31 type OverridesConfigMapsReconciler struct { 32 client.Client 33 Scheme *runtime.Scheme 34 log vzlog.VerrazzanoLogger 35 StatusUpdater vzstatus.Updater 36 } 37 38 // SetupWithManager creates a new controller and adds it to the manager 39 func (r *OverridesConfigMapsReconciler) SetupWithManager(mgr ctrl.Manager) error { 40 return ctrl.NewControllerManagedBy(mgr). 41 For(&corev1.ConfigMap{}). 42 Complete(r) 43 } 44 45 // Reconcile the ConfigMap 46 func (r *OverridesConfigMapsReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 47 48 if ctx == nil { 49 ctx = context.TODO() 50 } 51 52 // Get Verrazzano from the cluster 53 vzList := &installv1alpha1.VerrazzanoList{} 54 err := r.List(ctx, vzList) 55 if err != nil { 56 if errors.IsNotFound(err) { 57 return reconcile.Result{}, nil 58 } 59 zap.S().Errorf("Failed to fetch Verrazzano resource: %v", err) 60 return newRequeueWithDelay(), err 61 } 62 63 if vzList != nil && len(vzList.Items) > 0 { 64 vz := &vzList.Items[0] 65 res, err := r.reconcileInstallOverrideConfigMap(ctx, req, vz) 66 if err != nil { 67 zap.S().Errorf("Failed to reconcile ConfigMap: %v", err) 68 return newRequeueWithDelay(), err 69 } 70 return res, nil 71 } 72 return ctrl.Result{}, nil 73 } 74 75 // reconcileInstallOverrideConfigMap looks through the Verrazzano CR for the ConfigMap 76 // if the request is from the same namespace as the CR 77 func (r *OverridesConfigMapsReconciler) reconcileInstallOverrideConfigMap(ctx context.Context, req ctrl.Request, vz *installv1alpha1.Verrazzano) (ctrl.Result, error) { 78 79 // Get the ConfigMap present in the Verrazzano CR namespace 80 configMap := &corev1.ConfigMap{} 81 var currentCondition installv1alpha1.ConditionType 82 if len(vz.Status.Conditions) > 0 { 83 currentCondition = vz.Status.Conditions[len(vz.Status.Conditions)-1].Type 84 } 85 86 if currentCondition == installv1alpha1.CondInstallComplete || currentCondition == installv1alpha1.CondUpgradeComplete { 87 if err := controllers.CreateOrUpdateEffectiveConfigCM(ctx, r.Client, vz); err != nil { 88 return newRequeueWithDelay(), nil 89 } 90 } 91 92 if vz.Namespace == req.Namespace { 93 if err := r.Get(ctx, req.NamespacedName, configMap); err != nil { 94 // Do not reconcile if the ConfigMap was deleted 95 if errors.IsNotFound(err) { 96 if err := controllers.ProcDeletedOverride(r.StatusUpdater, r.Client, vz, req.Name, constants.ConfigMapKind); err != nil { 97 // Do not return an error as it's most likely due to timing 98 return newRequeueWithDelay(), nil 99 } 100 return reconcile.Result{}, nil 101 } 102 zap.S().Errorf("Failed to fetch ConfigMap in Verrazzano CR namespace: %v", err) 103 return newRequeueWithDelay(), err 104 } 105 106 if result, err := r.initLogger(*configMap); err != nil { 107 return result, err 108 } 109 110 componentCtx, err := spi.NewContext(r.log, r.Client, vz, nil, false) 111 if err != nil { 112 r.log.Errorf("Failed to construct component context: %v", err) 113 return newRequeueWithDelay(), err 114 } 115 116 // Check if the ConfigMap is listed as an override source under a component 117 if componentName, ok := controllers.VzContainsResource(componentCtx, configMap.Name, configMap.Kind); ok { 118 if configMap.DeletionTimestamp.IsZero() { 119 // Check if our finalizer is already present 120 if !controllerutil.ContainsFinalizer(configMap, constants.OverridesFinalizer) { 121 configMap.Finalizers = append(configMap.Finalizers, constants.OverridesFinalizer) 122 err := r.Update(context.TODO(), configMap) 123 if err != nil { 124 return newRequeueWithDelay(), err 125 } 126 return reconcile.Result{Requeue: true}, nil 127 } 128 } else { 129 // Requeue if other finalizers are present 130 if configMap.Finalizers != nil && !controllerutil.ContainsFinalizer(configMap, constants.OverridesFinalizer) { 131 return reconcile.Result{Requeue: true}, nil 132 } 133 134 // Now since only our finalizer is present, therefore we remove it to delete the ConfigMap 135 // and trigger verrazzano reconcile 136 controllerutil.RemoveFinalizer(configMap, constants.OverridesFinalizer) 137 err := r.Update(context.TODO(), configMap) 138 if err != nil { 139 return newRequeueWithDelay(), err 140 } 141 } 142 143 err := controllers.UpdateVerrazzanoForInstallOverrides(r.StatusUpdater, componentCtx, componentName) 144 if err != nil { 145 r.log.ErrorfThrottled("Failed to reconcile ConfigMap: %v", err) 146 return newRequeueWithDelay(), err 147 } 148 r.log.Infof("Updated Verrazzano Resource") 149 } 150 } 151 return ctrl.Result{}, nil 152 } 153 154 // initialize logger for ConfigMap 155 func (r *OverridesConfigMapsReconciler) initLogger(cm corev1.ConfigMap) (ctrl.Result, error) { 156 // Get the resource logger needed to log message using 'progress' and 'once' methods 157 log, err := vzlog.EnsureResourceLogger(&vzlog.ResourceConfig{ 158 Name: cm.Name, 159 Namespace: cm.Namespace, 160 ID: string(cm.UID), 161 Generation: cm.Generation, 162 ControllerName: "ConfigMaps", 163 }) 164 if err != nil { 165 zap.S().Errorf("Failed to create resource logger for VerrazzanoConfigMap controller: %v", err) 166 return newRequeueWithDelay(), err 167 } 168 r.log = log 169 return ctrl.Result{}, nil 170 } 171 172 // Create a new Result that will cause a reconcile requeue after a short delay 173 func newRequeueWithDelay() ctrl.Result { 174 return vzctrl.NewRequeueWithDelay(3, 5, time.Second) 175 }