func()

in pkg/operator/rules.go [222:365]


func (r *rulesReconciler) ensureRuleConfigs(ctx context.Context, projectID, location, cluster string, compression monitoringv1.CompressionType) error {
	logger, _ := logr.FromContext(ctx)

	// Re-generate the configmap that's loaded by the rule-evaluator.
	cm := &corev1.ConfigMap{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: r.opts.OperatorNamespace,
			Name:      nameRulesGenerated,
			Labels: map[string]string{
				LabelAppName: NameRuleEvaluator,
			},
		},
		// Ensure there's always at least an empty, uncompressed dummy file as the evaluator
		// expects at least one match.
		Data: map[string]string{
			"empty.yaml": "",
		},
	}

	// Generate a final rule file for each Rules resource.
	//
	// Depending on the scope level (global, cluster, namespace) the rules will be generated
	// so that queries are constrained to the appropriate project_id, cluster, and namespace
	// labels and that they are preserved through query aggregations and appear on the
	// output data.
	//
	// The location is not scoped as it's not a meaningful boundary for "human access"
	// to data as clusters may span locations.
	var rulesList monitoringv1.RulesList
	if err := r.client.List(ctx, &rulesList); err != nil {
		return fmt.Errorf("list rules: %w", err)
	}

	now := metav1.Now()
	conditionSuccess := &monitoringv1.MonitoringCondition{
		Type:   monitoringv1.ConfigurationCreateSuccess,
		Status: corev1.ConditionTrue,
	}
	var statusUpdates []monitoringv1.MonitoringCRD

	for i := range rulesList.Items {
		rs := &rulesList.Items[i]
		result, err := rs.RuleGroupsConfig(projectID, location, cluster)
		if err != nil {
			msg := "generating rule config failed"
			if rs.Status.SetMonitoringCondition(rs.GetGeneration(), now, &monitoringv1.MonitoringCondition{
				Type:    monitoringv1.ConfigurationCreateSuccess,
				Status:  corev1.ConditionFalse,
				Message: msg,
				Reason:  err.Error(),
			}) {
				statusUpdates = append(statusUpdates, rs)
			}
			logger.Error(err, "convert rules", "err", err, "namespace", rs.Namespace, "name", rs.Name)
			continue
		}
		filename := fmt.Sprintf("rules__%s__%s.yaml", rs.Namespace, rs.Name)
		if err := setConfigMapData(cm, compression, filename, result); err != nil {
			return err
		}

		if rs.Status.SetMonitoringCondition(rs.GetGeneration(), now, conditionSuccess) {
			statusUpdates = append(statusUpdates, rs)
		}
	}

	var clusterRulesList monitoringv1.ClusterRulesList
	if err := r.client.List(ctx, &clusterRulesList); err != nil {
		return fmt.Errorf("list cluster rules: %w", err)
	}
	for i := range clusterRulesList.Items {
		rs := &clusterRulesList.Items[i]
		result, err := rs.RuleGroupsConfig(projectID, location, cluster)
		if err != nil {
			msg := "generating rule config failed"
			if rs.Status.SetMonitoringCondition(rs.Generation, now, &monitoringv1.MonitoringCondition{
				Type:    monitoringv1.ConfigurationCreateSuccess,
				Status:  corev1.ConditionFalse,
				Message: msg,
				Reason:  err.Error(),
			}) {
				statusUpdates = append(statusUpdates, rs)
			}
			logger.Error(err, "convert rules", "err", err, "namespace", rs.Namespace, "name", rs.Name)
			continue
		}
		filename := fmt.Sprintf("clusterrules__%s.yaml", rs.Name)
		if err := setConfigMapData(cm, compression, filename, result); err != nil {
			return err
		}

		if rs.Status.SetMonitoringCondition(rs.GetGeneration(), now, conditionSuccess) {
			statusUpdates = append(statusUpdates, rs)
		}
	}

	var globalRulesList monitoringv1.GlobalRulesList
	if err := r.client.List(ctx, &globalRulesList); err != nil {
		return fmt.Errorf("list global rules: %w", err)
	}
	for i := range globalRulesList.Items {
		rs := &globalRulesList.Items[i]
		result, err := rs.RuleGroupsConfig()
		if err != nil {
			msg := "generating rule config failed"
			if rs.Status.SetMonitoringCondition(rs.Generation, now, &monitoringv1.MonitoringCondition{
				Type:    monitoringv1.ConfigurationCreateSuccess,
				Status:  corev1.ConditionFalse,
				Message: msg,
				Reason:  err.Error(),
			}) {
				statusUpdates = append(statusUpdates, rs)
			}
			logger.Error(err, "convert rules", "err", err, "namespace", rs.Namespace, "name", rs.Name)
			continue
		}
		filename := fmt.Sprintf("globalrules__%s.yaml", rs.Name)
		if err := setConfigMapData(cm, compression, filename, result); err != nil {
			return err
		}

		if rs.Status.SetMonitoringCondition(rs.GetGeneration(), now, conditionSuccess) {
			statusUpdates = append(statusUpdates, rs)
		}
	}

	// Create or update generated rule ConfigMap.
	if err := r.client.Update(ctx, cm); apierrors.IsNotFound(err) {
		if err := r.client.Create(ctx, cm); err != nil {
			return fmt.Errorf("create generated rules: %w", err)
		}
	} else if err != nil {
		return fmt.Errorf("update generated rules: %w", err)
	}

	var errs []error
	for _, obj := range statusUpdates {
		if err := patchMonitoringStatus(ctx, r.client, obj, obj.GetMonitoringStatus()); err != nil {
			errs = append(errs, err)
		}
	}

	return errors.Join(errs...)
}