Skip to content

Commit 7565d9a

Browse files
authored
Use env RUNBOOK_URL_TEMPLATE for the runbooks URL template (#307)
Signed-off-by: assafad <[email protected]>
1 parent f4b9755 commit 7565d9a

File tree

3 files changed

+85
-14
lines changed

3 files changed

+85
-14
lines changed

pkg/controller/hostpathprovisioner/controller_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,13 +1097,16 @@ func verifyCreatePrometheusResources(cl client.Client) {
10971097
Expect(r.Annotations).To(BeNil())
10981098
}
10991099
}
1100+
1101+
runbookURLTemplate := getRunbookURLTemplate()
1102+
11001103
hppDownAlert := promv1.Rule{
11011104
Alert: "HPPOperatorDown",
11021105
Expr: intstr.FromString("kubevirt_hpp_operator_up_total == 0"),
11031106
For: "5m",
11041107
Annotations: map[string]string{
11051108
"summary": "Hostpath Provisioner operator is down",
1106-
"runbook_url": runbookURLBasePath + "HPPOperatorDown",
1109+
"runbook_url": fmt.Sprintf(runbookURLTemplate, "HPPOperatorDown"),
11071110
},
11081111
Labels: map[string]string{
11091112
"severity": "warning",

pkg/controller/hostpathprovisioner/prometheus.go

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ package hostpathprovisioner
1818

1919
import (
2020
"context"
21+
"errors"
2122
"fmt"
2223
"os"
2324
"reflect"
25+
"strings"
2426

2527
promv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
2628
"github.com/go-logr/logr"
@@ -29,7 +31,7 @@ import (
2931
"sigs.k8s.io/controller-runtime/pkg/client"
3032
"sigs.k8s.io/controller-runtime/pkg/reconcile"
3133

32-
"k8s.io/apimachinery/pkg/api/errors"
34+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
3335
"k8s.io/apimachinery/pkg/api/meta"
3436
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3537
"k8s.io/apimachinery/pkg/util/intstr"
@@ -41,7 +43,8 @@ const (
4143
rbacName = "hostpath-provisioner-monitoring"
4244
monitorName = "service-monitor-hpp"
4345
defaultMonitoringNs = "monitoring"
44-
runbookURLBasePath = "https://kubevirt.io/monitoring/runbooks/"
46+
defaultRunbookURLTemplate = "https://kubevirt.io/monitoring/runbooks/%s"
47+
runbookURLTemplateEnv = "RUNBOOK_URL_TEMPLATE"
4548
severityAlertLabelKey = "severity"
4649
healthImpactAlertLabelKey = "operator_health_impact"
4750
partOfAlertLabelKey = "kubernetes_operator_part_of"
@@ -76,7 +79,7 @@ func (r *ReconcileHostPathProvisioner) reconcilePrometheusResource(reqLogger log
7679
setLastAppliedConfiguration(desired)
7780
// Check if this PrometheusRule already exists
7881
err := r.client.Get(context.TODO(), client.ObjectKeyFromObject(found), found)
79-
if err != nil && errors.IsNotFound(err) {
82+
if err != nil && k8serrors.IsNotFound(err) {
8083
reqLogger.Info("Creating a new PrometheusResource", "Name", found.GetName())
8184
err = r.client.Create(context.TODO(), desired)
8285
if err != nil {
@@ -131,7 +134,7 @@ func (r *ReconcileHostPathProvisioner) deletePrometheusResources(namespace strin
131134
Namespace: namespace,
132135
},
133136
}
134-
if err := r.client.Delete(context.TODO(), rule); err != nil && !errors.IsNotFound(err) {
137+
if err := r.client.Delete(context.TODO(), rule); err != nil && !k8serrors.IsNotFound(err) {
135138
return err
136139
}
137140

@@ -141,7 +144,7 @@ func (r *ReconcileHostPathProvisioner) deletePrometheusResources(namespace strin
141144
Namespace: namespace,
142145
},
143146
}
144-
if err := r.client.Delete(context.TODO(), role); err != nil && !errors.IsNotFound(err) {
147+
if err := r.client.Delete(context.TODO(), role); err != nil && !k8serrors.IsNotFound(err) {
145148
return err
146149
}
147150

@@ -151,7 +154,7 @@ func (r *ReconcileHostPathProvisioner) deletePrometheusResources(namespace strin
151154
Namespace: namespace,
152155
},
153156
}
154-
if err := r.client.Delete(context.TODO(), roleBinding); err != nil && !errors.IsNotFound(err) {
157+
if err := r.client.Delete(context.TODO(), roleBinding); err != nil && !k8serrors.IsNotFound(err) {
155158
return err
156159
}
157160

@@ -161,7 +164,7 @@ func (r *ReconcileHostPathProvisioner) deletePrometheusResources(namespace strin
161164
Namespace: namespace,
162165
},
163166
}
164-
if err := r.client.Delete(context.TODO(), monitor); err != nil && !errors.IsNotFound(err) {
167+
if err := r.client.Delete(context.TODO(), monitor); err != nil && !k8serrors.IsNotFound(err) {
165168
return err
166169
}
167170

@@ -171,7 +174,7 @@ func (r *ReconcileHostPathProvisioner) deletePrometheusResources(namespace strin
171174
Namespace: namespace,
172175
},
173176
}
174-
if err := r.client.Delete(context.TODO(), service); err != nil && !errors.IsNotFound(err) {
177+
if err := r.client.Delete(context.TODO(), service); err != nil && !k8serrors.IsNotFound(err) {
175178
return err
176179
}
177180

@@ -208,15 +211,15 @@ func getRecordRules(namespace string) []promv1.Rule {
208211
return recordRules
209212
}
210213

211-
func getAlertRules() []promv1.Rule {
214+
func getAlertRules(runbookURLTemplate string) []promv1.Rule {
212215
return []promv1.Rule{
213216
generateAlertRule(
214217
"HPPOperatorDown",
215218
"kubevirt_hpp_operator_up_total == 0",
216219
"5m",
217220
map[string]string{
218221
"summary": "Hostpath Provisioner operator is down",
219-
"runbook_url": runbookURLBasePath + "HPPOperatorDown",
222+
"runbook_url": fmt.Sprintf(runbookURLTemplate, "HPPOperatorDown"),
220223
},
221224
map[string]string{
222225
severityAlertLabelKey: "warning",
@@ -231,7 +234,7 @@ func getAlertRules() []promv1.Rule {
231234
"5m",
232235
map[string]string{
233236
"summary": "Hostpath Provisioner is not available to use",
234-
"runbook_url": runbookURLBasePath + "HPPNotReady",
237+
"runbook_url": fmt.Sprintf(runbookURLTemplate, "HPPNotReady"),
235238
},
236239
map[string]string{
237240
severityAlertLabelKey: "warning",
@@ -246,7 +249,7 @@ func getAlertRules() []promv1.Rule {
246249
"1m",
247250
map[string]string{
248251
"summary": "HPP pool path sharing a filesystem with OS, fix to prevent HPP PVs from causing disk pressure and affecting node operation",
249-
"runbook_url": runbookURLBasePath + "HPPSharingPoolPathWithOS",
252+
"runbook_url": fmt.Sprintf(runbookURLTemplate, "HPPSharingPoolPathWithOS"),
250253
},
251254
map[string]string{
252255
severityAlertLabelKey: "warning",
@@ -262,6 +265,8 @@ func createPrometheusRule(namespace string) *promv1.PrometheusRule {
262265
labels := getRecommendedLabels()
263266
labels[PrometheusLabelKey] = PrometheusLabelValue
264267

268+
runbookURLTemplate := getRunbookURLTemplate()
269+
265270
return &promv1.PrometheusRule{
266271
TypeMeta: metav1.TypeMeta{
267272
APIVersion: promv1.SchemeGroupVersion.String(),
@@ -276,7 +281,7 @@ func createPrometheusRule(namespace string) *promv1.PrometheusRule {
276281
Groups: []promv1.RuleGroup{
277282
{
278283
Name: "hpp.rules",
279-
Rules: append(getRecordRules(namespace), getAlertRules()...),
284+
Rules: append(getRecordRules(namespace), getAlertRules(runbookURLTemplate)...),
280285
},
281286
},
282287
},
@@ -438,3 +443,16 @@ func (r *ReconcileHostPathProvisioner) checkPrometheusUsed() (bool, error) {
438443
}
439444
return true, nil
440445
}
446+
447+
func getRunbookURLTemplate() string {
448+
runbookURLTemplate, exists := os.LookupEnv(runbookURLTemplateEnv)
449+
if !exists {
450+
runbookURLTemplate = defaultRunbookURLTemplate
451+
}
452+
453+
if strings.Count(runbookURLTemplate, "%s") != 1 {
454+
panic(errors.New("runbook URL template must have exactly 1 %s substring"))
455+
}
456+
457+
return runbookURLTemplate
458+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package hostpathprovisioner
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
. "github.com/onsi/ginkgo"
8+
. "github.com/onsi/gomega"
9+
)
10+
11+
var _ = Describe("Prometheus", func() {
12+
BeforeEach(func() {
13+
os.Unsetenv(runbookURLTemplateEnv)
14+
})
15+
16+
AfterEach(func() {
17+
os.Unsetenv(runbookURLTemplateEnv)
18+
})
19+
20+
It("should use the default runbook URL template when no ENV Variable is set", func() {
21+
promRule := createPrometheusRule("mynamespace")
22+
23+
for _, group := range promRule.Spec.Groups {
24+
for _, rule := range group.Rules {
25+
if rule.Alert != "" {
26+
if rule.Annotations["runbook_url"] != "" {
27+
Expect(rule.Annotations["runbook_url"]).To(Equal(fmt.Sprintf(defaultRunbookURLTemplate, rule.Alert)))
28+
}
29+
}
30+
}
31+
}
32+
})
33+
34+
It("should use the desired runbook URL template when its ENV Variable is set", func() {
35+
desiredRunbookURLTemplate := "desired/runbookURL/template/%s"
36+
os.Setenv(runbookURLTemplateEnv, desiredRunbookURLTemplate)
37+
38+
promRule := createPrometheusRule("mynamespace")
39+
40+
for _, group := range promRule.Spec.Groups {
41+
for _, rule := range group.Rules {
42+
if rule.Alert != "" {
43+
if rule.Annotations["runbook_url"] != "" {
44+
Expect(rule.Annotations["runbook_url"]).To(Equal(fmt.Sprintf(desiredRunbookURLTemplate, rule.Alert)))
45+
}
46+
}
47+
}
48+
}
49+
})
50+
})

0 commit comments

Comments
 (0)