github.com/verrazzano/verrazzano@v1.7.1/application-operator/controllers/metricstrait/operator.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 metricstrait 5 6 import ( 7 "context" 8 9 promoperapi "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" 10 vzapi "github.com/verrazzano/verrazzano/application-operator/apis/oam/v1alpha1" 11 "github.com/verrazzano/verrazzano/application-operator/constants" 12 vznav "github.com/verrazzano/verrazzano/application-operator/controllers/navigation" 13 "github.com/verrazzano/verrazzano/application-operator/controllers/reconcileresults" 14 "github.com/verrazzano/verrazzano/pkg/log/vzlog" 15 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 16 ctrl "sigs.k8s.io/controller-runtime" 17 "sigs.k8s.io/controller-runtime/pkg/client" 18 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 19 "sigs.k8s.io/controller-runtime/pkg/reconcile" 20 ) 21 22 // doOperatorReconcile reconciles a metrics trait to work with the Prometheus Operator 23 // This reconciler will create a ServiceMonitor for each metrics trait application to hook up metrics with Prometheus 24 func (r *Reconciler) doOperatorReconcile(ctx context.Context, trait *vzapi.MetricsTrait, log vzlog.VerrazzanoLogger) (ctrl.Result, error) { 25 log.Debugf("Entering the Service Monitor reconcile process for trait: %s", trait.Name) 26 if trait.DeletionTimestamp.IsZero() { 27 return r.reconcileOperatorTraitCreateOrUpdate(ctx, trait, log) 28 } 29 return r.reconcileOperatorTraitDelete(ctx, trait, log) 30 } 31 32 func (r *Reconciler) reconcileOperatorTraitCreateOrUpdate(ctx context.Context, trait *vzapi.MetricsTrait, log vzlog.VerrazzanoLogger) (ctrl.Result, error) { 33 log.Debugf("Creating or Updating the Service Monitor from trait: %s", trait.Name) 34 var err error 35 // Add finalizer if required. 36 if err := r.addFinalizerIfRequired(ctx, trait, log); err != nil { 37 return reconcile.Result{}, err 38 } 39 40 // Fetch workload resource using information from the trait 41 var workload *unstructured.Unstructured 42 if workload, err = vznav.FetchWorkloadFromTrait(ctx, r, log, trait); err != nil || workload == nil { 43 return reconcile.Result{}, err 44 } 45 46 // Construct the trait defaults from the trait and the workload resources 47 traitDefaults, supported, err := r.fetchTraitDefaults(ctx, workload, log) 48 if err != nil { 49 return reconcile.Result{}, err 50 } 51 if !supported || traitDefaults == nil { 52 return reconcile.Result{Requeue: false}, nil 53 } 54 55 // If the user has specified a non-default (i.e. not the legacy Prometheus) scraper, then we have already updated the scrape config, 56 // so do not attempt to create/update a ServiceMonitor. 57 if !r.isLegacyPrometheusScraper(trait, traitDefaults) { 58 return reconcile.Result{}, nil 59 } 60 61 // Find the child resources of the workload based on the childResourceKinds from the 62 // workload definition, workload uid and the ownerReferences of the children. 63 var children []*unstructured.Unstructured 64 if children, err = vznav.FetchWorkloadChildren(ctx, r, log, workload); err != nil { 65 return reconcile.Result{}, err 66 } 67 68 // Create or update the related resources of the trait and collect the outcomes. 69 status := r.createOrUpdateRelatedWorkloads(ctx, trait, workload, traitDefaults, children, log) 70 71 var opResult controllerutil.OperationResult 72 var rel vzapi.QualifiedResourceRelation 73 // update the ServiceMonitor if trait is enabled, delete it if trait is disabled 74 if isEnabled(trait) { 75 rel, opResult, err = r.updateServiceMonitor(ctx, trait, workload, traitDefaults, log) 76 } else { 77 serviceMonitorName, err := createServiceMonitorName(trait, 0) 78 if err != nil { 79 return reconcile.Result{}, log.ErrorfNewErr("Failed to create Service Monitor name: %v", err) 80 } 81 opResult, err = r.deleteServiceMonitor(ctx, trait.Namespace, serviceMonitorName, trait, log) 82 if client.IgnoreNotFound(err) != nil { 83 return reconcile.Result{}, log.ErrorfNewErr("Failed to delete Service Monitor %s for disabled metrics trait: %v", serviceMonitorName, err) 84 } 85 rel = vzapi.QualifiedResourceRelation{APIVersion: promoperapi.SchemeGroupVersion.String(), Kind: promoperapi.ServiceMonitorsKind, Namespace: trait.Namespace, Name: serviceMonitorName, Role: scraperRole} 86 } 87 status.RecordOutcome(rel, opResult, err) 88 89 return r.updateTraitStatus(ctx, trait, status, log) 90 } 91 92 func (r *Reconciler) reconcileOperatorTraitDelete(ctx context.Context, trait *vzapi.MetricsTrait, log vzlog.VerrazzanoLogger) (ctrl.Result, error) { 93 log.Debugf("Deleting the Service Monitor from trait: %s", trait.Name) 94 status := r.deleteOrUpdateObsoleteResources(ctx, trait, &reconcileresults.ReconcileResults{}, log) 95 // Only remove the finalizer if all related resources were successfully updated. 96 if !status.ContainsErrors() { 97 if err := r.removeFinalizerIfRequired(ctx, trait, log); err != nil { 98 return reconcile.Result{}, err 99 } 100 } 101 return ctrl.Result{}, nil 102 } 103 104 // fetchTraitDefaults fetches metrics trait default values. 105 // These default values are workload type dependent. 106 func (r *Reconciler) fetchTraitDefaults(ctx context.Context, workload *unstructured.Unstructured, log vzlog.VerrazzanoLogger) (*vzapi.MetricsTraitSpec, bool, error) { 107 apiVerKind, err := vznav.GetAPIVersionKindOfUnstructured(workload) 108 if err != nil { 109 return nil, true, log.ErrorfNewErr("Failed to get the API version from the workload: %v", err) 110 } 111 112 workloadType := GetSupportedWorkloadType(apiVerKind) 113 switch workloadType { 114 case constants.WorkloadTypeWeblogic: 115 spec, err := r.NewTraitDefaultsForWLSDomainWorkload(ctx, workload) 116 return spec, true, err 117 case constants.WorkloadTypeCoherence: 118 spec, err := r.NewTraitDefaultsForCOHWorkload(ctx, workload) 119 return spec, true, err 120 case constants.WorkloadTypeGeneric: 121 spec, err := r.NewTraitDefaultsForGenericWorkload() 122 return spec, true, err 123 default: 124 // Log the kind/workload is unsupported and return a nil trait. 125 log.Debugf("unsupported kind %s of workload %s", apiVerKind, vznav.GetNamespacedNameFromUnstructured(workload)) 126 return nil, false, nil 127 } 128 129 }