github.com/verrazzano/verrazzano@v1.7.1/application-operator/controllers/metricsbinding/metricsbinding_delete.go (about)

     1  // Copyright (c) 2022, 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 metricsbinding
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	"github.com/Jeffail/gabs/v2"
    11  	vzapi "github.com/verrazzano/verrazzano/application-operator/apis/app/v1alpha1"
    12  	"github.com/verrazzano/verrazzano/pkg/log/vzlog"
    13  	"github.com/verrazzano/verrazzano/pkg/metricsutils"
    14  	k8scorev1 "k8s.io/api/core/v1"
    15  	k8scontroller "sigs.k8s.io/controller-runtime"
    16  	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
    17  	"sigs.k8s.io/yaml"
    18  )
    19  
    20  // reconcileBindingDelete completes the reconcile process for an object that is being deleted
    21  func (r *Reconciler) reconcileBindingDelete(ctx context.Context, metricsBinding *vzapi.MetricsBinding, log vzlog.VerrazzanoLogger) (k8scontroller.Result, error) {
    22  	log.Debugw("Reconcile for deleted object", "resource", metricsBinding.GetName())
    23  
    24  	// If a ConfigMap is populated, delete the existing scrape config from the ConfigMap
    25  	var configMap = getPromConfigMap(metricsBinding)
    26  	if configMap != nil {
    27  		log.Debugf("ConfigMap %s/%s found in the MetricsBinding, deleting scrape config", configMap.GetName(), configMap.GetNamespace())
    28  		if err := r.deleteFromPrometheusConfigMap(ctx, metricsBinding, configMap, log); err != nil {
    29  			return k8scontroller.Result{Requeue: true}, err
    30  		}
    31  	}
    32  	// If the Secret exists, delete the existing config from the Secret
    33  	secret, key := getPromConfigSecret(metricsBinding)
    34  	if secret != nil {
    35  		log.Debugf("Secret %s/%s found in the MetricsBinding, deleting scrape config", secret.GetName(), secret.GetNamespace())
    36  		if err := r.deleteFromPrometheusConfigSecret(ctx, metricsBinding, secret, key, log); err != nil {
    37  			return k8scontroller.Result{Requeue: true}, err
    38  		}
    39  	}
    40  
    41  	// Remove the finalizer if deletion was successful
    42  	_, err := controllerutil.CreateOrUpdate(ctx, r.Client, metricsBinding, func() error {
    43  		controllerutil.RemoveFinalizer(metricsBinding, finalizerName)
    44  		return nil
    45  	})
    46  	if err != nil {
    47  		return k8scontroller.Result{Requeue: true}, err
    48  	}
    49  
    50  	return k8scontroller.Result{}, nil
    51  }
    52  
    53  // deleteFromPrometheusConfigMap deletes the scrape config from the Prometheus ConfigMap
    54  func (r *Reconciler) deleteFromPrometheusConfigMap(ctx context.Context, metricsBinding *vzapi.MetricsBinding, configMap *k8scorev1.ConfigMap, log vzlog.VerrazzanoLogger) error {
    55  	log.Debugw("Prometheus target ConfigMap is being altered", "resource", configMap.GetName())
    56  	_, err := controllerutil.CreateOrUpdate(ctx, r.Client, configMap, func() error {
    57  		// Get data from the configmap
    58  		promConfig, err := getConfigData(configMap)
    59  		if err != nil {
    60  			return log.ErrorfNewErr("Failed to get Prometheus ConfigMap Data: %v", err)
    61  		}
    62  		// scrape configs would have been edited in-place, in the promConfig Container, so ignore
    63  		// that return value
    64  		_, err = r.deleteScrapeConfig(metricsBinding, promConfig, log, true)
    65  		if err != nil {
    66  			return log.ErrorfNewErr("Failed to delete scrape config from Prometheus ConfigMap: %v", err)
    67  		}
    68  		// scrape configs would have been edited in-place, in the promConfig Container, so serialize
    69  		// the whole thing for the new data.
    70  		newPromConfigData, err := yaml.JSONToYAML(promConfig.Bytes())
    71  		if err != nil {
    72  			return log.ErrorfNewErr("Failed to convert scrape config JSON to YAML: %v", err)
    73  		}
    74  		configMap.Data[prometheusConfigKey] = string(newPromConfigData)
    75  		return nil
    76  	})
    77  	return err
    78  }
    79  
    80  // deleteFromPrometheusConfigSecret deletes the scrape config from the Prometheus config Secret
    81  func (r *Reconciler) deleteFromPrometheusConfigSecret(ctx context.Context, metricsBinding *vzapi.MetricsBinding, secret *k8scorev1.Secret, key string, log vzlog.VerrazzanoLogger) error {
    82  	log.Debugw("Prometheus target config Secret is being altered", "resource", secret.GetName())
    83  	_, err := controllerutil.CreateOrUpdate(ctx, r.Client, secret, func() error {
    84  		scrapeConfigData, err := getConfigDataFromSecret(secret, key)
    85  		if err != nil {
    86  			return err
    87  		}
    88  		updatedScrapeConfigs, err := r.deleteScrapeConfig(metricsBinding, scrapeConfigData, log, false)
    89  		if err != nil {
    90  			return err
    91  		}
    92  		newPromConfigData, err := yaml.JSONToYAML(updatedScrapeConfigs.Bytes())
    93  		if err != nil {
    94  			return log.ErrorfNewErr("Failed to convert scrape config JSON to YAML: %v", err)
    95  		}
    96  		secret.Data[key] = newPromConfigData
    97  		return nil
    98  	})
    99  	return err
   100  }
   101  
   102  // deleteScrapeConfig is a mutation function that deletes the scrape config data from the Prometheus ConfigMap
   103  func (r *Reconciler) deleteScrapeConfig(metricsBinding *vzapi.MetricsBinding, configData *gabs.Container, log vzlog.VerrazzanoLogger, isPromConfigMap bool) (*gabs.Container, error) {
   104  	log.Debugw("Scrape Config is being deleted from the Prometheus Config", "resource", metricsBinding.GetName())
   105  
   106  	// Verify the Owner Reference exists
   107  	if len(metricsBinding.OwnerReferences) < 1 {
   108  		return nil, fmt.Errorf("Failed to find Owner Reference found in the MetricsBinding: %s", metricsBinding.GetName())
   109  	}
   110  
   111  	// Delete scrape config with job name matching resource
   112  	// parse the scrape config so we can manipulate it
   113  	jobNameToDelete := createJobName(metricsBinding)
   114  
   115  	var updatedConfigData *gabs.Container
   116  	var err error
   117  	if isPromConfigMap {
   118  		err = metricsutils.EditScrapeJobInPrometheusConfig(configData, prometheusScrapeConfigsLabel, jobNameToDelete, nil)
   119  		updatedConfigData = configData
   120  	} else {
   121  		updatedConfigData, err = metricsutils.EditScrapeJob(configData, jobNameToDelete, nil)
   122  	}
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  	return updatedConfigData, err
   127  }