Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions api/common/v1alpha1/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@ import (
)

const (
// TopologyRegionLabel is a label that can be applied to MachinePool, VolumePool, and BucketPool
//
// `Machine`s, `Volume`s, and `Bucket`s can use this label for pool selection.
//
// The intent is similar to Kubernetes' topology labels (i.e. `topology.kubernetes.io/region`)
TopologyRegionLabel = "topology.ironcore.dev/region"

// TopologyZoneLabel is a label that can be applied to MachinePool, VolumePool, and BucketPool
//
// `Machine`s, `Volume`s, and `Bucket`s can use this label for pool selection.
//
// The intent is similar to Kubernetes' topology labels (i.e. `topology.kubernetes.io/zone`)
TopologyZoneLabel = "topology.ironcore.dev/zone"

// WatchLabel is a label that can be applied to any ironcore resource.
//
// Provider controllers that allow for selective reconciliation may check this label and proceed
Expand Down
30 changes: 20 additions & 10 deletions poollet/machinepoollet/cmd/machinepoollet/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ type Options struct {
NetworkDownwardAPILabels map[string]string
NetworkDownwardAPIAnnotations map[string]string

TopologyRegionLabel string
TopologyZoneLabel string

ProviderID string
MachineRuntimeEndpoint string
MachineRuntimeSocketDiscoveryTimeout time.Duration
Expand Down Expand Up @@ -136,6 +139,9 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
fs.StringToStringVar(&o.NetworkDownwardAPILabels, "network-downward-api-label", o.NetworkDownwardAPILabels, "Downward-API labels to set on the iri network.")
fs.StringToStringVar(&o.NetworkDownwardAPIAnnotations, "network-downward-api-annotation", o.NetworkDownwardAPIAnnotations, "Downward-API annotations to set on the iri network.")

fs.StringVar(&o.TopologyRegionLabel, "topology-region-label", "", "Label to use for the region topology information.")
fs.StringVar(&o.TopologyZoneLabel, "topology-zone-label", "", "Label to use for the zone topology information.")

fs.StringVar(&o.ProviderID, "provider-id", "", "Provider id to announce on the machine pool.")
fs.StringVar(&o.MachineRuntimeEndpoint, "machine-runtime-endpoint", o.MachineRuntimeEndpoint, "Endpoint of the remote machine runtime service.")
fs.DurationVar(&o.MachineRuntimeSocketDiscoveryTimeout, "machine-runtime-socket-discovery-timeout", 20*time.Second, "Timeout for discovering the machine runtime socket.")
Expand Down Expand Up @@ -456,12 +462,14 @@ func Run(ctx context.Context, opts Options) error {
}

if err := (&controllers.MachinePoolReconciler{
Client: mgr.GetClient(),
MachinePoolName: opts.MachinePoolName,
Addresses: machinePoolAddresses,
Port: port,
MachineRuntime: machineRuntime,
MachineClassMapper: machineClassMapper,
Client: mgr.GetClient(),
MachinePoolName: opts.MachinePoolName,
Addresses: machinePoolAddresses,
Port: port,
MachineRuntime: machineRuntime,
MachineClassMapper: machineClassMapper,
TopologyRegionLabel: opts.TopologyRegionLabel,
TopologyZoneLabel: opts.TopologyZoneLabel,
}).SetupWithManager(mgr); err != nil {
return fmt.Errorf("error setting up machine pool reconciler with manager: %w", err)
}
Expand All @@ -478,10 +486,12 @@ func Run(ctx context.Context, opts Options) error {
}

if err := (&controllers.MachinePoolInit{
Client: mgr.GetClient(),
MachinePoolName: opts.MachinePoolName,
ProviderID: opts.ProviderID,
OnInitialized: onInitialized,
Client: mgr.GetClient(),
MachinePoolName: opts.MachinePoolName,
ProviderID: opts.ProviderID,
TopologyRegionLabel: opts.TopologyRegionLabel,
TopologyZoneLabel: opts.TopologyZoneLabel,
OnInitialized: onInitialized,
}).SetupWithManager(mgr); err != nil {
return fmt.Errorf("error setting up machine pool init with manager: %w", err)
}
Expand Down
15 changes: 11 additions & 4 deletions poollet/machinepoollet/controllers/controllers_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"

"github.com/ironcore-dev/controller-utils/buildutils"
commonv1alpha1 "github.com/ironcore-dev/ironcore/api/common/v1alpha1"
computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1"
corev1alpha1 "github.com/ironcore-dev/ironcore/api/core/v1alpha1"
ipamv1alpha1 "github.com/ironcore-dev/ironcore/api/ipam/v1alpha1"
Expand Down Expand Up @@ -167,6 +168,10 @@ func SetupTest() (*corev1.Namespace, *computev1alpha1.MachinePool, *computev1alp
*mp = computev1alpha1.MachinePool{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "test-mp-",
Labels: map[string]string{
commonv1alpha1.TopologyRegionLabel: "foo-region-1",
commonv1alpha1.TopologyZoneLabel: "foo-zone-1",
},
},
}
Expect(k8sClient.Create(ctx, mp)).To(Succeed(), "failed to create test machine pool")
Expand Down Expand Up @@ -265,10 +270,12 @@ func SetupTest() (*corev1.Namespace, *computev1alpha1.MachinePool, *computev1alp
}).SetupWithManager(k8sManager)).To(Succeed())

Expect((&controllers.MachinePoolReconciler{
Client: k8sManager.GetClient(),
MachineRuntime: srv,
MachineClassMapper: machineClassMapper,
MachinePoolName: mp.Name,
Client: k8sManager.GetClient(),
MachineRuntime: srv,
MachineClassMapper: machineClassMapper,
MachinePoolName: mp.Name,
TopologyRegionLabel: "foo-region-1",
TopologyZoneLabel: "foo-zone-1",
}).SetupWithManager(k8sManager)).To(Succeed())

Expect((&controllers.MachinePoolAnnotatorReconciler{
Expand Down
12 changes: 12 additions & 0 deletions poollet/machinepoollet/controllers/machinepool_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"

"github.com/go-logr/logr"
commonv1alpha1 "github.com/ironcore-dev/ironcore/api/common/v1alpha1"
computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1"
corev1alpha1 "github.com/ironcore-dev/ironcore/api/core/v1alpha1"
computeclient "github.com/ironcore-dev/ironcore/internal/client/compute"
Expand Down Expand Up @@ -38,6 +39,9 @@ type MachinePoolReconciler struct {

MachineRuntime machine.RuntimeService
MachineClassMapper mcm.MachineClassMapper

TopologyRegionLabel string
TopologyZoneLabel string
}

//+kubebuilder:rbac:groups=compute.ironcore.dev,resources=machinepools,verbs=get;list;watch;update;patch
Expand Down Expand Up @@ -151,6 +155,14 @@ func (r *MachinePoolReconciler) reconcile(ctx context.Context, log logr.Logger,
return ctrl.Result{RequeueAfter: 1}, nil
}

log.V(1).Info("Enforcing configured topology labels")
base := machinePool.DeepCopy()
setLabel(&machinePool.ObjectMeta, commonv1alpha1.TopologyRegionLabel, r.TopologyRegionLabel)
setLabel(&machinePool.ObjectMeta, commonv1alpha1.TopologyZoneLabel, r.TopologyZoneLabel)
if err := r.Patch(ctx, machinePool, client.MergeFrom(base)); err != nil {
return ctrl.Result{}, fmt.Errorf("error patching machine pool labels: %w", err)
}

log.V(1).Info("Listing machine classes")
machineClassList := &computev1alpha1.MachineClassList{}
if err := r.List(ctx, machineClassList); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,4 +238,20 @@ var _ = Describe("MachinePoolController", func() {
))),
)
})

It("should enforce topology labels", func(ctx SpecContext) {
By("patching the machine pool with incorrect topology labels")
Eventually(Update(machinePool, func() {
machinePool.Labels = map[string]string{
"topology.ironcore.dev/region": "wrong-region",
"topology.ironcore.dev/zone": "wrong-zone",
}
})).Should(Succeed())

By("checking if the topology labels are overwritten by the reconciler")
Eventually(Object(machinePool)).Should(SatisfyAll(
HaveField("ObjectMeta.Labels", HaveKeyWithValue("topology.ironcore.dev/region", "foo-region-1")),
HaveField("ObjectMeta.Labels", HaveKeyWithValue("topology.ironcore.dev/zone", "foo-zone-1")),
))
})
})
9 changes: 9 additions & 0 deletions poollet/machinepoollet/controllers/machinepool_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"fmt"

commonv1alpha1 "github.com/ironcore-dev/ironcore/api/common/v1alpha1"
computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1"
machinepoolletv1alpha1 "github.com/ironcore-dev/ironcore/poollet/machinepoollet/api/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -20,6 +21,9 @@ type MachinePoolInit struct {
MachinePoolName string
ProviderID string

TopologyRegionLabel string
TopologyZoneLabel string

// TODO: Remove OnInitialized / OnFailed as soon as the controller-runtime provides support for pre-start hooks:
// https://github.com/kubernetes-sigs/controller-runtime/pull/2044

Expand All @@ -45,6 +49,11 @@ func (i *MachinePoolInit) Start(ctx context.Context) error {
ProviderID: i.ProviderID,
},
}

log.V(1).Info("Initially setting topology labels")
setLabel(&machinePool.ObjectMeta, commonv1alpha1.TopologyRegionLabel, i.TopologyRegionLabel)
setLabel(&machinePool.ObjectMeta, commonv1alpha1.TopologyZoneLabel, i.TopologyZoneLabel)

if err := i.Patch(ctx, machinePool, client.Apply, client.ForceOwnership, client.FieldOwner(machinepoolletv1alpha1.FieldOwner)); err != nil {
if i.OnFailed != nil {
log.V(1).Info("Failed applying, calling OnFailed callback", "Error", err)
Expand Down
47 changes: 47 additions & 0 deletions poollet/machinepoollet/controllers/machinepool_init_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and IronCore contributors
// SPDX-License-Identifier: Apache-2.0

package controllers_test

import (
"context"

computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1"
"github.com/ironcore-dev/ironcore/poollet/machinepoollet/controllers"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
. "sigs.k8s.io/controller-runtime/pkg/envtest/komega"
)

var _ = Describe("MachinePoolInit", func() {
It("should add topology labels", func(ctx SpecContext) {
initializedCalled := false

mpi := &controllers.MachinePoolInit{
Client: k8sClient,
MachinePoolName: "test-pool",
ProviderID: "provider-123",
TopologyRegionLabel: "foo-region-1",
TopologyZoneLabel: "foo-zone-1",
OnInitialized: func(ctx context.Context) error {
initializedCalled = true
return nil
},
}

Expect(mpi.Start(ctx)).ToNot(HaveOccurred())
Expect(initializedCalled).To(BeTrue())

pool := &computev1alpha1.MachinePool{
ObjectMeta: metav1.ObjectMeta{
Name: "test-pool",
},
}

Eventually(Object(pool)).Should(SatisfyAll(
HaveField("ObjectMeta.Labels", HaveKeyWithValue("topology.ironcore.dev/region", "foo-region-1")),
HaveField("ObjectMeta.Labels", HaveKeyWithValue("topology.ironcore.dev/zone", "foo-zone-1")),
))
})
})
13 changes: 13 additions & 0 deletions poollet/machinepoollet/controllers/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
iri "github.com/ironcore-dev/ironcore/iri/apis/machine/v1alpha1"
"github.com/ironcore-dev/ironcore/utils/generic"
utilslices "github.com/ironcore-dev/ironcore/utils/slices"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func FindNewIRINetworkInterfaces(desiredIRINics, existingIRINics []*iri.NetworkInterface) []*iri.NetworkInterface {
Expand Down Expand Up @@ -59,3 +60,15 @@ func getAndParseFromStringMap[E any](annotations map[string]string, key string,

return e, nil
}

func setLabel(om *metav1.ObjectMeta, lblKey string, lblVal string) {
if len(lblVal) < 1 {
return
}

if om.Labels == nil {
om.Labels = make(map[string]string)
}

om.Labels[lblKey] = lblVal
}
Loading