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

kubevirt / hyperconverged-cluster-operator / 16000124650

01 Jul 2025 01:03PM UTC coverage: 75.464% (-0.1%) from 75.599%
16000124650

Pull #3602

github

web-flow
Merge b9875d25e into c90e45477
Pull Request #3602: Add E2E test for multi-arch

246 of 351 new or added lines in 8 files covered. (70.09%)

4 existing lines in 3 files now uncovered.

6588 of 8730 relevant lines covered (75.46%)

1.5 hits per line

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

49.32
/controllers/nodes/nodes_controller.go
1
package nodes
2

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

7
        "github.com/go-logr/logr"
8
        "github.com/google/uuid"
9
        operatorhandler "github.com/operator-framework/operator-lib/handler"
10
        corev1 "k8s.io/api/core/v1"
11
        "k8s.io/apimachinery/pkg/api/errors"
12
        k8stypes "k8s.io/apimachinery/pkg/types"
13
        "k8s.io/client-go/util/workqueue"
14
        "sigs.k8s.io/controller-runtime/pkg/client"
15
        "sigs.k8s.io/controller-runtime/pkg/controller"
16
        "sigs.k8s.io/controller-runtime/pkg/event"
17
        "sigs.k8s.io/controller-runtime/pkg/handler"
18
        logf "sigs.k8s.io/controller-runtime/pkg/log"
19
        "sigs.k8s.io/controller-runtime/pkg/manager"
20
        "sigs.k8s.io/controller-runtime/pkg/reconcile"
21
        "sigs.k8s.io/controller-runtime/pkg/source"
22

23
        hcov1beta1 "github.com/kubevirt/hyperconverged-cluster-operator/api/v1beta1"
24
        "github.com/kubevirt/hyperconverged-cluster-operator/pkg/nodeinfo"
25
        hcoutil "github.com/kubevirt/hyperconverged-cluster-operator/pkg/util"
26
)
27

28
var (
29
        log               = logf.Log.WithName("controller_nodes")
30
        randomConstSuffix = uuid.New().String()
31

32
        hcoReq = reconcile.Request{
33
                NamespacedName: k8stypes.NamespacedName{
34
                        Name:      "hyperconverged-req-" + randomConstSuffix,
35
                        Namespace: hcoutil.GetOperatorNamespaceFromEnv(),
36
                },
37
        }
38
)
39

40
// RegisterReconciler creates a new Nodes Reconciler and registers it into manager.
NEW
41
func RegisterReconciler(mgr manager.Manager, nodeEvents chan<- event.GenericEvent) error {
×
NEW
42
        return add(mgr, newReconciler(mgr, nodeEvents))
×
UNCOV
43
}
×
44

45
// newReconciler returns a new reconcile.Reconciler
NEW
46
func newReconciler(mgr manager.Manager, nodeEvents chan<- event.GenericEvent) reconcile.Reconciler {
×
47
        r := &ReconcileNodeCounter{
×
NEW
48
                Client:     mgr.GetClient(),
×
NEW
49
                nodeEvents: nodeEvents,
×
50
        }
×
51

×
52
        return r
×
53
}
×
54

55
// add adds a new Controller to mgr with r as the reconcile.Reconciler
56
func add(mgr manager.Manager, r reconcile.Reconciler) error {
×
57
        // Create a new controller
×
58
        c, err := controller.New("nodes-controller", mgr, controller.Options{Reconciler: r})
×
59
        if err != nil {
×
60
                return err
×
61
        }
×
62

63
        // Watch for changes to the cluster's nodes
64
        err = c.Watch(
×
NEW
65
                source.Kind[*corev1.Node](
×
NEW
66
                        mgr.GetCache(), &corev1.Node{},
×
NEW
67
                        &operatorhandler.InstrumentedEnqueueRequestForObject[*corev1.Node]{},
×
68
                        nodeCountChangePredicate{},
×
69
                ))
×
70
        if err != nil {
×
71
                return err
×
72
        }
×
73

NEW
74
        return c.Watch(
×
NEW
75
                source.Kind[*hcov1beta1.HyperConverged](
×
NEW
76
                        mgr.GetCache(), &hcov1beta1.HyperConverged{},
×
NEW
77
                        &handler.TypedEnqueueRequestForObject[*hcov1beta1.HyperConverged]{},
×
NEW
78
                        hyperconvergedPredicate{},
×
NEW
79
                ))
×
80
}
81

82
// ReconcileNodeCounter reconciles the nodes count
83
type ReconcileNodeCounter struct {
84
        // This client, initialized using mgr.Client() above, is a split client
85
        // that reads objects from the cache and writes to the apiserver
86
        client.Client
87
        HyperConvergedQueue workqueue.TypedRateLimitingInterface[reconcile.Request]
88
        nodeEvents          chan<- event.GenericEvent
89
}
90

91
// Reconcile updates the nodes count on ClusterInfo singleton
92
func (r *ReconcileNodeCounter) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
1✔
93
        logger, err := logr.FromContext(ctx)
1✔
94
        if err != nil {
2✔
95
                logger = log
1✔
96
        }
1✔
97
        if req == hcoReq {
1✔
NEW
98
                // This is a request triggered by a change in the HyperConverged CR
×
NEW
99
                logger.Info("Triggered by a HyperConverged CR change")
×
100
        } else {
1✔
101
                logger.Info("Triggered by a node change", "node name", req.Name)
1✔
102
        }
1✔
103

104
        logger.Info("Reading the latest HyperConverged CR")
1✔
105
        hc, err := r.readHyperConverged(ctx)
1✔
106
        if err != nil {
1✔
NEW
107
                return reconcile.Result{}, fmt.Errorf("failed to read the HyperConverged CR; %v", err)
×
UNCOV
108
        }
×
109

110
        nodeInfoChanged, err := nodeinfo.HandleNodeChanges(ctx, r, hc, logger)
1✔
111
        if err != nil {
2✔
112
                return reconcile.Result{}, err
1✔
113
        }
1✔
114

115
        if hc == nil || !hc.DeletionTimestamp.IsZero() {
2✔
116
                return reconcile.Result{}, nil
1✔
117
        }
1✔
118

119
        if nodeInfoChanged {
2✔
120
                r.nodeEvents <- event.GenericEvent{}
1✔
121
        }
1✔
122

123
        return reconcile.Result{}, nil
1✔
124
}
125

126
func (r *ReconcileNodeCounter) readHyperConverged(ctx context.Context) (*hcov1beta1.HyperConverged, error) {
1✔
127
        hc := &hcov1beta1.HyperConverged{}
1✔
128
        hcoKey := k8stypes.NamespacedName{
1✔
129
                Name:      hcoutil.HyperConvergedName,
1✔
130
                Namespace: hcoutil.GetOperatorNamespaceFromEnv(),
1✔
131
        }
1✔
132

1✔
133
        err := r.Get(ctx, hcoKey, hc)
1✔
134
        if err != nil {
2✔
135
                if errors.IsNotFound(err) {
2✔
136
                        return nil, nil
1✔
137
                }
1✔
NEW
138
                return nil, err
×
139
        }
140

141
        return hc, nil
1✔
142
}
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

© 2026 Coveralls, Inc