mirror of
https://github.com/siderolabs/sidero.git
synced 2025-10-23 05:21:36 +02:00
This PR updates the naming of the two apps that make up sidero for consistency. It also updates things like the Makefile, Dockerfile, and kustomize to make sure image names are the same as these app names. Signed-off-by: Spencer Smith <robertspencersmith@gmail.com>
232 lines
6.6 KiB
Go
232 lines
6.6 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package controllers
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/go-logr/logr"
|
|
corev1 "k8s.io/api/core/v1"
|
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
"k8s.io/apimachinery/pkg/fields"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
"k8s.io/client-go/tools/record"
|
|
"sigs.k8s.io/cluster-api/util/patch"
|
|
ctrl "sigs.k8s.io/controller-runtime"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
"sigs.k8s.io/controller-runtime/pkg/controller"
|
|
"sigs.k8s.io/controller-runtime/pkg/handler"
|
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
|
"sigs.k8s.io/controller-runtime/pkg/source"
|
|
|
|
infrav1 "github.com/talos-systems/sidero/app/caps-controller-manager/api/v1alpha3"
|
|
metalv1alpha1 "github.com/talos-systems/sidero/app/sidero-controller-manager/api/v1alpha1"
|
|
)
|
|
|
|
// ServerBindingReconciler reconciles a ServerBinding object.
|
|
type ServerBindingReconciler struct {
|
|
client.Client
|
|
Log logr.Logger
|
|
Scheme *runtime.Scheme
|
|
Recorder record.EventRecorder
|
|
}
|
|
|
|
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=serverbindings,verbs=get;list;watch;create;update;patch;delete
|
|
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=serverbindings/status,verbs=get;update;patch
|
|
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=metalmachines,verbs=get;list;watch
|
|
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=metalmachines/status,verbs=get;list;watch
|
|
// +kubebuilder:rbac:groups=metal.sidero.dev,resources=serverclasses,verbs=get;list;watch;
|
|
// +kubebuilder:rbac:groups=metal.sidero.dev,resources=serverclasses/status,verbs=get;list;watch;
|
|
// +kubebuilder:rbac:groups=metal.sidero.dev,resources=servers,verbs=get;list;watch;
|
|
// +kubebuilder:rbac:groups=metal.sidero.dev,resources=servers/status,verbs=get;list;watch
|
|
// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch
|
|
|
|
func (r *ServerBindingReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, err error) {
|
|
ctx := context.Background()
|
|
logger := r.Log.WithValues("serverbinding", req.NamespacedName)
|
|
|
|
serverBinding := &infrav1.ServerBinding{}
|
|
|
|
err = r.Get(ctx, req.NamespacedName, serverBinding)
|
|
if apierrors.IsNotFound(err) {
|
|
return r.reconcileTransition(logger, req)
|
|
}
|
|
|
|
if err != nil {
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
// Initialize the patch helper
|
|
patchHelper, err := patch.NewHelper(serverBinding, r)
|
|
if err != nil {
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
// Always attempt to Patch the ServerBinding object and status after each reconciliation.
|
|
defer func() {
|
|
if e := patchHelper.Patch(ctx, serverBinding); e != nil {
|
|
logger.Error(e, "failed to patch metalMachine")
|
|
|
|
if err == nil {
|
|
err = e
|
|
}
|
|
}
|
|
}()
|
|
|
|
var server metalv1alpha1.Server
|
|
|
|
err = r.Get(ctx, req.NamespacedName, &server)
|
|
if err != nil {
|
|
if apierrors.IsNotFound(err) {
|
|
serverBinding.Status.Ready = false
|
|
|
|
return ctrl.Result{}, nil
|
|
}
|
|
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
serverBinding.Status.Ready = true
|
|
|
|
return ctrl.Result{}, nil
|
|
}
|
|
|
|
func (r *ServerBindingReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error {
|
|
if err := mgr.GetFieldIndexer().IndexField(context.Background(), &infrav1.MetalMachine{}, infrav1.MetalMachineServerRefField, func(rawObj runtime.Object) []string {
|
|
metalMachine := rawObj.(*infrav1.MetalMachine)
|
|
|
|
if metalMachine.Spec.ServerRef == nil {
|
|
return nil
|
|
}
|
|
|
|
return []string{metalMachine.Spec.ServerRef.Name}
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
|
|
// This mapRequests handler allows us to transition to the new scheme with ServerBinding.
|
|
mapRequests := handler.ToRequestsFunc(
|
|
func(a handler.MapObject) []reconcile.Request {
|
|
metalMachine := &infrav1.MetalMachine{}
|
|
|
|
if err := r.Get(context.Background(), types.NamespacedName{Namespace: a.Meta.GetNamespace(), Name: a.Meta.GetName()}, metalMachine); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if metalMachine.Spec.ServerRef == nil {
|
|
return nil
|
|
}
|
|
|
|
return []reconcile.Request{
|
|
{
|
|
NamespacedName: types.NamespacedName{
|
|
Name: metalMachine.Spec.ServerRef.Name,
|
|
Namespace: metalMachine.Spec.ServerRef.Namespace,
|
|
},
|
|
},
|
|
}
|
|
})
|
|
|
|
return ctrl.NewControllerManagedBy(mgr).
|
|
WithOptions(options).
|
|
For(&infrav1.ServerBinding{}).
|
|
Watches(
|
|
&source.Kind{Type: &infrav1.MetalMachine{}},
|
|
&handler.EnqueueRequestsFromMapFunc{
|
|
ToRequests: mapRequests,
|
|
},
|
|
).
|
|
Complete(r)
|
|
}
|
|
|
|
func (r *ServerBindingReconciler) reconcileTransition(logger logr.Logger, req ctrl.Request) (_ ctrl.Result, err error) {
|
|
ctx := context.Background()
|
|
|
|
logger.Info("reconciling missing serverbinding")
|
|
|
|
var metalMachineList infrav1.MetalMachineList
|
|
|
|
if err := r.List(ctx, &metalMachineList, client.MatchingFields(fields.Set{infrav1.MetalMachineServerRefField: req.Name})); err != nil {
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
var serverBinding infrav1.ServerBinding
|
|
|
|
serverBinding.Namespace = req.Namespace
|
|
serverBinding.Name = req.Name
|
|
serverBinding.Labels = map[string]string{}
|
|
|
|
found := false
|
|
|
|
for _, metalMachine := range metalMachineList.Items {
|
|
if !metalMachine.DeletionTimestamp.IsZero() {
|
|
continue
|
|
}
|
|
|
|
if metalMachine.Spec.ServerRef != nil {
|
|
if metalMachine.Spec.ServerRef.Name == serverBinding.Name && metalMachine.Spec.ServerRef.Namespace == serverBinding.Namespace {
|
|
found = true
|
|
|
|
serverBinding.Spec.MetalMachineRef = corev1.ObjectReference{
|
|
Kind: metalMachine.Kind,
|
|
UID: metalMachine.UID,
|
|
Namespace: metalMachine.Namespace,
|
|
Name: metalMachine.Name,
|
|
}
|
|
|
|
if metalMachine.Spec.ServerClassRef != nil {
|
|
serverBinding.Spec.ServerClassRef = metalMachine.Spec.ServerClassRef.DeepCopy()
|
|
}
|
|
|
|
for label, value := range metalMachine.Labels {
|
|
serverBinding.Labels[label] = value
|
|
}
|
|
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
logger.Info("no matching metalmachine found")
|
|
|
|
return ctrl.Result{}, nil
|
|
}
|
|
|
|
var server metalv1alpha1.Server
|
|
|
|
if err = r.Get(ctx, req.NamespacedName, &server); err != nil {
|
|
if apierrors.IsNotFound(err) {
|
|
// broken link?
|
|
logger.Info("server not found", "name", req.Name)
|
|
|
|
return ctrl.Result{}, nil
|
|
}
|
|
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
for _, ownerRef := range server.OwnerReferences {
|
|
if ownerRef.Kind == "ServerClass" {
|
|
serverBinding.Spec.ServerClassRef = &corev1.ObjectReference{
|
|
Kind: ownerRef.Kind,
|
|
Name: ownerRef.Name,
|
|
}
|
|
}
|
|
}
|
|
|
|
logger.Info("creating missing server binding", "metalmachine", serverBinding.Spec.MetalMachineRef.Name)
|
|
|
|
err = r.Create(ctx, &serverBinding)
|
|
if err != nil {
|
|
if apierrors.IsAlreadyExists(err) {
|
|
err = nil
|
|
}
|
|
}
|
|
|
|
return ctrl.Result{}, err
|
|
}
|