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  }