@@ -21,12 +21,13 @@ import (
2121 "context"
2222 "fmt"
2323
24- v1 "k8s.io/api/core/v1"
24+ corev1 "k8s.io/api/core/v1"
25+ k8serrors "k8s.io/apimachinery/pkg/api/errors"
2526 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2627 "k8s.io/apimachinery/pkg/runtime"
27- "k8s.io/apimachinery/pkg/types"
2828 ctrl "sigs.k8s.io/controller-runtime"
2929 "sigs.k8s.io/controller-runtime/pkg/client"
30+ "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3031 logger "sigs.k8s.io/controller-runtime/pkg/log"
3132
3233 kvmv1alpha1 "github.com/cobaltcode-dev/kvm-node-agent/api/v1alpha1"
@@ -46,93 +47,68 @@ const LabelMetalNodeName = "kubernetes.metal.cloud.sap/name"
4647
4748// +kubebuilder:rbac:groups="",resources=nodes,verbs=get;list;watch
4849// +kubebuilder:rbac:groups="",resources=nodes/status,verbs=get
49- // +kubebuilder:rbac:groups=kvm.cloud.sap,resources=hypervisors,verbs=get;list;watch;create;update;patch;delete
50-
51- func (r * NodeReconciler ) getNode (ctx context.Context ) (* v1.Node , error ) {
52- // Fetch the Node we're current running on
53- var nodes v1.NodeList
54- err := r .List (ctx , & nodes , client.MatchingLabels {v1 .LabelHostname : sys .Hostname })
55- if client .IgnoreNotFound (err ) != nil {
56- return nil , fmt .Errorf ("failed fetching nodes: %w" , err )
57- }
58-
59- switch len (nodes .Items ) {
60- case 0 :
61- return nil , nil
62- case 1 :
63- return & nodes .Items [0 ], nil
64- default :
65- return nil , fmt .Errorf ("found more than one node with label %s=%s" , v1 .LabelHostname , sys .Hostname )
66- }
67-
68- }
50+ // +kubebuilder:rbac:groups=kvm.cloud.sap,resources=hypervisors,verbs=get;list;watch;create;delete
6951
7052func (r * NodeReconciler ) Reconcile (ctx context.Context , req ctrl.Request ) (ctrl.Result , error ) {
7153 log := logger .FromContext (ctx , "controller" , "node" )
7254
7355 if req .Name != sys .Hostname {
74- // only reconcile the node I am running on
75- return ctrl.Result {}, nil
56+ panic (fmt .Sprintf ("reconciling node %s, but I am running on %s" , req .Name , sys .Hostname ))
7657 }
7758
78- namespace := req .Namespace
79- if namespace == "" {
80- namespace = sys .Namespace
59+ node := & corev1.Node {}
60+ if err := r .Get (ctx , req .NamespacedName , node ); client .IgnoreNotFound (err ) != nil {
61+ // ignore not found errors, could be deleted
62+ return ctrl.Result {}, err
8163 }
8264
83- node , err := r . getNode ( ctx )
84- if err != nil {
85- return ctrl. Result {}, fmt . Errorf ( "failed fetching node: %w" , err )
65+ metalNodeName := sys . Hostname
66+ if name , ok := node . Labels [ LabelMetalNodeName ]; ok {
67+ metalNodeName = name
8668 }
87- if node == nil {
88- return ctrl.Result {}, nil
69+
70+ hypervisor := & kvmv1alpha1.Hypervisor {
71+ ObjectMeta : metav1.ObjectMeta {
72+ Name : node .Name ,
73+ Namespace : sys .Namespace ,
74+ Labels : map [string ]string {
75+ corev1 .LabelHostname : sys .Hostname ,
76+ LabelMetalNodeName : metalNodeName ,
77+ },
78+ },
79+ Spec : kvmv1alpha1.HypervisorSpec {
80+ Reboot : r .Reboot ,
81+ EvacuateOnReboot : r .EvacuateOnReboot ,
82+ CreateCertManagerCertificate : r .CreateCertManagerCertificate ,
83+ },
8984 }
90- // Todo: check I am really an hypervisor?
9185
9286 // Ensure corresponding hypervisor exists
9387 log .Info ("Reconcile" , "name" , req .Name , "namespace" , req .Namespace )
94- var hypervisors kvmv1alpha1.HypervisorList
95- if err = r .List (ctx , & hypervisors , client.MatchingLabels {v1 .LabelHostname : sys .Hostname }); err != nil {
96- return ctrl.Result {}, fmt .Errorf ("failed fetching hypervisors: %w" , err )
97- }
98-
99- if len (hypervisors .Items ) == 0 {
100- // create hypervisor
101- if err = r .Create (ctx , & kvmv1alpha1.Hypervisor {
102- ObjectMeta : metav1.ObjectMeta {
103- Name : node .Name ,
104- Namespace : namespace ,
105- Labels : map [string ]string {v1 .LabelHostname : sys .Hostname },
106- },
107- Spec : kvmv1alpha1.HypervisorSpec {
108- Reboot : r .Reboot ,
109- EvacuateOnReboot : r .EvacuateOnReboot ,
110- CreateCertManagerCertificate : r .CreateCertManagerCertificate ,
111- },
112- }); err != nil {
113- return ctrl.Result {}, fmt .Errorf ("failed creating hypervisor: %w" , err )
88+ if err := r .Get (ctx , client .ObjectKeyFromObject (hypervisor ), hypervisor ); err != nil {
89+ if k8serrors .IsNotFound (err ) {
90+ // attach ownerReference for cascading deletion
91+ if err = controllerutil .SetControllerReference (node , hypervisor , r .Scheme ); err != nil {
92+ return ctrl.Result {}, fmt .Errorf ("failed setting controller reference: %w" , err )
93+ }
94+
95+ log .Info ("Creating new hypervisor" , "name" , node .Name )
96+ if err = r .Create (ctx , hypervisor ); err != nil {
97+ return ctrl.Result {}, err
98+ }
99+
100+ // Requeue to update status
101+ return ctrl.Result {}, nil
114102 }
115- return ctrl.Result {}, nil
103+
104+ return ctrl.Result {}, err
116105 }
117106
118107 if node .ObjectMeta .DeletionTimestamp != nil {
119108 // node is being deleted, cleanup hypervisor
120- if err = r .Delete (ctx , & hypervisors . Items [ 0 ] ); client .IgnoreNotFound (err ) != nil {
109+ if err : = r .Delete (ctx , hypervisor ); client .IgnoreNotFound (err ) != nil {
121110 return ctrl.Result {}, fmt .Errorf ("failed cleanup up hypervisor: %w" , err )
122111 }
123- return ctrl.Result {}, nil
124- }
125-
126- hv := hypervisors .Items [0 ].DeepCopy ()
127- hv .Status .Node = types .NodeName (node .Name )
128- if name , ok := node .Labels [LabelMetalNodeName ]; ok {
129- hv .Status .Node = types .NodeName (name )
130- }
131-
132- // Update Status
133- err = r .Status ().Patch (ctx , hv , client .MergeFrom (& hypervisors .Items [0 ]))
134- if err != nil {
135- return ctrl.Result {}, fmt .Errorf ("failed patching hypervisor status: %w" , err )
136112 }
137113
138114 return ctrl.Result {}, nil
@@ -141,6 +117,6 @@ func (r *NodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.
141117// SetupWithManager sets up the controller with the Manager.
142118func (r * NodeReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
143119 return ctrl .NewControllerManagedBy (mgr ).
144- For (& v1 .Node {}).
120+ For (& corev1 .Node {}).
145121 Complete (r )
146122}
0 commit comments