• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kubevirt / hyperconverged-cluster-operator / 18159384946

01 Oct 2025 10:30AM UTC coverage: 72.475% (+0.2%) from 72.269%
18159384946

Pull #3795

github

machadovilaca
On metric token refresh, also delete the ServiceMonitor (#3790)

Currently, on token refresh, we're recreating the secret. But Prometheus
does not fetch the new secret, and fails to access the metrics endpoint,
rceiving 401 from the pod.

This PR fixes the issue by also remove the ServiceMonitor, letting the
next reconcile loop to re-create it, to force Prometheus, afer a few
minutes, to re fetch the token from the secret.

Signed-off-by: Nahshon Unna-Tsameret <nunnatsa@redhat.com>
Co-authored-by: Nahshon Unna-Tsameret <nunnatsa@redhat.com>
Pull Request #3795: [release-1.14] On metric token refresh, also delete the ServiceMonitor (#3790)

97 of 106 new or added lines in 4 files covered. (91.51%)

3 existing lines in 1 file now uncovered.

6543 of 9028 relevant lines covered (72.47%)

0.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.11
/controllers/alerts/secret.go
1
package alerts
2

3
import (
4
        "context"
5
        "sync"
6

7
        "github.com/go-logr/logr"
8
        corev1 "k8s.io/api/core/v1"
9
        "k8s.io/apimachinery/pkg/api/errors"
10
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11
        "sigs.k8s.io/controller-runtime/pkg/client"
12

13
        "github.com/kubevirt/hyperconverged-cluster-operator/pkg/authorization"
14
        hcoutil "github.com/kubevirt/hyperconverged-cluster-operator/pkg/util"
15
)
16

17
const (
18
        secretName = "hco-bearer-auth"
19
)
20

21
type CreateSecretFunc func(namespace string, owner metav1.OwnerReference, token string) *corev1.Secret
22
type SecretReconciler struct {
23
        theSecret    *corev1.Secret
24
        lock         *sync.RWMutex
25
        createSecret CreateSecretFunc
26
        secretName   string
27
        refresher    Refresher
28
}
29

30
func NewSecretReconciler(namespace string, owner metav1.OwnerReference, secretName string, createSecret CreateSecretFunc, rfr Refresher) *SecretReconciler {
1✔
31
        token, err := authorization.CreateToken()
1✔
32
        if err != nil {
1✔
33
                logger.Error(err, "failed to create bearer token")
×
34
                return nil
×
35
        }
×
36

37
        return &SecretReconciler{
1✔
38
                theSecret:    createSecret(namespace, owner, token),
1✔
39
                lock:         &sync.RWMutex{},
1✔
40
                createSecret: createSecret,
1✔
41
                secretName:   secretName,
1✔
42
                refresher:    rfr,
1✔
43
        }
1✔
44
}
45

46
func (r *SecretReconciler) Kind() string {
1✔
47
        return "Secret"
1✔
48
}
1✔
49

50
func (r *SecretReconciler) ResourceName() string {
1✔
51
        return r.secretName
1✔
52
}
1✔
53

54
func (r *SecretReconciler) GetFullResource() client.Object {
1✔
55
        r.lock.RLock()
1✔
56
        defer r.lock.RUnlock()
1✔
57

1✔
58
        return r.theSecret.DeepCopy()
1✔
59
}
1✔
60

61
func (r *SecretReconciler) refreshToken() error {
1✔
62
        r.lock.Lock()
1✔
63
        defer r.lock.Unlock()
1✔
64

1✔
65
        token, err := authorization.CreateToken()
1✔
66
        if err != nil {
1✔
NEW
67
                return err
×
NEW
68
        }
×
69

70
        r.theSecret = r.createSecret(r.theSecret.Namespace, r.theSecret.OwnerReferences[0], token)
1✔
71

1✔
72
        r.refresher.setShouldRefresh()
1✔
73

1✔
74
        return nil
1✔
75
}
76

77
func (r *SecretReconciler) EmptyObject() client.Object {
1✔
78
        return &corev1.Secret{}
1✔
79
}
1✔
80

81
// UpdateExistingResource checks if the secret already exists and has the correct token.
82
// If it does, it returns nil. If the secret exists but the token is incorrect, it deletes the old secret
83
// and creates a new one with the updated token. If the secret does not exist, it creates a new one.
84
// It deletes the old secret to force Prometheus to reload the configuration.
85
func (r *SecretReconciler) UpdateExistingResource(ctx context.Context, cl client.Client, resource client.Object, logger logr.Logger) (client.Object, bool, error) {
1✔
86
        found := resource.(*corev1.Secret)
1✔
87

1✔
88
        token, err := authorization.CreateToken()
1✔
89
        if err != nil {
1✔
90
                return nil, false, err
×
91
        }
×
92

93
        // Check if the secret has the correct token
94
        if string(found.Data["token"]) == token {
1✔
95
                return nil, false, nil
×
96
        }
×
97

98
        // If the token is incorrect, delete the old secret and create a new one
99
        if err = cl.Delete(ctx, found); err != nil {
1✔
100
                if !errors.IsNotFound(err) {
×
101
                        logger.Error(err, "failed to delete old secret")
×
102
                        return nil, false, err
×
103
                }
×
104
        }
105

106
        if err = r.refreshToken(); err != nil {
1✔
NEW
107
                logger.Error(err, "failed to refresh token")
×
NEW
108
                return nil, false, err
×
NEW
109
        }
×
110

111
        sec := r.GetFullResource()
1✔
112
        if err = cl.Create(ctx, sec); err != nil {
1✔
113
                logger.Error(err, "failed to create new secret")
×
114
                return nil, false, err
×
115
        }
×
116

117
        return sec, true, nil
1✔
118
}
119

120
func newSecret(namespace string, owner metav1.OwnerReference, token string) *corev1.Secret {
1✔
121
        return &corev1.Secret{
1✔
122
                TypeMeta: metav1.TypeMeta{
1✔
123
                        APIVersion: "v1",
1✔
124
                        Kind:       "Secret",
1✔
125
                },
1✔
126
                ObjectMeta: metav1.ObjectMeta{
1✔
127
                        Name:            secretName,
1✔
128
                        Namespace:       namespace,
1✔
129
                        Labels:          hcoutil.GetLabels(hcoutil.HyperConvergedName, hcoutil.AppComponentMonitoring),
1✔
130
                        OwnerReferences: []metav1.OwnerReference{owner},
1✔
131
                },
1✔
132
                StringData: map[string]string{
1✔
133
                        "token": token,
1✔
134
                },
1✔
135
        }
1✔
136
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc