Skip to content

Commit a3924fb

Browse files
committed
make sure ServiceMonitors and Roles are changed and updated for DNS pods as well
1 parent 8617070 commit a3924fb

6 files changed

Lines changed: 118 additions & 10 deletions

manifests/0000_70_dns-operator_00-cluster-role.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ rules:
9191
- rbac.authorization.k8s.io
9292
resources:
9393
- clusterroles
94+
- roles
9495
verbs:
9596
- update
9697

pkg/operator/controller/controller.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -464,15 +464,8 @@ func (r *reconciler) ensureMetricsIntegration(dns *operatorv1.DNS, svc *corev1.S
464464
logrus.Infof("created dns metrics cluster role binding %s", crb.Name)
465465
}
466466

467-
mr := manifests.MetricsRole()
468-
if err := r.client.Get(context.TODO(), types.NamespacedName{Namespace: mr.Namespace, Name: mr.Name}, mr); err != nil {
469-
if !errors.IsNotFound(err) {
470-
return fmt.Errorf("failed to get dns metrics role %s/%s: %v", mr.Namespace, mr.Name, err)
471-
}
472-
if err := r.client.Create(context.TODO(), mr); err != nil {
473-
return fmt.Errorf("failed to create dns metrics role %s/%s: %v", mr.Namespace, mr.Name, err)
474-
}
475-
logrus.Infof("created dns metrics role %s/%s", mr.Namespace, mr.Name)
467+
if _, _, err := r.ensureDNSMetricsRole(); err != nil {
468+
return fmt.Errorf("failed to ensure dns metrics role for %s: %v", dns.Name, err)
476469
}
477470

478471
mrb := manifests.MetricsRoleBinding()
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package controller
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/google/go-cmp/cmp"
8+
"github.com/google/go-cmp/cmp/cmpopts"
9+
"github.com/openshift/cluster-dns-operator/pkg/manifests"
10+
11+
"github.com/sirupsen/logrus"
12+
13+
rbacv1 "k8s.io/api/rbac/v1"
14+
"k8s.io/apimachinery/pkg/api/errors"
15+
"k8s.io/apimachinery/pkg/types"
16+
)
17+
18+
func (r *reconciler) ensureDNSMetricsRole() (bool, *rbacv1.Role, error) {
19+
desired := manifests.MetricsRole()
20+
21+
have, current, err := r.currentDNSMetricsRole()
22+
if err != nil {
23+
return false, nil, err
24+
}
25+
26+
switch {
27+
case !have:
28+
if err := r.client.Create(context.TODO(), desired); err != nil {
29+
return false, nil, fmt.Errorf("failed to create dns metrics role %s/%s: %v", desired.GetNamespace(), desired.GetName(), err)
30+
}
31+
logrus.Infof("created dns metrics role %s/%s", desired.GetNamespace(), desired.GetName())
32+
return r.currentDNSMetricsRole()
33+
case have:
34+
if updated, err := r.updateDNSMetricsRole(current, desired); err != nil {
35+
return true, current, err
36+
} else if updated {
37+
return r.currentDNSMetricsRole()
38+
}
39+
}
40+
return true, current, nil
41+
}
42+
43+
func (r *reconciler) currentDNSMetricsRole() (bool, *rbacv1.Role, error) {
44+
desired := manifests.MetricsRole()
45+
current := &rbacv1.Role{}
46+
if err := r.client.Get(context.TODO(), types.NamespacedName{Namespace: desired.GetNamespace(), Name: desired.GetName()}, current); err != nil {
47+
if errors.IsNotFound(err) {
48+
return false, nil, nil
49+
}
50+
return false, nil, err
51+
}
52+
return true, current, nil
53+
}
54+
55+
func (r *reconciler) updateDNSMetricsRole(current, desired *rbacv1.Role) (bool, error) {
56+
changed, updated := dnsMetricsRoleChanged(current, desired)
57+
if !changed {
58+
return false, nil
59+
}
60+
61+
// Diff before updating because the client may mutate the object.
62+
diff := cmp.Diff(current, updated, cmpopts.EquateEmpty())
63+
if err := r.client.Update(context.TODO(), updated); err != nil {
64+
return false, fmt.Errorf("failed to update dns metrics role %s/%s: %v", updated.GetNamespace(), updated.GetName(), err)
65+
}
66+
logrus.Infof("updated dns metrics role %s/%s: %v", updated.GetNamespace(), updated.GetName(), diff)
67+
return true, nil
68+
}
69+
70+
func dnsMetricsRoleChanged(current, desired *rbacv1.Role) (bool, *rbacv1.Role) {
71+
if cmp.Equal(current.Rules, desired.Rules, cmpopts.EquateEmpty()) {
72+
return false, nil
73+
}
74+
75+
updated := current.DeepCopy()
76+
updated.Rules = desired.Rules
77+
78+
return true, updated
79+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package controller
2+
3+
import (
4+
"testing"
5+
6+
"github.com/openshift/cluster-dns-operator/pkg/manifests"
7+
rbacv1 "k8s.io/api/rbac/v1"
8+
)
9+
10+
func TestDNSggMetricsRoleChanged(t *testing.T) {
11+
role1 := manifests.MetricsRole()
12+
role2 := manifests.MetricsRole()
13+
if changed, _ := dnsMetricsRoleChanged(role1, role2); changed {
14+
t.Fatal("expected changed to be false for two roles with identical rules")
15+
}
16+
role2.Rules = append(role2.Rules, rbacv1.PolicyRule{
17+
APIGroups: []string{"example.io"},
18+
Resources: []string{"foos"},
19+
Verbs: []string{"get"},
20+
})
21+
if changed, updated := dnsMetricsRoleChanged(role1, role2); !changed {
22+
t.Fatal("expected changed to be true after adding a rule")
23+
} else if changedAgain, _ := dnsMetricsRoleChanged(role2, updated); changedAgain {
24+
t.Fatal("dnsMetricsRoleChanged does not behave as a fixed-point function")
25+
}
26+
}

pkg/operator/controller/controller_service_monitor.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ func desiredServiceMonitor(dns *operatorv1.DNS, svc *corev1.Service, daemonsetRe
5757
"openshift-dns",
5858
},
5959
},
60-
"selector": map[string]interface{}{},
60+
"selector": map[string]interface{}{},
61+
"serviceDiscoveryRole": "EndpointSlice",
6162
"endpoints": []interface{}{
6263
map[string]interface{}{
6364
"bearerTokenFile": "/var/run/secrets/kubernetes.io/serviceaccount/token",

pkg/operator/controller/controller_service_monitor_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ func TestDNSServiceMonitorChanged(t *testing.T) {
3131
},
3232
expect: true,
3333
},
34+
{
35+
description: "if serviceDiscoveryRole changes",
36+
mutate: func(serviceMonitor *unstructured.Unstructured) {
37+
spec := serviceMonitor.Object["spec"].(map[string]interface{})
38+
spec["serviceDiscoveryRole"] = "EndpointSlice"
39+
},
40+
expect: true,
41+
},
3442
{
3543
description: "if labels change",
3644
mutate: func(serviceMonitor *unstructured.Unstructured) {

0 commit comments

Comments
 (0)