github.com/argoproj-labs/argocd-operator@v0.10.0/controllers/argocd/prometheus_test.go (about) 1 package argocd 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 8 monitoringv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1" 9 "github.com/stretchr/testify/assert" 10 "k8s.io/apimachinery/pkg/runtime" 11 "k8s.io/apimachinery/pkg/types" 12 "k8s.io/apimachinery/pkg/util/intstr" 13 "sigs.k8s.io/controller-runtime/pkg/client" 14 15 argoproj "github.com/argoproj-labs/argocd-operator/api/v1beta1" 16 ) 17 18 func TestReconcileWorkloadStatusAlertRule(t *testing.T) { 19 tests := []struct { 20 name string 21 argocd *argoproj.ArgoCD 22 wantPromRuleFound bool 23 existingPromRule bool 24 }{ 25 { 26 name: "monitoring enabled, no existing prom rule", 27 argocd: makeTestArgoCD(func(cr *argoproj.ArgoCD) { 28 cr.Spec.Monitoring.Enabled = true 29 }), 30 existingPromRule: false, 31 wantPromRuleFound: true, 32 }, 33 { 34 name: "monitoring disabled, no existing prom rule", 35 argocd: makeTestArgoCD(func(cr *argoproj.ArgoCD) { 36 cr.Spec.Monitoring.Enabled = false 37 }), 38 existingPromRule: false, 39 wantPromRuleFound: false, 40 }, 41 { 42 name: "monitoring enabled, existing prom rule", 43 argocd: makeTestArgoCD(func(cr *argoproj.ArgoCD) { 44 cr.Spec.Monitoring.Enabled = true 45 }), 46 existingPromRule: true, 47 wantPromRuleFound: true, 48 }, 49 { 50 name: "monitoring disabled, existing prom rule", 51 argocd: makeTestArgoCD(func(cr *argoproj.ArgoCD) { 52 cr.Spec.Monitoring.Enabled = false 53 }), 54 existingPromRule: true, 55 wantPromRuleFound: false, 56 }, 57 } 58 59 for _, test := range tests { 60 t.Run(test.name, func(t *testing.T) { 61 62 desiredRuleGroup := []monitoringv1.RuleGroup{ 63 { 64 Name: "ArgoCDComponentStatus", 65 Rules: []monitoringv1.Rule{ 66 { 67 Alert: "ApplicationControllerNotReady", 68 Annotations: map[string]string{ 69 "message": fmt.Sprintf("application controller deployment for Argo CD instance in namespace %s is not running", test.argocd.Namespace), 70 }, 71 Expr: intstr.IntOrString{ 72 Type: intstr.String, 73 StrVal: fmt.Sprintf("kube_statefulset_status_replicas{statefulset=\"%s\", namespace=\"%s\"} != kube_statefulset_status_replicas_ready{statefulset=\"%s\", namespace=\"%s\"} ", fmt.Sprintf(test.argocd.Name+"-application-controller"), test.argocd.Namespace, fmt.Sprintf(test.argocd.Name+"-application-controller"), test.argocd.Namespace), 74 }, 75 For: "1m", 76 Labels: map[string]string{ 77 "severity": "critical", 78 }, 79 }, 80 { 81 Alert: "ServerNotReady", 82 Annotations: map[string]string{ 83 "message": fmt.Sprintf("server deployment for Argo CD instance in namespace %s is not running", test.argocd.Namespace), 84 }, 85 Expr: intstr.IntOrString{ 86 Type: intstr.String, 87 StrVal: fmt.Sprintf("kube_deployment_status_replicas{deployment=\"%s\", namespace=\"%s\"} != kube_deployment_status_replicas_ready{deployment=\"%s\", namespace=\"%s\"} ", fmt.Sprintf(test.argocd.Name+"-server"), test.argocd.Namespace, fmt.Sprintf(test.argocd.Name+"-server"), test.argocd.Namespace), 88 }, 89 For: "1m", 90 Labels: map[string]string{ 91 "severity": "critical", 92 }, 93 }, 94 { 95 Alert: "RepoServerNotReady", 96 Annotations: map[string]string{ 97 "message": fmt.Sprintf("repo server deployment for Argo CD instance in namespace %s is not running", test.argocd.Namespace), 98 }, 99 Expr: intstr.IntOrString{ 100 Type: intstr.String, 101 StrVal: fmt.Sprintf("kube_deployment_status_replicas{deployment=\"%s\", namespace=\"%s\"} != kube_deployment_status_replicas_ready{deployment=\"%s\", namespace=\"%s\"} ", fmt.Sprintf(test.argocd.Name+"-repo-server"), test.argocd.Namespace, fmt.Sprintf(test.argocd.Name+"-repo-server"), test.argocd.Namespace), 102 }, 103 For: "1m", 104 Labels: map[string]string{ 105 "severity": "critical", 106 }, 107 }, 108 { 109 Alert: "ApplicationSetControllerNotReady", 110 Annotations: map[string]string{ 111 "message": fmt.Sprintf("applicationSet controller deployment for Argo CD instance in namespace %s is not running", test.argocd.Namespace), 112 }, 113 Expr: intstr.IntOrString{ 114 Type: intstr.String, 115 StrVal: fmt.Sprintf("kube_deployment_status_replicas{deployment=\"%s\", namespace=\"%s\"} != kube_deployment_status_replicas_ready{deployment=\"%s\", namespace=\"%s\"} ", fmt.Sprintf(test.argocd.Name+"-applicationset-controller"), test.argocd.Namespace, fmt.Sprintf(test.argocd.Name+"-applicationset-controller"), test.argocd.Namespace), 116 }, 117 For: "5m", 118 Labels: map[string]string{ 119 "severity": "warning", 120 }, 121 }, 122 { 123 Alert: "DexNotReady", 124 Annotations: map[string]string{ 125 "message": fmt.Sprintf("dex deployment for Argo CD instance in namespace %s is not running", test.argocd.Namespace), 126 }, 127 Expr: intstr.IntOrString{ 128 Type: intstr.String, 129 StrVal: fmt.Sprintf("kube_deployment_status_replicas{deployment=\"%s\", namespace=\"%s\"} != kube_deployment_status_replicas_ready{deployment=\"%s\", namespace=\"%s\"} ", fmt.Sprintf(test.argocd.Name+"-dex-server"), test.argocd.Namespace, fmt.Sprintf(test.argocd.Name+"-dex-server"), test.argocd.Namespace), 130 }, 131 For: "5m", 132 Labels: map[string]string{ 133 "severity": "warning", 134 }, 135 }, 136 { 137 Alert: "NotificationsControllerNotReady", 138 Annotations: map[string]string{ 139 "message": fmt.Sprintf("notifications controller deployment for Argo CD instance in namespace %s is not running", test.argocd.Namespace), 140 }, 141 Expr: intstr.IntOrString{ 142 Type: intstr.String, 143 StrVal: fmt.Sprintf("kube_deployment_status_replicas{deployment=\"%s\", namespace=\"%s\"} != kube_deployment_status_replicas_ready{deployment=\"%s\", namespace=\"%s\"} ", fmt.Sprintf(test.argocd.Name+"-notifications-controller"), test.argocd.Namespace, fmt.Sprintf(test.argocd.Name+"-notifications-controller"), test.argocd.Namespace), 144 }, 145 For: "5m", 146 Labels: map[string]string{ 147 "severity": "warning", 148 }, 149 }, 150 { 151 Alert: "RedisNotReady", 152 Annotations: map[string]string{ 153 "message": fmt.Sprintf("redis deployment for Argo CD instance in namespace %s is not running", test.argocd.Namespace), 154 }, 155 Expr: intstr.IntOrString{ 156 Type: intstr.String, 157 StrVal: fmt.Sprintf("kube_deployment_status_replicas{deployment=\"%s\", namespace=\"%s\"} != kube_deployment_status_replicas_ready{deployment=\"%s\", namespace=\"%s\"} ", fmt.Sprintf(test.argocd.Name+"-redis"), test.argocd.Namespace, fmt.Sprintf(test.argocd.Name+"-redis"), test.argocd.Namespace), 158 }, 159 For: "5m", 160 Labels: map[string]string{ 161 "severity": "warning", 162 }, 163 }, 164 }, 165 }, 166 } 167 168 resObjs := []client.Object{test.argocd} 169 subresObjs := []client.Object{test.argocd} 170 runtimeObjs := []runtime.Object{} 171 sch := makeTestReconcilerScheme(argoproj.AddToScheme) 172 cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs) 173 r := makeTestReconciler(cl, sch) 174 175 err := monitoringv1.AddToScheme(r.Scheme) 176 assert.NoError(t, err) 177 178 if test.existingPromRule { 179 r.Client.Create(context.TODO(), newPrometheusRule(test.argocd.Namespace, "argocd-component-status-alert")) 180 } 181 182 err = r.reconcilePrometheusRule(test.argocd) 183 184 // reconciler doesn't need to do anything and should return nil 185 if (test.existingPromRule && test.wantPromRuleFound) || (!test.existingPromRule && !test.wantPromRuleFound) { 186 if err != nil { 187 t.Fatal("expected nil response but got non-nil response") 188 } 189 } else { 190 // reconciler either needs to create rule or delete it 191 testRule := &monitoringv1.PrometheusRule{} 192 err = r.Client.Get(context.TODO(), types.NamespacedName{ 193 Name: "argocd-component-status-alert", 194 Namespace: test.argocd.Namespace, 195 }, testRule) 196 197 if test.wantPromRuleFound && err != nil { 198 t.Fatal("unexpected error - prometheusRule not found") 199 } else if !test.wantPromRuleFound && err == nil { 200 t.Fatal("expected error but did not get one - prometheusRule not deleted") 201 } 202 203 if !test.existingPromRule { 204 assert.Equal(t, desiredRuleGroup, testRule.Spec.Groups) 205 } 206 207 } 208 }) 209 } 210 }