Skip to content

Commit

Permalink
inventory controller
Browse files Browse the repository at this point in the history
Signed-off-by: Artem Bortnikov <[email protected]>
  • Loading branch information
aobort committed Jun 13, 2024
1 parent 06ff8c1 commit cdf55e4
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 92 deletions.
25 changes: 22 additions & 3 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import (
"github.com/ironcore-dev/metal/internal/controller"
"github.com/ironcore-dev/metal/internal/log"
"github.com/ironcore-dev/metal/internal/namespace"
//+kubebuilder:scaffold:imports
// +kubebuilder:scaffold:imports
)

type params struct {
Expand All @@ -49,6 +49,7 @@ type params struct {
enableMachineController bool
enableMachineClaimController bool
enableOOBController bool
enableInventoryController bool
oobIpLabelSelector string
oobMacDB string
oobCredsRenewalBeforeExpiry time.Duration
Expand All @@ -73,6 +74,7 @@ func parseCmdLine() params {
pflag.Bool("enable-machine-controller", true, "Enable the Machine controller.")
pflag.Bool("enable-machineclaim-controller", true, "Enable the MachineClaim controller.")
pflag.Bool("enable-oob-controller", true, "Enable the OOB controller.")
pflag.Bool("enable-inventory-controller", true, "Enable the Inventory controller")
pflag.String("oob-ip-label-selector", "", "OOB: Filter IP objects by labels.")
pflag.String("oob-mac-db", "", "OOB: Load MAC DB from file.")
pflag.Duration("oob-creds-renewal-before-expiry", time.Hour*24*7, "OOB: Renew expiring credentials this long before they expire.")
Expand Down Expand Up @@ -171,7 +173,7 @@ func main() {
exitCode = 1
return
}
//+kubebuilder:scaffold:scheme
// +kubebuilder:scaffold:scheme

var kcfg *rest.Config
kcfg, err = ctrl.GetConfig()
Expand Down Expand Up @@ -286,7 +288,24 @@ func main() {
}
}

//+kubebuilder:scaffold:builder
if p.enableInventoryController {
var inventoryReconciler *controller.InventoryReconciler
inventoryReconciler, err = controller.NewInventoryReconciler()
if err != nil {
log.Error(ctx, fmt.Errorf("cannot create controller: %w", err), "controller", "Inventory")
exitCode = 1
return
}

err = inventoryReconciler.SetupWithManager(mgr)
if err != nil {
log.Error(ctx, fmt.Errorf("cannot create controller: %w", err), "controller", "Inventory")
exitCode = 1
return
}
}

// +kubebuilder:scaffold:builder

err = mgr.AddHealthzCheck("health", healthz.Ping)
if err != nil {
Expand Down
61 changes: 61 additions & 0 deletions internal/controller/inventory_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package controller

import (
"context"
"fmt"
"slices"

metalv1alpha1 "github.com/ironcore-dev/metal/api/v1alpha1"
metalv1alpha1apply "github.com/ironcore-dev/metal/client/applyconfiguration/api/v1alpha1"
"github.com/ironcore-dev/metal/internal/ssa"
v1 "k8s.io/api/core/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func NewInventoryReconciler() (*InventoryReconciler, error) {
return &InventoryReconciler{}, nil
}

type InventoryReconciler struct {
client.Client
}

func (r *InventoryReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
var inventory metalv1alpha1.Inventory
if err := r.Get(ctx, req.NamespacedName, &inventory); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(fmt.Errorf("cannot get Inventory: %w", err))
}
if !inventory.DeletionTimestamp.IsZero() {
return ctrl.Result{}, nil
}
return ctrl.Result{}, r.reconcile(ctx, inventory)
}

func (r *InventoryReconciler) reconcile(ctx context.Context, inventory metalv1alpha1.Inventory) error {
machines := &metalv1alpha1.MachineList{}
if err := r.List(ctx, machines); err != nil {
return err
}
idx := slices.IndexFunc(machines.Items, func(machine metalv1alpha1.Machine) bool {
return machine.Spec.InventoryRef == nil && machine.Spec.UUID == inventory.Name
})
if idx == -1 {
return nil
}
machine := machines.Items[idx].DeepCopy()
machineApply := metalv1alpha1apply.Machine(machine.Name, machine.Namespace)
machineSpecApply := metalv1alpha1apply.MachineSpec().
WithPower(metalv1alpha1.PowerOff).
WithInventoryRef(v1.LocalObjectReference{Name: inventory.Name})
machineApply = machineApply.WithSpec(machineSpecApply)
return r.Patch(ctx, machine, ssa.Apply(machineApply), client.FieldOwner(MachineFieldOwner), client.ForceOwnership)
}

func (r *InventoryReconciler) SetupWithManager(mgr ctrl.Manager) error {
r.Client = mgr.GetClient()

return ctrl.NewControllerManagedBy(mgr).
For(&metalv1alpha1.Inventory{}).
Complete(r)
}
101 changes: 12 additions & 89 deletions internal/controller/machine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,20 @@ func (r *MachineReconciler) reconcile(
machineApply := metalv1alpha1apply.Machine(machine.Name, machine.Namespace)
machineStatusApply := metalv1alpha1apply.MachineStatus()
r.fillConditions(machine, machineStatusApply)
if machine.Spec.Maintenance {
switch {
case machine.Spec.Maintenance:
machineStatusApply = machineStatusApply.WithState(metalv1alpha1.MachineStateMaintenance)
} else {
case machine.Spec.InventoryRef == nil && !slices.Contains(nonInitialStates, machine.Status.State):
if machine.Spec.Power != metalv1alpha1.PowerOn {
return machineApply.WithSpec(metalv1alpha1apply.MachineSpec().WithPower(metalv1alpha1.PowerOn))
}
default:
r.evaluateConditions(ctx, machine, machineStatusApply)
r.evaluateCleanupRequired(machine, machineStatusApply)
r.evaluateReadiness(machine, machineStatusApply)
r.evaluateAvailability(machine, machineStatusApply)
}

r.evaluateErrorState(machine, machineStatusApply)
machineApply = machineApply.WithStatus(machineStatusApply)
return machineApply
Expand Down Expand Up @@ -556,7 +562,10 @@ func (r *MachineReconciler) SetupWithManager(mgr ctrl.Manager) error {
return requests
}
for _, machine := range machineList.Items {
if machine.Spec.UUID == source.Name {
if machine.Spec.InventoryRef == nil {
continue
}
if machine.Spec.InventoryRef.Name == source.Name {
requests = append(requests, reconcile.Request{
NamespacedName: types.NamespacedName{
Name: machine.GetName(),
Expand All @@ -569,95 +578,9 @@ func (r *MachineReconciler) SetupWithManager(mgr ctrl.Manager) error {
Complete(r)
}

// func convertToApplyConfiguration(base, machine metalv1alpha1.Machine) *metalv1alpha1apply.MachineApplyConfiguration {
// machineApply := metalv1alpha1apply.Machine(machine.Name, machine.Namespace)
// specApply := metalv1alpha1apply.MachineSpec()
// if base.Spec.Power != machine.Spec.Power && machine.Spec.Power != "" {
// specApply = specApply.WithPower(machine.Spec.Power)
// }
//
// statusApply := metalv1alpha1apply.MachineStatus()
// if networkInterfacesChanged(base.Status.NetworkInterfaces, machine.Status.NetworkInterfaces) {
// nicApplyList := make([]*metalv1alpha1apply.MachineNetworkInterfaceApplyConfiguration, 0, len(machine.Status.NetworkInterfaces))
// for _, nic := range machine.Status.NetworkInterfaces {
// nicApply := metalv1alpha1apply.MachineNetworkInterface().
// WithName(nic.Name).
// WithMacAddress(nic.MacAddress)
// if nic.IPRef != nil {
// nicApply = nicApply.WithIPRef(*nic.IPRef)
// }
// if nic.SwitchRef != nil {
// nicApply = nicApply.WithSwitchRef(*nic.SwitchRef)
// }
// nicApplyList = append(nicApplyList, nicApply)
// }
// statusApply = statusApply.WithNetworkInterfaces(nicApplyList...)
// }
// if conditionsChanged(base.Status.Conditions, machine.Status.Conditions) {
// conditionsApply := make([]*v1.ConditionApplyConfiguration, 0, len(machine.Status.Conditions))
// for _, c := range machine.Status.Conditions {
// conditionApply := v1.Condition().
// WithType(c.Type).
// WithStatus(c.Status).
// WithReason(c.Reason).
// WithMessage(c.Message).
// WithLastTransitionTime(c.LastTransitionTime).
// WithObservedGeneration(c.ObservedGeneration)
// conditionsApply = append(conditionsApply, conditionApply)
// }
// statusApply = statusApply.WithConditions(conditionsApply...)
// }
// if base.Status.State != machine.Status.State {
// statusApply = statusApply.WithState(machine.Status.State)
// }
//
// return machineApply.WithSpec(specApply).WithStatus(statusApply)
// }

func convertMacAddress(src string) string {
var mac = src
mac = strings.ReplaceAll(mac, ":", "")
mac = strings.ReplaceAll(mac, "-", "")
return mac
}

// func resourceChanged(objOld, objNew metalv1alpha1.Machine) bool {
// return metadataChanged(objOld, objNew) || specChanged(objOld, objNew)
// }

// func metadataChanged(objOld, objNew metalv1alpha1.Machine) bool {
// labelsChanged := !reflect.DeepEqual(objOld.GetLabels(), objNew.GetLabels())
// annotationsChanged := !reflect.DeepEqual(objOld.GetAnnotations(), objNew.GetAnnotations())
// finalizersChanged := !reflect.DeepEqual(objOld.GetFinalizers(), objNew.GetFinalizers())
// return labelsChanged || annotationsChanged || finalizersChanged
// }

// func specChanged(objOld, objNew metalv1alpha1.Machine) bool {
// oldSpec, _ := json.Marshal(objOld.Spec)
// newSpec, _ := json.Marshal(objNew.Spec)
// return !reflect.DeepEqual(oldSpec, newSpec)
// }

// func subresourceChanged(objOld, objNew metalv1alpha1.Machine) bool {
// oldStatus, _ := json.Marshal(objOld.Status)
// newStatus, _ := json.Marshal(objNew.Status)
// return !reflect.DeepEqual(oldStatus, newStatus)
// }

// func conditionsChanged(oldData, newData []metav1.Condition) bool {
// if len(oldData) != len(newData) {
// return true
// }
// oldConditions, _ := json.Marshal(oldData)
// newConditions, _ := json.Marshal(newData)
// return !reflect.DeepEqual(oldConditions, newConditions)
// }

// func networkInterfacesChanged(oldData, newData []metalv1alpha1.MachineNetworkInterface) bool {
// if len(oldData) != len(newData) {
// return true
// }
// oldNetworkInterfaces, _ := json.Marshal(oldData)
// newNetworkInterfaces, _ := json.Marshal(newData)
// return !reflect.DeepEqual(oldNetworkInterfaces, newNetworkInterfaces)
// }
6 changes: 6 additions & 0 deletions internal/controller/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ var _ = BeforeSuite(func() {
Expect(oobReconciler).NotTo(BeNil())
Expect(oobReconciler.SetupWithManager(mgr)).To(Succeed())

var inventoryReconciler *InventoryReconciler
inventoryReconciler, err = NewInventoryReconciler()
Expect(err).NotTo(HaveOccurred())
Expect(inventoryReconciler).NotTo(BeNil())
Expect(inventoryReconciler.SetupWithManager(mgr)).To(Succeed())

mgrCtx, mgrCancel := context.WithCancel(ctx)
DeferCleanup(mgrCancel)

Expand Down

0 comments on commit cdf55e4

Please sign in to comment.