diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml index 215d3d80..6cdb59bd 100644 --- a/config/rbac/kustomization.yaml +++ b/config/rbac/kustomization.yaml @@ -11,10 +11,10 @@ resources: # Comment the following 4 lines if you want to disable # the auth proxy (https://github.com/brancz/kube-rbac-proxy) # which protects your /metrics endpoint. -# - auth_proxy_service.yaml -# - auth_proxy_role.yaml -# - auth_proxy_role_binding.yaml -# - auth_proxy_client_clusterrole.yaml +- auth_proxy_service.yaml +- auth_proxy_role.yaml +- auth_proxy_role_binding.yaml +- auth_proxy_client_clusterrole.yaml # For each CRD, "Editor" and "Viewer" roles are scaffolded by # default, aiding admins in cluster management. Those roles are # not used by the Project itself. You can comment the following lines diff --git a/controllers/clusterprofile_controller.go b/controllers/clusterprofile_controller.go index 0dea5dc5..262babe1 100644 --- a/controllers/clusterprofile_controller.go +++ b/controllers/clusterprofile_controller.go @@ -196,7 +196,10 @@ func (r *ClusterProfileReconciler) reconcileNormal( depClusters := depManager.GetClusterDeployments(profileRef) matchingCluster = append(matchingCluster, depClusters...) - profileScope.SetMatchingClusterRefs(removeDuplicates(matchingCluster)) + matchingClusters := removeDuplicates(matchingCluster) + profileScope.SetMatchingClusterRefs(matchingClusters) + trackMatchingClusters(configv1beta1.ClusterProfileKind, "", profileScope.Profile.GetName(), + len(matchingClusters), logger) r.updateMaps(profileScope) diff --git a/controllers/clustersummary_deployer.go b/controllers/clustersummary_deployer.go index 3e801d02..b52d8485 100644 --- a/controllers/clustersummary_deployer.go +++ b/controllers/clustersummary_deployer.go @@ -887,17 +887,34 @@ func (r *ClusterSummaryReconciler) updateFeatureStatus(clusterSummaryScope *scop logger.V(logs.LogDebug).Info("updating clustersummary status") now := metav1.NewTime(time.Now()) + clusterSummary := clusterSummaryScope.ClusterSummary + profileKind, profileNamespace, profileName := getProfileLabels(clusterSummary, logger) + switch *status { case libsveltosv1beta1.FeatureStatusProvisioned: failed := false clusterSummaryScope.SetFeatureStatus(featureID, libsveltosv1beta1.FeatureStatusProvisioned, hash, &failed) clusterSummaryScope.SetFailureMessage(featureID, nil) clusterSummaryScope.SetLastAppliedTime(featureID, &now) + trackReconcileOutcome(clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, + string(featureID), clusterSummary.Spec.ClusterType, true, profileKind, profileNamespace, profileName, logger) + trackConsecutiveFailures(clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, + string(featureID), clusterSummary.Spec.ClusterType, r.getConsecutiveFailures(clusterSummaryScope, featureID), + profileKind, profileNamespace, profileName, logger) + trackLastSuccess(clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, + string(featureID), clusterSummary.Spec.ClusterType, now.Time, profileKind, profileNamespace, profileName, logger) case libsveltosv1beta1.FeatureStatusRemoved: failed := false clusterSummaryScope.SetFeatureStatus(featureID, libsveltosv1beta1.FeatureStatusRemoved, hash, &failed) clusterSummaryScope.SetFailureMessage(featureID, nil) clusterSummaryScope.SetLastAppliedTime(featureID, &now) + trackReconcileOutcome(clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, + string(featureID), clusterSummary.Spec.ClusterType, true, profileKind, profileNamespace, profileName, logger) + trackConsecutiveFailures(clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, + string(featureID), clusterSummary.Spec.ClusterType, r.getConsecutiveFailures(clusterSummaryScope, featureID), + profileKind, profileNamespace, profileName, logger) + trackLastSuccess(clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, + string(featureID), clusterSummary.Spec.ClusterType, now.Time, profileKind, profileNamespace, profileName, logger) case libsveltosv1beta1.FeatureStatusProvisioning: clusterSummaryScope.SetFeatureStatus(featureID, libsveltosv1beta1.FeatureStatusProvisioning, hash, nil) case libsveltosv1beta1.FeatureStatusAgentRemoving: @@ -912,6 +929,11 @@ func (r *ClusterSummaryReconciler) updateFeatureStatus(clusterSummaryScope *scop clusterSummaryScope.SetFailureMessage(featureID, &err) } clusterSummaryScope.SetLastAppliedTime(featureID, &now) + trackReconcileOutcome(clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, + string(featureID), clusterSummary.Spec.ClusterType, false, profileKind, profileNamespace, profileName, logger) + trackConsecutiveFailures(clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, + string(featureID), clusterSummary.Spec.ClusterType, r.getConsecutiveFailures(clusterSummaryScope, featureID), + profileKind, profileNamespace, profileName, logger) } } diff --git a/controllers/metrics.go b/controllers/metrics.go index c4d780dc..c298a6e4 100644 --- a/controllers/metrics.go +++ b/controllers/metrics.go @@ -14,161 +14,158 @@ limitations under the License. package controllers import ( - "errors" "fmt" - "strings" "time" "github.com/go-logr/logr" "github.com/prometheus/client_golang/prometheus" "sigs.k8s.io/controller-runtime/pkg/metrics" + configv1beta1 "github.com/projectsveltos/addon-controller/api/v1beta1" libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" logs "github.com/projectsveltos/libsveltos/lib/logsettings" ) const ( - metricProgramResourcesName = "program_resources_time_seconds" - metricProgramResourcesHelp = "Program Resources on a workload cluster duration distribution" - metricProgramChartsName = "program_charts_time_seconds" + // metricNamespace prefixes every custom metric in this file, purely to avoid name collisions with + // unrelated tools scraped by the same Prometheus instance. Deliberately a fixed literal, not derived + // from getSveltosNamespace() (the Kubernetes namespace this component happens to be deployed into, + // which is user-configurable per install): a metric name prefix should stay stable across every + // install so dashboards/alerts built against it work the same way everywhere, regardless of which + // Kubernetes namespace a given cluster chose to deploy addon-controller into. + metricNamespace = "projectsveltos" + metricClusterNameLabel = "cluster_name" metricClusterNamespaceLabel = "cluster_namespace" metricClusterTypeLabel = "cluster_type" metricFeatureLabel = "feature" + metricStatusLabel = "status" + metricProfileKindLabel = "profile_kind" + metricProfileNamespaceLabel = "profile_namespace" + metricProfileNameLabel = "profile_name" + + statusSuccess = "success" + statusFailure = "failure" ) var ( - programResourceDurationHistogram = prometheus.NewHistogram( - prometheus.HistogramOpts{ - Namespace: getSveltosNamespace(), - Name: metricProgramResourcesName, - Help: metricProgramResourcesHelp, - Buckets: []float64{0.5, 1, 1.5, 2, 3, 5, 10, 30, 60, 90, 120}, - }, - ) - - programChartDurationHistogram = prometheus.NewHistogram( + // reconcileDurationHistogram tracks how long it takes to program a feature (Resources, Helm, + // Kustomize) on a workload cluster. Labeled by cluster and feature so it can be filtered down to + // a single cluster, aggregated to a namespace, or averaged fleet-wide, and so each feature type + // is distinguishable rather than collapsed into a "resources vs everything else" split. + // + // Not labeled by profile: this is observed from programDuration, which is invoked as a + // libsveltos/lib/deployer.MetricHandler callback — a type shared with several other components + // (healthcheck-manager, classifier, event-manager, etc.). That callback only carries cluster + // identity and featureID, not the ClusterSummary/profile that requested the work, so adding a + // profile label here would require changing the shared MetricHandler signature across all of + // them. reconcileOutcomeCounter and driftCounter below get profile labels instead, since both + // are recorded from addon-controller-local code that already has the full ClusterSummary object. + reconcileDurationHistogram = prometheus.NewHistogramVec( prometheus.HistogramOpts{ - Namespace: getSveltosNamespace(), - Name: metricProgramChartsName, - Help: "Program Helm charts on a workload cluster duration distribution", - Buckets: []float64{0.5, 1, 1.5, 2, 3, 5, 10, 30, 60, 90, 120}, + Namespace: metricNamespace, + Name: "reconcile_duration_seconds", + Help: "Duration distribution of programming a feature (Resources, Helm, Kustomize) on a workload cluster", + Buckets: []float64{0.5, 1, 1.5, 2, 3, 5, 10, 30, 60, 90, 120, 180, 300, 600}, }, + []string{metricClusterTypeLabel, metricClusterNamespaceLabel, metricClusterNameLabel, metricFeatureLabel}, ) + // reconciliationCounter is not labeled by profile for the same reason as reconcileDurationHistogram + // above: it is incremented from the same shared MetricHandler callback. reconciliationCounter = prometheus.NewCounterVec( prometheus.CounterOpts{ - Namespace: getSveltosNamespace(), + Namespace: metricNamespace, Name: "reconcile_operations_total", Help: "Total number of reconcile operations for Helm, Resources, and Kustomization", }, []string{metricClusterTypeLabel, metricClusterNamespaceLabel, metricClusterNameLabel, metricFeatureLabel}, ) + // reconcileOutcomeCounter tracks terminal reconcile outcomes (success/failure), unlike + // reconciliationCounter above which counts every attempt regardless of outcome. Incremented from + // updateFeatureStatus, the one place that already knows whether a feature ended up Provisioned/Removed + // (success) or Failed/FailedNonRetriable (failure), and has the full ClusterSummary object needed + // to resolve the owning ClusterProfile/Profile. + reconcileOutcomeCounter = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: metricNamespace, + Name: "reconcile_outcome_total", + Help: "Total number of terminal reconcile outcomes for Helm, Resources, and Kustomization, by outcome", + }, + []string{metricClusterTypeLabel, metricClusterNamespaceLabel, metricClusterNameLabel, metricFeatureLabel, + metricStatusLabel, metricProfileKindLabel, metricProfileNamespaceLabel, metricProfileNameLabel}, + ) + driftCounter = prometheus.NewCounterVec( prometheus.CounterOpts{ - Namespace: getSveltosNamespace(), + Namespace: metricNamespace, Name: "total_drifts", Help: "Total number of drifts for a given cluster indexed via type, namespace/name and feature id", }, - []string{metricClusterTypeLabel, metricClusterNamespaceLabel, metricClusterNameLabel, metricFeatureLabel}, + []string{metricClusterTypeLabel, metricClusterNamespaceLabel, metricClusterNameLabel, metricFeatureLabel, + metricProfileKindLabel, metricProfileNamespaceLabel, metricProfileNameLabel}, ) -) - -//nolint:gochecknoinits // forced pattern, can't workaround -func init() { - // Register custom metrics with the global prometheus registry - metrics.Registry.MustRegister(programResourceDurationHistogram, programChartDurationHistogram, reconciliationCounter, driftCounter) -} - -func newResourceHistogram(clusterNamespace, clusterName string, clusterType libsveltosv1beta1.ClusterType, - logger logr.Logger) prometheus.Histogram { - clusterInfo := strings.ReplaceAll(fmt.Sprintf("%s_%s_%s", clusterType, clusterNamespace, clusterName), "-", "_") - histogram := prometheus.NewHistogram( - prometheus.HistogramOpts{ - Namespace: clusterInfo, - Name: metricProgramResourcesName, - Help: metricProgramResourcesHelp, - Buckets: []float64{0.5, 1, 1.5, 2, 3, 5, 10, 30, 60, 90, 120}, + // matchingClustersGauge tracks how many clusters currently match a given ClusterProfile/Profile's + // selector. Set from ClusterProfileReconciler/ProfileReconciler right after they compute the + // matching set, independent of any per-cluster reconcile activity. + matchingClustersGauge = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: metricNamespace, + Name: "matching_clusters", + Help: "Number of clusters currently matching a ClusterProfile/Profile's selector", }, + []string{metricProfileKindLabel, metricProfileNamespaceLabel, metricProfileNameLabel}, ) - err := metrics.Registry.Register(histogram) - if err != nil { - var registrationError *prometheus.AlreadyRegisteredError - ok := errors.As(err, ®istrationError) - if ok { - _, ok = registrationError.ExistingCollector.(prometheus.Histogram) - if ok { - return registrationError.ExistingCollector.(prometheus.Histogram) - } - logCollectorError(err, logger) - return nil - } - logCollectorError(err, logger) - return nil - } - - return histogram -} - -func newChartHistogram(clusterNamespace, clusterName string, clusterType libsveltosv1beta1.ClusterType, - logger logr.Logger) prometheus.Histogram { - - clusterInfo := strings.ReplaceAll(fmt.Sprintf("%s_%s_%s", clusterType, clusterNamespace, clusterName), "-", "_") - histogram := prometheus.NewHistogram( - prometheus.HistogramOpts{ - Namespace: clusterInfo, - Name: metricProgramChartsName, - Help: "Program Helm Charts on a workload cluster duration distribution", - Buckets: []float64{0.5, 1, 1.5, 2, 3, 5, 10, 30, 60, 90, 120}, + // reconcileConsecutiveFailuresGauge mirrors ClusterSummary.status.featureSummaries[].consecutiveFailures. + // A gauge, not a counter: it resets to 0 on the next success, so it answers "is this stuck failing right + // now" directly, unlike reconcileOutcomeCounter which only accumulates and never reflects recovery. + reconcileConsecutiveFailuresGauge = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: metricNamespace, + Name: "reconcile_consecutive_failures", + Help: "Number of consecutive terminal failures for a feature on a cluster; reset to 0 on success", }, + []string{metricClusterTypeLabel, metricClusterNamespaceLabel, metricClusterNameLabel, metricFeatureLabel, + metricProfileKindLabel, metricProfileNamespaceLabel, metricProfileNameLabel}, ) - err := metrics.Registry.Register(histogram) - if err != nil { - var registrationError *prometheus.AlreadyRegisteredError - ok := errors.As(err, ®istrationError) - if ok { - _, ok = registrationError.ExistingCollector.(prometheus.Histogram) - if ok { - return registrationError.ExistingCollector.(prometheus.Histogram) - } - logCollectorError(err, logger) - return nil - } - logCollectorError(err, logger) - return nil - } - - return histogram -} + // reconcileLastSuccessTimestampGauge records when a feature last reached a successful terminal state + // (Provisioned/Removed). Unlike reconcileConsecutiveFailuresGauge, this only ever moves forward on + // success and is left untouched on failure, so it answers "how long has it been since this last + // worked" even for something that fails intermittently rather than in a tight consecutive streak. + reconcileLastSuccessTimestampGauge = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: metricNamespace, + Name: "reconcile_last_success_timestamp_seconds", + Help: "Unix timestamp of the last successful (Provisioned/Removed) terminal outcome for a feature on a cluster", + }, + []string{metricClusterTypeLabel, metricClusterNamespaceLabel, metricClusterNameLabel, metricFeatureLabel, + metricProfileKindLabel, metricProfileNamespaceLabel, metricProfileNameLabel}, + ) +) -func logCollectorError(err error, logger logr.Logger) { - logger.V(logs.LogVerbose).Info(fmt.Sprintf("failed to register collector: %s", err)) +//nolint:gochecknoinits // forced pattern, can't workaround +func init() { + // Register custom metrics with the global prometheus registry + metrics.Registry.MustRegister(reconcileDurationHistogram, reconciliationCounter, reconcileOutcomeCounter, + driftCounter, matchingClustersGauge, reconcileConsecutiveFailuresGauge, reconcileLastSuccessTimestampGauge) } func programDuration(elapsed time.Duration, clusterNamespace, clusterName, featureID string, clusterType libsveltosv1beta1.ClusterType, logger logr.Logger) { - if featureID == string(libsveltosv1beta1.FeatureResources) { - programResourceDurationHistogram.Observe(elapsed.Seconds()) - clusterHistogram := newResourceHistogram(clusterNamespace, clusterName, clusterType, logger) - if clusterHistogram != nil { - logger.V(logs.LogVerbose).Info(fmt.Sprintf("register data for %s/%s %s", - clusterNamespace, clusterName, featureID)) - clusterHistogram.Observe(elapsed.Seconds()) - } - } else { - programChartDurationHistogram.Observe(elapsed.Seconds()) - clusterHistogram := newChartHistogram(clusterNamespace, clusterName, clusterType, logger) - if clusterHistogram != nil { - logger.V(logs.LogVerbose).Info(fmt.Sprintf("register data for %s/%s %s", - clusterNamespace, clusterName, featureID)) - clusterHistogram.Observe(elapsed.Seconds()) - } - } + reconcileDurationHistogram.With(prometheus.Labels{ + metricClusterTypeLabel: string(clusterType), + metricClusterNamespaceLabel: clusterNamespace, + metricClusterNameLabel: clusterName, + metricFeatureLabel: featureID, + }).Observe(elapsed.Seconds()) + + logger.V(logs.LogVerbose).Info(fmt.Sprintf("recorded duration for %s/%s %s: %s", + clusterNamespace, clusterName, featureID, elapsed)) } func programDeployMetrics(elapsed time.Duration, clusterNamespace, clusterName, featureID string, @@ -190,14 +187,115 @@ func trackReconciliation(clusterNamespace, clusterName, featureID string, cluste clusterType, clusterNamespace, clusterName, featureID)) } -func trackDrifts(clusterNamespace, clusterName, featureID, clusterType string, logger logr.Logger) { +// getProfileLabels resolves the ClusterProfile/Profile owning clusterSummary into the three profile +// labels shared by reconcileOutcomeCounter, driftCounter, and matchingClustersGauge. Returns empty +// strings if the owner can't be resolved (e.g. a transient state before OwnerReferences are set) rather +// than failing metric recording. +func getProfileLabels(clusterSummary *configv1beta1.ClusterSummary, logger logr.Logger) (profileKind, profileNamespace, profileName string) { + ref, err := configv1beta1.GetProfileOwnerReference(clusterSummary) + if err != nil { + logger.V(logs.LogVerbose).Info(fmt.Sprintf("failed to get profile owner reference: %s", err)) + return "", "", "" + } + + if ref.Kind == configv1beta1.ProfileKind { + // Profile is namespaced; an owner reference is always same-namespace as the owned object. + return ref.Kind, clusterSummary.Namespace, ref.Name + } + + return ref.Kind, "", ref.Name +} + +// trackReconcileOutcome records a terminal reconcile outcome for a feature. success is true for +// FeatureStatusProvisioned/FeatureStatusRemoved, false for FeatureStatusFailed/FeatureStatusFailedNonRetriable. +// Non-terminal statuses (Provisioning, Removing, AgentRemoving) must not call this. +func trackReconcileOutcome(clusterNamespace, clusterName, featureID string, clusterType libsveltosv1beta1.ClusterType, + success bool, profileKind, profileNamespace, profileName string, logger logr.Logger) { + + status := statusFailure + if success { + status = statusSuccess + } + + reconcileOutcomeCounter.With(prometheus.Labels{ + metricClusterTypeLabel: string(clusterType), + metricClusterNamespaceLabel: clusterNamespace, + metricClusterNameLabel: clusterName, + metricFeatureLabel: featureID, + metricStatusLabel: status, + metricProfileKindLabel: profileKind, + metricProfileNamespaceLabel: profileNamespace, + metricProfileNameLabel: profileName, + }).Inc() + + logger.V(logs.LogVerbose).Info(fmt.Sprintf("Tracking reconcile outcome for %s %s/%s %s: %s", + clusterType, clusterNamespace, clusterName, featureID, status)) +} + +func trackDrifts(clusterNamespace, clusterName, featureID, clusterType, profileKind, profileNamespace, profileName string, + logger logr.Logger) { + driftCounter.With(prometheus.Labels{ metricClusterTypeLabel: clusterType, metricClusterNamespaceLabel: clusterNamespace, metricClusterNameLabel: clusterName, metricFeatureLabel: featureID, + metricProfileKindLabel: profileKind, + metricProfileNamespaceLabel: profileNamespace, + metricProfileNameLabel: profileName, }).Inc() logger.V(logs.LogVerbose).Info(fmt.Sprintf("Tracking drifts for %s %s/%s %s", clusterType, clusterNamespace, clusterName, featureID)) } + +// trackMatchingClusters records how many clusters currently match a ClusterProfile/Profile's selector. +func trackMatchingClusters(profileKind, profileNamespace, profileName string, count int, logger logr.Logger) { + matchingClustersGauge.With(prometheus.Labels{ + metricProfileKindLabel: profileKind, + metricProfileNamespaceLabel: profileNamespace, + metricProfileNameLabel: profileName, + }).Set(float64(count)) + + logger.V(logs.LogVerbose).Info(fmt.Sprintf("Tracking matching clusters for %s %s/%s: %d", + profileKind, profileNamespace, profileName, count)) +} + +// trackConsecutiveFailures records the current consecutive-failure streak for a feature on a cluster, +// read from ClusterSummary.status.featureSummaries[].consecutiveFailures after SetFeatureStatus has +// updated it. Called on every terminal outcome (success resets it to 0, failure increments it). +func trackConsecutiveFailures(clusterNamespace, clusterName, featureID string, clusterType libsveltosv1beta1.ClusterType, + consecutiveFailures uint, profileKind, profileNamespace, profileName string, logger logr.Logger) { + + reconcileConsecutiveFailuresGauge.With(prometheus.Labels{ + metricClusterTypeLabel: string(clusterType), + metricClusterNamespaceLabel: clusterNamespace, + metricClusterNameLabel: clusterName, + metricFeatureLabel: featureID, + metricProfileKindLabel: profileKind, + metricProfileNamespaceLabel: profileNamespace, + metricProfileNameLabel: profileName, + }).Set(float64(consecutiveFailures)) + + logger.V(logs.LogVerbose).Info(fmt.Sprintf("Tracking consecutive failures for %s %s/%s %s: %d", + clusterType, clusterNamespace, clusterName, featureID, consecutiveFailures)) +} + +// trackLastSuccess records the timestamp of the most recent successful (Provisioned/Removed) terminal +// outcome for a feature on a cluster. Only called from the success branches of updateFeatureStatus. +func trackLastSuccess(clusterNamespace, clusterName, featureID string, clusterType libsveltosv1beta1.ClusterType, + timestamp time.Time, profileKind, profileNamespace, profileName string, logger logr.Logger) { + + reconcileLastSuccessTimestampGauge.With(prometheus.Labels{ + metricClusterTypeLabel: string(clusterType), + metricClusterNamespaceLabel: clusterNamespace, + metricClusterNameLabel: clusterName, + metricFeatureLabel: featureID, + metricProfileKindLabel: profileKind, + metricProfileNamespaceLabel: profileNamespace, + metricProfileNameLabel: profileName, + }).Set(float64(timestamp.Unix())) + + logger.V(logs.LogVerbose).Info(fmt.Sprintf("Tracking last success for %s %s/%s %s: %s", + clusterType, clusterNamespace, clusterName, featureID, timestamp)) +} diff --git a/controllers/profile_controller.go b/controllers/profile_controller.go index 5054748b..b604b7c9 100644 --- a/controllers/profile_controller.go +++ b/controllers/profile_controller.go @@ -226,7 +226,10 @@ func (r *ProfileReconciler) reconcileNormal( depClusters := depManager.GetClusterDeployments(profileRef) matchingCluster = append(matchingCluster, depClusters...) - profileScope.SetMatchingClusterRefs(removeDuplicates(matchingCluster)) + matchingClusters := removeDuplicates(matchingCluster) + profileScope.SetMatchingClusterRefs(matchingClusters) + trackMatchingClusters(configv1beta1.ProfileKind, profileScope.Profile.GetNamespace(), profileScope.Profile.GetName(), + len(matchingClusters), logger) r.updateMaps(profileScope) diff --git a/controllers/resourcesummary_collection.go b/controllers/resourcesummary_collection.go index ed53d9ef..afa2a58e 100644 --- a/controllers/resourcesummary_collection.go +++ b/controllers/resourcesummary_collection.go @@ -524,6 +524,7 @@ func processResourceSummary(ctx context.Context, clusterClient client.Client, } l := logger.WithValues("clusterSummary", clusterSummary.Name) + profileKind, profileNamespace, profileName := getProfileLabels(clusterSummary, l) for i := range clusterSummary.Status.FeatureSummaries { switch clusterSummary.Status.FeatureSummaries[i].FeatureID { case libsveltosv1beta1.FeatureHelm: @@ -532,7 +533,7 @@ func processResourceSummary(ctx context.Context, clusterClient client.Client, clusterSummary.Status.FeatureSummaries[i].Hash = nil clusterSummary.Status.FeatureSummaries[i].Status = libsveltosv1beta1.FeatureStatusProvisioning trackDrifts(clusterSummaryNamespace, clusterSummary.Spec.ClusterName, string(clusterSummary.Status.FeatureSummaries[i].FeatureID), - string(clusterSummary.Spec.ClusterType), logger) + string(clusterSummary.Spec.ClusterType), profileKind, profileNamespace, profileName, logger) } case libsveltosv1beta1.FeatureResources: if rs.Status.ResourcesChanged { @@ -540,7 +541,7 @@ func processResourceSummary(ctx context.Context, clusterClient client.Client, clusterSummary.Status.FeatureSummaries[i].Hash = nil clusterSummary.Status.FeatureSummaries[i].Status = libsveltosv1beta1.FeatureStatusProvisioning trackDrifts(clusterSummaryNamespace, clusterSummary.Spec.ClusterName, string(clusterSummary.Status.FeatureSummaries[i].FeatureID), - string(clusterSummary.Spec.ClusterType), logger) + string(clusterSummary.Spec.ClusterType), profileKind, profileNamespace, profileName, logger) } case libsveltosv1beta1.FeatureKustomize: if rs.Status.KustomizeResourcesChanged { @@ -548,7 +549,7 @@ func processResourceSummary(ctx context.Context, clusterClient client.Client, clusterSummary.Status.FeatureSummaries[i].Hash = nil clusterSummary.Status.FeatureSummaries[i].Status = libsveltosv1beta1.FeatureStatusProvisioning trackDrifts(clusterSummaryNamespace, clusterSummary.Spec.ClusterName, string(clusterSummary.Status.FeatureSummaries[i].FeatureID), - string(clusterSummary.Spec.ClusterType), logger) + string(clusterSummary.Spec.ClusterType), profileKind, profileNamespace, profileName, logger) } } } diff --git a/manifest/manifest.yaml b/manifest/manifest.yaml index 1d385215..e5dccb8b 100644 --- a/manifest/manifest.yaml +++ b/manifest/manifest.yaml @@ -10505,6 +10505,34 @@ metadata: name: addon-controller-role-extra --- apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: addon-metrics-reader +rules: +- nonResourceURLs: + - /metrics + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: addon-proxy-role +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: addon-controller-rolebinding-extra @@ -10544,6 +10572,19 @@ subjects: name: addon-controller namespace: projectsveltos --- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: addon-proxy-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: addon-proxy-role +subjects: +- kind: ServiceAccount + name: addon-controller + namespace: projectsveltos +--- apiVersion: v1 kind: Service metadata: @@ -10561,6 +10602,22 @@ spec: control-plane: addon-controller type: ClusterIP --- +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: addon-controller + name: addon-controller-metrics-service + namespace: projectsveltos +spec: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: https + selector: + control-plane: addon-controller +--- apiVersion: apps/v1 kind: Deployment metadata: