github.com/verrazzano/verrazzano@v1.7.0/platform-operator/controllers/controller_utils.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 controllers 5 6 import ( 7 "context" 8 "fmt" 9 "github.com/verrazzano/verrazzano/pkg/log/vzlog" 10 installv1alpha1 "github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1alpha1" 11 "github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1beta1" 12 "github.com/verrazzano/verrazzano/platform-operator/constants" 13 "github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/component/registry" 14 "github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/component/spi" 15 vzstatus "github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/healthcheck" 16 "github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/transform" 17 corev1 "k8s.io/api/core/v1" 18 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 19 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 20 21 k8serrors "k8s.io/apimachinery/pkg/api/errors" 22 "sigs.k8s.io/controller-runtime/pkg/client" 23 "sigs.k8s.io/yaml" 24 ) 25 26 // Name of Effective Configmap Data Key 27 const effConfigKey = "effective-config.yaml" 28 29 // Suffix of the Name of the Configmap containing effective CR 30 const effConfigSuffix = "-effective-config" 31 32 // VzContainsResource checks to see if the resource is listed in the Verrazzano 33 func VzContainsResource(ctx spi.ComponentContext, objectName string, objectKind string) (string, bool) { 34 for _, component := range registry.GetComponents() { 35 if component.MonitorOverrides(ctx) { 36 if found := componentContainsResource(component.GetOverrides(ctx.EffectiveCR()).([]installv1alpha1.Overrides), objectName, objectKind); found { 37 return component.Name(), found 38 } 39 } 40 } 41 return "", false 42 } 43 44 // componentContainsResource looks through the component override list see if the resource is listed 45 func componentContainsResource(Overrides []installv1alpha1.Overrides, objectName string, objectKind string) bool { 46 for _, override := range Overrides { 47 if objectKind == constants.ConfigMapKind && override.ConfigMapRef != nil { 48 if objectName == override.ConfigMapRef.Name { 49 return true 50 } 51 } 52 if objectKind == constants.SecretKind && override.SecretRef != nil { 53 if objectName == override.SecretRef.Name { 54 return true 55 } 56 } 57 } 58 return false 59 } 60 61 // UpdateVerrazzanoForInstallOverrides mutates the status subresource of Verrazzano Custom Resource specific 62 // to a component to cause a reconcile 63 func UpdateVerrazzanoForInstallOverrides(statusUpdater vzstatus.Updater, componentCtx spi.ComponentContext, componentName string) error { 64 cr := componentCtx.ActualCR() 65 // Return an error to requeue if Verrazzano Component Status hasn't been initialized 66 if cr.Status.Components == nil { 67 return fmt.Errorf("Components not initialized") 68 } 69 // Set ReconcilingGeneration to 1 to re-enter install flow 70 details := cr.Status.Components[componentName].DeepCopy() 71 details.ReconcilingGeneration = 1 72 componentsToUpdate := map[string]*installv1alpha1.ComponentStatusDetails{ 73 componentName: details, 74 } 75 statusUpdater.Update(&vzstatus.UpdateEvent{ 76 Verrazzano: cr, 77 Components: componentsToUpdate, 78 }) 79 return nil 80 } 81 82 // ProcDeletedOverride checks Verrazzano CR for an override resource that has now been deleted, 83 // and updates the CR if the resource is found listed as an override 84 func ProcDeletedOverride(statusUpdater vzstatus.Updater, c client.Client, vz *installv1alpha1.Verrazzano, objectName string, objectKind string) error { 85 // DefaultLogger is used since we only need to create a component context and any actual logging isn't being performed 86 log := vzlog.DefaultLogger() 87 ctx, err := spi.NewContext(log, c, vz, nil, false) 88 if err != nil { 89 return err 90 } 91 92 compName, ok := VzContainsResource(ctx, objectName, objectKind) 93 if !ok { 94 return nil 95 } 96 97 if err := UpdateVerrazzanoForInstallOverrides(statusUpdater, ctx, compName); err != nil { 98 return err 99 } 100 return nil 101 } 102 103 // CreateOrUpdateEffectiveConfigCM takes in the Actual CR, retrieves the Effective CR, 104 // converts it into YAML and stores it in a configmap If no configmap exists, 105 // it will create one, otherwise it updates the configmap with the effective CR 106 func CreateOrUpdateEffectiveConfigCM(ctx context.Context, c client.Client, vz *installv1alpha1.Verrazzano) error { 107 108 //In the case of verrazzano uninstall,the reconciler re-creates the config map 109 //when the vz status is either uninstalling or uninstall completely then do not create anything 110 var currentCondition installv1alpha1.ConditionType 111 if len(vz.Status.Conditions) > 0 { 112 currentCondition = vz.Status.Conditions[len(vz.Status.Conditions)-1].Type 113 } 114 if currentCondition == installv1alpha1.CondUninstallComplete || currentCondition == installv1alpha1.CondUninstallStarted { 115 return nil 116 } 117 // Get the Effective CR from the Verrazzano CR supplied and convert it into v1beta1 118 v1beta1ActualCR := &v1beta1.Verrazzano{} 119 err := vz.ConvertTo(v1beta1ActualCR) 120 if err != nil { 121 return fmt.Errorf("failed Converting v1alpha1 Verrazzano to v1beta1: %v", err) 122 } 123 124 effCR, err := transform.GetEffectiveV1beta1CR(v1beta1ActualCR) 125 if err != nil { 126 return fmt.Errorf("failed retrieving the Effective CR: %v", err) 127 } 128 129 // Marshal Indent it to format the Effective CR Specs into YAML 130 effCRSpecs, err := yaml.Marshal(effCR.Spec) 131 if err != nil { 132 return fmt.Errorf("failed to convert effective CR into YAML: %v", err) 133 } 134 135 // Create a Configmap Object that stores the Effective CR Specs 136 effCRConfigmap := &corev1.ConfigMap{ 137 ObjectMeta: metav1.ObjectMeta{ 138 Name: (vz.ObjectMeta.Name + effConfigSuffix), 139 Namespace: (vz.ObjectMeta.Namespace), 140 }, 141 } 142 143 // Update the configMap if a ConfigMap already exists 144 // In case, there's no ConfigMap, the IsNotFound() func will return true and then it will create one. 145 _, err = controllerutil.CreateOrUpdate(ctx, c, effCRConfigmap, func() error { 146 147 effCRConfigmap.Data = map[string]string{effConfigKey: string(effCRSpecs)} 148 return nil 149 }) 150 if k8serrors.IsAlreadyExists(err) { 151 return nil 152 } 153 if err != nil { 154 return fmt.Errorf("failed to Create or Update the configmap: %v", err) 155 } 156 157 return nil 158 }