diff --git a/broker/bucketbroker/server/bucket_create.go b/broker/bucketbroker/server/bucket_create.go index b8c37dc47..15aa8bc2e 100644 --- a/broker/bucketbroker/server/bucket_create.go +++ b/broker/bucketbroker/server/bucket_create.go @@ -9,12 +9,14 @@ import ( "github.com/go-logr/logr" storagev1alpha1 "github.com/ironcore-dev/ironcore/api/storage/v1alpha1" + brokerutils "github.com/ironcore-dev/ironcore/broker/common/utils" + bucketbrokerv1alpha1 "github.com/ironcore-dev/ironcore/broker/bucketbroker/api/v1alpha1" "github.com/ironcore-dev/ironcore/broker/bucketbroker/apiutils" iri "github.com/ironcore-dev/ironcore/iri/apis/bucket/v1alpha1" bucketpoolletv1alpha1 "github.com/ironcore-dev/ironcore/poollet/bucketpoollet/api/v1alpha1" - poolletutils "github.com/ironcore-dev/ironcore/poollet/common/utils" - "github.com/ironcore-dev/ironcore/utils/maps" + + utilsmaps "github.com/ironcore-dev/ironcore/utils/maps" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -25,22 +27,6 @@ type AggregateIronCoreBucket struct { AccessSecret *corev1.Secret } -func (s *Server) prepareIronCoreBucketLabels(bucket *iri.Bucket) map[string]string { - labels := make(map[string]string) - - for downwardAPILabelName, defaultLabelName := range s.brokerDownwardAPILabels { - value := bucket.GetMetadata().GetLabels()[poolletutils.DownwardAPILabel(bucketpoolletv1alpha1.BucketDownwardAPIPrefix, downwardAPILabelName)] - if value == "" { - value = bucket.GetMetadata().GetLabels()[defaultLabelName] - } - if value != "" { - labels[poolletutils.DownwardAPILabel(bucketpoolletv1alpha1.BucketDownwardAPIPrefix, downwardAPILabelName)] = value - } - } - - return labels -} - func (s *Server) getIronCoreBucketConfig(_ context.Context, bucket *iri.Bucket) (*AggregateIronCoreBucket, error) { var bucketPoolRef *corev1.LocalObjectReference if s.bucketPoolName != "" { @@ -48,12 +34,16 @@ func (s *Server) getIronCoreBucketConfig(_ context.Context, bucket *iri.Bucket) Name: s.bucketPoolName, } } - labels := s.prepareIronCoreBucketLabels(bucket) + labels := brokerutils.PrepareDownwardAPILabels( + bucket.GetMetadata().GetLabels(), + s.brokerDownwardAPILabels, + bucketpoolletv1alpha1.BucketDownwardAPIPrefix, + ) ironcoreBucket := &storagev1alpha1.Bucket{ ObjectMeta: metav1.ObjectMeta{ Namespace: s.namespace, Name: s.generateID(), - Labels: maps.AppendMap(labels, map[string]string{ + Labels: utilsmaps.AppendMap(labels, map[string]string{ bucketbrokerv1alpha1.ManagerLabel: bucketbrokerv1alpha1.BucketBrokerManager, }), }, diff --git a/broker/common/utils/utils.go b/broker/common/utils/utils.go index 6b9c4ad90..fb91c0d11 100644 --- a/broker/common/utils/utils.go +++ b/broker/common/utils/utils.go @@ -6,6 +6,8 @@ package utils import ( "context" + poolletutils "github.com/ironcore-dev/ironcore/poollet/common/utils" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/client" @@ -55,3 +57,22 @@ func ClientObjectGetter[ObjPtr ObjectPtr[Obj], Obj any]( return objPtr, nil } } + +func PrepareDownwardAPILabels( + labelSource map[string]string, + downwardAPILabels map[string]string, + prefix string, +) map[string]string { + preparedLabels := make(map[string]string) + for downwardAPILabelName, defaultLabelName := range downwardAPILabels { + key := poolletutils.DownwardAPILabel(prefix, downwardAPILabelName) + value := labelSource[key] + if value == "" { + value = labelSource[defaultLabelName] + } + if value != "" { + preparedLabels[key] = value + } + } + return preparedLabels +} diff --git a/broker/machinebroker/networks/networks.go b/broker/machinebroker/networks/networks.go index 1b88c984b..43471ed57 100644 --- a/broker/machinebroker/networks/networks.go +++ b/broker/machinebroker/networks/networks.go @@ -14,6 +14,7 @@ import ( networkingv1alpha1 "github.com/ironcore-dev/ironcore/api/networking/v1alpha1" machinebrokerv1alpha1 "github.com/ironcore-dev/ironcore/broker/machinebroker/api/v1alpha1" "github.com/ironcore-dev/ironcore/broker/machinebroker/cluster" + utilsmaps "github.com/ironcore-dev/ironcore/utils/maps" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/client-go/util/workqueue" @@ -42,9 +43,10 @@ func NewManager(cluster cluster.Cluster) *Manager { } type waiter struct { - network *networkingv1alpha1.Network - error error - done chan struct{} + network *networkingv1alpha1.Network + error error + done chan struct{} + networkLabels map[string]string } func (e *Manager) getNetworkForProviderID(ctx context.Context, providerID string) (*networkingv1alpha1.Network, error) { @@ -81,7 +83,7 @@ func (e *Manager) providerIDHash(providerID string) string { return rand.SafeEncodeString(fmt.Sprint(h.Sum32())) } -func (e *Manager) getOrCreateNetworkForProviderID(ctx context.Context, log logr.Logger, providerID string) (*networkingv1alpha1.Network, error) { +func (e *Manager) getOrCreateNetworkForProviderID(ctx context.Context, log logr.Logger, providerID string, labels map[string]string) (*networkingv1alpha1.Network, error) { network, err := e.getNetworkForProviderID(ctx, providerID) if err != nil { return nil, fmt.Errorf("error getting network for providerID: %w", err) @@ -102,9 +104,9 @@ func (e *Manager) getOrCreateNetworkForProviderID(ctx context.Context, log logr. Annotations: map[string]string{ commonv1alpha1.ManagedByAnnotation: machinebrokerv1alpha1.MachineBrokerManager, }, - Labels: map[string]string{ + Labels: utilsmaps.AppendMap(labels, map[string]string{ machinebrokerv1alpha1.ManagerLabel: machinebrokerv1alpha1.MachineBrokerManager, - }, + }), }, Spec: networkingv1alpha1.NetworkSpec{ ProviderID: providerID, @@ -125,9 +127,9 @@ func (e *Manager) setNetworkAsAvailable(ctx context.Context, network *networking return nil } -func (e *Manager) doWork(ctx context.Context, providerID string) (*networkingv1alpha1.Network, error) { +func (e *Manager) doWork(ctx context.Context, providerID string, labels map[string]string) (*networkingv1alpha1.Network, error) { log := ctrl.LoggerFrom(ctx) - network, err := e.getOrCreateNetworkForProviderID(ctx, log, providerID) + network, err := e.getOrCreateNetworkForProviderID(ctx, log, providerID, labels) if err != nil { return nil, fmt.Errorf("error getting / creating network for providerID: %w", err) } @@ -150,7 +152,14 @@ func (e *Manager) processNextWorkItem(ctx context.Context) bool { } defer e.queue.Done(providerID) - network, err := e.doWork(ctx, providerID) + var labels map[string]string + e.waitersByProviderIDMu.Lock() + if w, ok := e.waitersByProviderID[providerID]; ok { + labels = w.networkLabels + } + e.waitersByProviderIDMu.Unlock() + + network, err := e.doWork(ctx, providerID, labels) e.emit(providerID, network, err) e.queue.Forget(providerID) return true @@ -188,7 +197,7 @@ func (e *Manager) Start(ctx context.Context) error { return nil } -func (e *Manager) getOrCreateWaiter(providerID string) *waiter { +func (e *Manager) getOrCreateWaiter(providerID string, labels map[string]string) *waiter { e.waitersByProviderIDMu.Lock() defer e.waitersByProviderIDMu.Unlock() @@ -197,7 +206,9 @@ func (e *Manager) getOrCreateWaiter(providerID string) *waiter { return w } - w = &waiter{done: make(chan struct{})} + w = &waiter{ + done: make(chan struct{}), + networkLabels: labels} e.waitersByProviderID[providerID] = w e.queue.Add(providerID) return w @@ -220,8 +231,8 @@ func (e *Manager) emit(providerID string, network *networkingv1alpha1.Network, e delete(e.waitersByProviderID, providerID) } -func (e *Manager) GetNetwork(ctx context.Context, providerID string) (*networkingv1alpha1.Network, error) { - w := e.getOrCreateWaiter(providerID) +func (e *Manager) GetNetwork(ctx context.Context, providerID string, labels map[string]string) (*networkingv1alpha1.Network, error) { + w := e.getOrCreateWaiter(providerID, labels) select { case <-ctx.Done(): return nil, ctx.Err() diff --git a/broker/machinebroker/server/machine.go b/broker/machinebroker/server/machine.go index 9a3fef6b1..9149c4d3d 100644 --- a/broker/machinebroker/server/machine.go +++ b/broker/machinebroker/server/machine.go @@ -9,7 +9,6 @@ import ( computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1" networkingv1alpha1 "github.com/ironcore-dev/ironcore/api/networking/v1alpha1" storagev1alpha1 "github.com/ironcore-dev/ironcore/api/storage/v1alpha1" - machinebrokerv1alpha1 "github.com/ironcore-dev/ironcore/broker/machinebroker/api/v1alpha1" "github.com/ironcore-dev/ironcore/broker/machinebroker/apiutils" iri "github.com/ironcore-dev/ironcore/iri/apis/machine/v1alpha1" corev1 "k8s.io/api/core/v1" @@ -169,16 +168,11 @@ func (s *Server) convertIronCoreNetworkInterfaceAttachment( return nil, err } - labels := ironcoreNic.NetworkInterface.GetLabels() - //TODO Remove once labels are not part of API - delete(labels, machinebrokerv1alpha1.ManagerLabel) - return &iri.NetworkInterface{ Name: ironcoreMachineNic.Name, NetworkId: ironcoreNic.Network.Spec.ProviderID, Ips: ips, Attributes: ironcoreNic.NetworkInterface.Spec.Attributes, - Labels: labels, }, nil default: return nil, fmt.Errorf("unrecognized ironcore machine network interface %#v", ironcoreMachineNic) diff --git a/broker/machinebroker/server/machine_create.go b/broker/machinebroker/server/machine_create.go index 16abcd847..f71dddcd1 100644 --- a/broker/machinebroker/server/machine_create.go +++ b/broker/machinebroker/server/machine_create.go @@ -11,14 +11,14 @@ import ( commonv1alpha1 "github.com/ironcore-dev/ironcore/api/common/v1alpha1" computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1" "github.com/ironcore-dev/ironcore/broker/common/cleaner" + brokerutils "github.com/ironcore-dev/ironcore/broker/common/utils" machinebrokerv1alpha1 "github.com/ironcore-dev/ironcore/broker/machinebroker/api/v1alpha1" + utilsmaps "github.com/ironcore-dev/ironcore/utils/maps" + "github.com/ironcore-dev/ironcore/broker/machinebroker/apiutils" machinepoolletv1alpha1 "github.com/ironcore-dev/ironcore/poollet/machinepoollet/api/v1alpha1" - poolletutils "github.com/ironcore-dev/ironcore/poollet/common/utils" - iri "github.com/ironcore-dev/ironcore/iri/apis/machine/v1alpha1" - "github.com/ironcore-dev/ironcore/utils/maps" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -52,22 +52,6 @@ func (s *Server) prepareIronCoreMachinePower(power iri.Power) (computev1alpha1.P } } -func (s *Server) prepareIronCoreMachineLabels(machine *iri.Machine) map[string]string { - labels := make(map[string]string) - - for downwardAPILabelName, defaultLabelName := range s.brokerDownwardAPILabels { - value := machine.GetMetadata().GetLabels()[poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, downwardAPILabelName)] - if value == "" { - value = machine.GetMetadata().GetLabels()[defaultLabelName] - } - if value != "" { - labels[poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, downwardAPILabelName)] = value - } - } - - return labels -} - func (s *Server) prepareIronCoreMachineAnnotations(machine *iri.Machine) (map[string]string, error) { annotationsValue, err := apiutils.EncodeAnnotationsAnnotation(machine.GetMetadata().GetAnnotations()) if err != nil { @@ -116,7 +100,11 @@ func (s *Server) getIronCoreMachineConfig(machine *iri.Machine) (*IronCoreMachin ironcoreVolumeCfgs[i] = ironcoreVolumeCfg } - labels := s.prepareIronCoreMachineLabels(machine) + labels := brokerutils.PrepareDownwardAPILabels( + machine.GetMetadata().GetLabels(), + s.brokerDownwardAPILabels, + machinepoolletv1alpha1.MachineDownwardAPIPrefix, + ) annotations, err := s.prepareIronCoreMachineAnnotations(machine) if err != nil { return nil, fmt.Errorf("error preparing ironcore machine annotations: %w", err) @@ -201,7 +189,7 @@ func (s *Server) createIronCoreMachine( Namespace: s.cluster.Namespace(), Name: s.cluster.IDGen().Generate(), Annotations: cfg.Annotations, - Labels: maps.AppendMap(cfg.Labels, map[string]string{ + Labels: utilsmaps.AppendMap(cfg.Labels, map[string]string{ machinebrokerv1alpha1.ManagerLabel: machinebrokerv1alpha1.MachineBrokerManager, }), }, diff --git a/broker/machinebroker/server/machine_list.go b/broker/machinebroker/server/machine_list.go index 5764dc947..72ac7ec7a 100644 --- a/broker/machinebroker/server/machine_list.go +++ b/broker/machinebroker/server/machine_list.go @@ -107,7 +107,7 @@ func (s *Server) aggregateIronCoreMachine( aggIronCoreNic, err := s.aggregateIronCoreNetworkInterface(ctx, rd, ironcoreNic) if err != nil { - return nil, fmt.Errorf("error aggregating network interface: %w", err) + return nil, fmt.Errorf("error aggregating ironcore network interface %s: %w", ironcoreNic.Name, err) } aggIronCoreNics[machineNic.Name] = aggIronCoreNic diff --git a/broker/machinebroker/server/machine_networkinterface_attach.go b/broker/machinebroker/server/machine_networkinterface_attach.go index bc6f61173..18a30f0fc 100644 --- a/broker/machinebroker/server/machine_networkinterface_attach.go +++ b/broker/machinebroker/server/machine_networkinterface_attach.go @@ -5,6 +5,7 @@ package server import ( "context" + "encoding/json" "fmt" "github.com/go-logr/logr" @@ -12,12 +13,12 @@ import ( computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1" networkingv1alpha1 "github.com/ironcore-dev/ironcore/api/networking/v1alpha1" "github.com/ironcore-dev/ironcore/broker/common/cleaner" + brokerutils "github.com/ironcore-dev/ironcore/broker/common/utils" machinebrokerv1alpha1 "github.com/ironcore-dev/ironcore/broker/machinebroker/api/v1alpha1" "github.com/ironcore-dev/ironcore/broker/machinebroker/apiutils" iri "github.com/ironcore-dev/ironcore/iri/apis/machine/v1alpha1" - poolletutils "github.com/ironcore-dev/ironcore/poollet/common/utils" machinepoolletv1alpha1 "github.com/ironcore-dev/ironcore/poollet/machinepoollet/api/v1alpha1" - "github.com/ironcore-dev/ironcore/utils/maps" + utilsmaps "github.com/ironcore-dev/ironcore/utils/maps" "google.golang.org/grpc/codes" grpcstatus "google.golang.org/grpc/status" corev1 "k8s.io/api/core/v1" @@ -26,43 +27,57 @@ import ( ) type IronCoreNetworkInterfaceConfig struct { - Name string - NetworkID string - IPs []commonv1alpha1.IP - Attributes map[string]string - Labels map[string]string + Name string + NetworkID string + IPs []commonv1alpha1.IP + Attributes map[string]string + NICLabels map[string]string + NetworkLabels map[string]string } -func (s *Server) prepareIronCoreNetworkInterfaceLabels(networkinterface *iri.NetworkInterface) map[string]string { - labels := make(map[string]string) - - for downwardAPILabelName, defaultLabelName := range s.brokerDownwardAPILabels { - value := networkinterface.GetLabels()[poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, downwardAPILabelName)] - if value == "" { - value = networkinterface.GetLabels()[defaultLabelName] - } - if value != "" { - labels[poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, downwardAPILabelName)] = value - } - } - - return labels -} func (s *Server) getIronCoreNetworkInterfaceConfig(iriNIC *iri.NetworkInterface) (*IronCoreNetworkInterfaceConfig, error) { ips, err := s.parseIPs(iriNIC.Ips) if err != nil { return nil, err } - labels := s.prepareIronCoreNetworkInterfaceLabels(iriNIC) + var preparedNicLabels, preparedNetworkLabels map[string]string + attributes := iriNIC.GetAttributes() + if attributes != nil { + preparedNicLabels, preparedNetworkLabels, err = s.prepareLabelsFromAttributes(iriNIC.GetAttributes()) + if err != nil { + return nil, err + } + } return &IronCoreNetworkInterfaceConfig{ - Name: iriNIC.Name, - NetworkID: iriNIC.NetworkId, - IPs: ips, - Attributes: iriNIC.Attributes, - Labels: labels, + Name: iriNIC.Name, + NetworkID: iriNIC.NetworkId, + IPs: ips, + Attributes: iriNIC.Attributes, + NICLabels: preparedNicLabels, + NetworkLabels: preparedNetworkLabels, }, nil } +func (s *Server) prepareLabelsFromAttributes(attrs map[string]string) (map[string]string, map[string]string, error) { + var nicLabels, networkLabels map[string]string + + if nicLabelsString, ok := attrs[machinepoolletv1alpha1.NICLabelsAttributeKey]; ok { + if err := json.Unmarshal([]byte(nicLabelsString), &nicLabels); err != nil { + return nil, nil, fmt.Errorf("error unmarshaling labels: %w", err) + } + } + + if networkLabelsString, ok := attrs[machinepoolletv1alpha1.NetworkLabelsAttributeKey]; ok { + if err := json.Unmarshal([]byte(networkLabelsString), &networkLabels); err != nil { + return nil, nil, fmt.Errorf("error unmarshaling labels: %w", err) + } + } + preparedNicLabels := brokerutils.PrepareDownwardAPILabels(nicLabels, s.brokerDownwardAPILabels, machinepoolletv1alpha1.MachineDownwardAPIPrefix) + preparedNetworkLabels := brokerutils.PrepareDownwardAPILabels(networkLabels, s.brokerDownwardAPILabels, machinepoolletv1alpha1.MachineDownwardAPIPrefix) + + return preparedNicLabels, preparedNetworkLabels, nil +} + func (s *Server) createIronCoreNetworkInterface( ctx context.Context, log logr.Logger, @@ -71,7 +86,8 @@ func (s *Server) createIronCoreNetworkInterface( cfg *IronCoreNetworkInterfaceConfig, ) (ironcoreMachineNic *computev1alpha1.NetworkInterface, aggIronCoreNic *AggregateIronCoreNetworkInterface, retErr error) { log.V(1).Info("Getting network for handle") - ironcoreNetwork, err := s.networks.GetNetwork(ctx, cfg.NetworkID) + + ironcoreNetwork, err := s.networks.GetNetwork(ctx, cfg.NetworkID, cfg.NetworkLabels) if err != nil { return nil, nil, fmt.Errorf("error getting network: %w", err) } @@ -83,7 +99,7 @@ func (s *Server) createIronCoreNetworkInterface( Annotations: map[string]string{ commonv1alpha1.ManagedByAnnotation: machinebrokerv1alpha1.MachineBrokerManager, }, - Labels: maps.AppendMap(cfg.Labels, map[string]string{ + Labels: utilsmaps.AppendMap(cfg.NICLabels, map[string]string{ machinebrokerv1alpha1.ManagerLabel: machinebrokerv1alpha1.MachineBrokerManager, }), OwnerReferences: s.optionalOwnerReferences(ironcoreMachineGVK, optIronCoreMachine), @@ -96,6 +112,7 @@ func (s *Server) createIronCoreNetworkInterface( Attributes: cfg.Attributes, }, } + log.V(1).Info("Creating ironcore network interface") if err := s.cluster.Client().Create(ctx, ironcoreNic); err != nil { return nil, nil, fmt.Errorf("error creating ironcore network interface: %w", err) diff --git a/broker/machinebroker/server/machine_networkinterface_attach_test.go b/broker/machinebroker/server/machine_networkinterface_attach_test.go index ad140ec45..0aa5606fb 100644 --- a/broker/machinebroker/server/machine_networkinterface_attach_test.go +++ b/broker/machinebroker/server/machine_networkinterface_attach_test.go @@ -4,6 +4,8 @@ package server_test import ( + "encoding/json" + commonv1alpha1 "github.com/ironcore-dev/ironcore/api/common/v1alpha1" computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1" networkingv1alpha1 "github.com/ironcore-dev/ironcore/api/networking/v1alpha1" @@ -14,6 +16,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gstruct" + apierrors "k8s.io/apimachinery/pkg/api/errors" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -39,14 +42,22 @@ var _ = Describe("AttachNetworkInterface", func() { machineID := createMachineRes.Machine.Metadata.Id By("attaching a network interface") + nicLabels := map[string]string{ + machinepoolletv1alpha1.NetworkInterfaceUIDLabel: "foobar", + } + networkLabels := map[string]string{ + machinepoolletv1alpha1.NetworkUIDLabel: "bar", + } + Expect(srv.AttachNetworkInterface(ctx, &iri.AttachNetworkInterfaceRequest{ MachineId: machineID, NetworkInterface: &iri.NetworkInterface{ Name: "my-nic", NetworkId: "network-id", Ips: []string{"10.0.0.1"}, - Labels: map[string]string{ - machinepoolletv1alpha1.NetworkInterfaceUIDLabel: "foobar", + Attributes: map[string]string{ + machinepoolletv1alpha1.NICLabelsAttributeKey: string(mustMarshalJSON(nicLabels)), + machinepoolletv1alpha1.NetworkLabelsAttributeKey: string(mustMarshalJSON(networkLabels)), }, }, })).Error().NotTo(HaveOccurred()) @@ -73,14 +84,13 @@ var _ = Describe("AttachNetworkInterface", func() { Expect(k8sClient.Get(ctx, nicKey, nic)).To(Succeed()) By("inspecting the ironcore network interface") + Expect(nic.Spec.IPs).To(Equal([]networkingv1alpha1.IPSource{ + {Value: commonv1alpha1.MustParseNewIP("10.0.0.1")}, + })) Expect(nic.Labels).To(Equal(map[string]string{ poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-nic-uid"): "foobar", machinebrokerv1alpha1.ManagerLabel: machinebrokerv1alpha1.MachineBrokerManager, })) - By("inspecting the ironcore network interface") - Expect(nic.Spec.IPs).To(Equal([]networkingv1alpha1.IPSource{ - {Value: commonv1alpha1.MustParseNewIP("10.0.0.1")}, - })) By("getting the referenced ironcore network") network := &networkingv1alpha1.Network{} @@ -94,6 +104,10 @@ var _ = Describe("AttachNetworkInterface", func() { Expect(network.Status).To(Equal(networkingv1alpha1.NetworkStatus{ State: networkingv1alpha1.NetworkStateAvailable, })) + Expect(network.Labels).To(Equal(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-network-uid"): "bar", + machinebrokerv1alpha1.ManagerLabel: machinebrokerv1alpha1.MachineBrokerManager, + })) }) It("should correctly re-create a network in case it has been removed", func(ctx SpecContext) { @@ -113,12 +127,22 @@ var _ = Describe("AttachNetworkInterface", func() { machineID := createMachineRes.Machine.Metadata.Id By("attaching a network interface") + nicLabels := map[string]string{ + machinepoolletv1alpha1.NetworkInterfaceUIDLabel: "foobar", + } + networkLabels := map[string]string{ + machinepoolletv1alpha1.NetworkUIDLabel: "bar", + } Expect(srv.AttachNetworkInterface(ctx, &iri.AttachNetworkInterfaceRequest{ MachineId: machineID, NetworkInterface: &iri.NetworkInterface{ Name: "my-nic", NetworkId: "network-id", Ips: []string{"10.0.0.1"}, + Attributes: map[string]string{ + machinepoolletv1alpha1.NICLabelsAttributeKey: string(mustMarshalJSON(nicLabels)), + machinepoolletv1alpha1.NetworkLabelsAttributeKey: string(mustMarshalJSON(networkLabels)), + }, }, })).Error().NotTo(HaveOccurred()) @@ -147,6 +171,10 @@ var _ = Describe("AttachNetworkInterface", func() { Expect(nic.Spec.IPs).To(Equal([]networkingv1alpha1.IPSource{ {Value: commonv1alpha1.MustParseNewIP("10.0.0.1")}, })) + Expect(nic.Labels).To(Equal(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-nic-uid"): "foobar", + machinebrokerv1alpha1.ManagerLabel: machinebrokerv1alpha1.MachineBrokerManager, + })) By("getting the referenced ironcore network") network := &networkingv1alpha1.Network{} @@ -160,6 +188,10 @@ var _ = Describe("AttachNetworkInterface", func() { Expect(network.Status).To(Equal(networkingv1alpha1.NetworkStatus{ State: networkingv1alpha1.NetworkStateAvailable, })) + Expect(network.Labels).To(Equal(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-network-uid"): "bar", + machinebrokerv1alpha1.ManagerLabel: machinebrokerv1alpha1.MachineBrokerManager, + })) By("detaching the network interface") Expect(srv.DetachNetworkInterface(ctx, &iri.DetachNetworkInterfaceRequest{ @@ -183,6 +215,10 @@ var _ = Describe("AttachNetworkInterface", func() { Name: "my-nic", NetworkId: "network-id", Ips: []string{"10.0.0.1"}, + Attributes: map[string]string{ + machinepoolletv1alpha1.NICLabelsAttributeKey: string(mustMarshalJSON(nicLabels)), + machinepoolletv1alpha1.NetworkLabelsAttributeKey: string(mustMarshalJSON(networkLabels)), + }, }, })).Error().NotTo(HaveOccurred()) @@ -193,5 +229,17 @@ var _ = Describe("AttachNetworkInterface", func() { Expect(network.Status).To(Equal(networkingv1alpha1.NetworkStatus{ State: networkingv1alpha1.NetworkStateAvailable, })) + Expect(network.Labels).To(Equal(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-network-uid"): "bar", + machinebrokerv1alpha1.ManagerLabel: machinebrokerv1alpha1.MachineBrokerManager, + })) }) }) + +func mustMarshalJSON(v interface{}) string { + data, err := json.Marshal(v) + if err != nil { + panic(err) + } + return string(data) +} diff --git a/broker/machinebroker/server/networkinterface.go b/broker/machinebroker/server/networkinterface.go index e9f25e788..13d9bfda7 100644 --- a/broker/machinebroker/server/networkinterface.go +++ b/broker/machinebroker/server/networkinterface.go @@ -45,7 +45,7 @@ func (s *Server) aggregateIronCoreNetworkInterface( ironcoreNetwork := &networkingv1alpha1.Network{} ironcoreNetworkKey := client.ObjectKey{Namespace: s.cluster.Namespace(), Name: ironcoreNic.Spec.NetworkRef.Name} if err := rd.Get(ctx, ironcoreNetworkKey, ironcoreNetwork); err != nil { - return nil, fmt.Errorf("error getting ironcore network %s: %w", ironcoreNic.Name, err) + return nil, fmt.Errorf("error getting ironcore network: %w", err) } return &AggregateIronCoreNetworkInterface{ diff --git a/broker/machinebroker/server/server_suite_test.go b/broker/machinebroker/server/server_suite_test.go index b48e5c3a1..de315d058 100644 --- a/broker/machinebroker/server/server_suite_test.go +++ b/broker/machinebroker/server/server_suite_test.go @@ -138,6 +138,7 @@ func SetupTest() (*corev1.Namespace, *server.Server) { BrokerDownwardAPILabels: map[string]string{ "root-machine-uid": machinepoolletv1alpha1.MachineUIDLabel, "root-nic-uid": machinepoolletv1alpha1.NetworkInterfaceUIDLabel, + "root-network-uid": machinepoolletv1alpha1.NetworkUIDLabel, }, }) Expect(err).NotTo(HaveOccurred()) diff --git a/broker/volumebroker/server/volume_create.go b/broker/volumebroker/server/volume_create.go index a27c084b1..596fe8bc9 100644 --- a/broker/volumebroker/server/volume_create.go +++ b/broker/volumebroker/server/volume_create.go @@ -10,13 +10,14 @@ import ( "github.com/go-logr/logr" corev1alpha1 "github.com/ironcore-dev/ironcore/api/core/v1alpha1" storagev1alpha1 "github.com/ironcore-dev/ironcore/api/storage/v1alpha1" + brokerutils "github.com/ironcore-dev/ironcore/broker/common/utils" volumebrokerv1alpha1 "github.com/ironcore-dev/ironcore/broker/volumebroker/api/v1alpha1" + "github.com/ironcore-dev/ironcore/broker/volumebroker/apiutils" iri "github.com/ironcore-dev/ironcore/iri/apis/volume/v1alpha1" - poolletutils "github.com/ironcore-dev/ironcore/poollet/common/utils" volumepoolletv1alpha1 "github.com/ironcore-dev/ironcore/poollet/volumepoollet/api/v1alpha1" - "github.com/ironcore-dev/ironcore/utils/maps" + utilsmaps "github.com/ironcore-dev/ironcore/utils/maps" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -29,22 +30,6 @@ type AggregateIronCoreVolume struct { AccessSecret *corev1.Secret } -func (s *Server) prepareIronCoreVolumeLabels(volume *iri.Volume) map[string]string { - labels := make(map[string]string) - - for downwardAPILabelName, defaultLabelName := range s.brokerDownwardAPILabels { - value := volume.GetMetadata().GetLabels()[poolletutils.DownwardAPILabel(volumepoolletv1alpha1.VolumeDownwardAPIPrefix, downwardAPILabelName)] - if value == "" { - value = volume.GetMetadata().GetLabels()[defaultLabelName] - } - if value != "" { - labels[poolletutils.DownwardAPILabel(volumepoolletv1alpha1.VolumeDownwardAPIPrefix, downwardAPILabelName)] = value - } - } - - return labels -} - func (s *Server) getIronCoreVolumeConfig(_ context.Context, volume *iri.Volume) (*AggregateIronCoreVolume, error) { var volumePoolRef *corev1.LocalObjectReference if s.volumePoolName != "" { @@ -75,13 +60,17 @@ func (s *Server) getIronCoreVolumeConfig(_ context.Context, volume *iri.Volume) } } - labels := s.prepareIronCoreVolumeLabels(volume) + labels := brokerutils.PrepareDownwardAPILabels( + volume.GetMetadata().GetLabels(), + s.brokerDownwardAPILabels, + volumepoolletv1alpha1.VolumeDownwardAPIPrefix, + ) ironcoreVolume := &storagev1alpha1.Volume{ ObjectMeta: metav1.ObjectMeta{ Namespace: s.namespace, Name: s.idGen.Generate(), - Labels: maps.AppendMap(labels, map[string]string{ + Labels: utilsmaps.AppendMap(labels, map[string]string{ volumebrokerv1alpha1.ManagerLabel: volumebrokerv1alpha1.VolumeBrokerManager, }), }, diff --git a/config/machinepoollet-broker/manager/manager.yaml b/config/machinepoollet-broker/manager/manager.yaml index a4b37bb71..69582c4b0 100644 --- a/config/machinepoollet-broker/manager/manager.yaml +++ b/config/machinepoollet-broker/manager/manager.yaml @@ -38,6 +38,9 @@ spec: - --nic-downward-api-label=root-nic-namespace=metadata.labels['downward-api.machinepoollet.ironcore.dev/root-nic-namespace'] - --nic-downward-api-label=root-nic-name=metadata.labels['downward-api.machinepoollet.ironcore.dev/root-nic-name'] - --nic-downward-api-label=root-nic-uid=metadata.labels['downward-api.machinepoollet.ironcore.dev/root-nic-uid'] + - --network-downward-api-label=root-network-namespace=metadata.labels['downward-api.machinepoollet.ironcore.dev/root-network-namespace'] + - --network-downward-api-label=root-network-name=metadata.labels['downward-api.machinepoollet.ironcore.dev/root-network-name'] + - --network-downward-api-label=root-network-uid=metadata.labels['downward-api.machinepoollet.ironcore.dev/root-network-uid'] image: machinepoollet:latest env: - name: KUBERNETES_SERVICE_NAME @@ -86,6 +89,9 @@ spec: - --broker-downward-api-label=root-nic-namespace=machinepoollet.ironcore.dev/nic-namespace - --broker-downward-api-label=root-nic-name=machinepoollet.ironcore.dev/nic-name - --broker-downward-api-label=root-nic-uid=machinepoollet.ironcore.dev/nic-uid + - --broker-downward-api-label=root-network-namespace=machinepoollet.ironcore.dev/network-namespace + - --broker-downward-api-label=root-network-name=machinepoollet.ironcore.dev/network-name + - --broker-downward-api-label=root-network-uid=machinepoollet.ironcore.dev/network-uid securityContext: allowPrivilegeEscalation: false livenessProbe: diff --git a/iri/apis/machine/v1alpha1/api.pb.go b/iri/apis/machine/v1alpha1/api.pb.go index 9a0ccc9c3..e1228182b 100644 --- a/iri/apis/machine/v1alpha1/api.pb.go +++ b/iri/apis/machine/v1alpha1/api.pb.go @@ -758,7 +758,6 @@ type NetworkInterface struct { NetworkId string `protobuf:"bytes,2,opt,name=network_id,json=networkId,proto3" json:"network_id,omitempty"` Ips []string `protobuf:"bytes,3,rep,name=ips,proto3" json:"ips,omitempty"` Attributes map[string]string `protobuf:"bytes,4,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - Labels map[string]string `protobuf:"bytes,5,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -821,13 +820,6 @@ func (x *NetworkInterface) GetAttributes() map[string]string { return nil } -func (x *NetworkInterface) GetLabels() map[string]string { - if x != nil { - return x.Labels - } - return nil -} - type MachineSpec struct { state protoimpl.MessageState `protogen:"open.v1"` Power Power `protobuf:"varint,1,opt,name=power,proto3,enum=machine.v1alpha1.Power" json:"power,omitempty"` @@ -2513,7 +2505,7 @@ const file_machine_v1alpha1_api_proto_rawDesc = "" + "empty_disk\x18\x04 \x01(\v2\x1b.machine.v1alpha1.EmptyDiskR\temptyDisk\x12B\n" + "\n" + "connection\x18\x05 \x01(\v2\".machine.v1alpha1.VolumeConnectionR\n" + - "connection\"\xed\x02\n" + + "connection\"\xea\x01\n" + "\x10NetworkInterface\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12\x1d\n" + "\n" + @@ -2521,13 +2513,9 @@ const file_machine_v1alpha1_api_proto_rawDesc = "" + "\x03ips\x18\x03 \x03(\tR\x03ips\x12R\n" + "\n" + "attributes\x18\x04 \x03(\v22.machine.v1alpha1.NetworkInterface.AttributesEntryR\n" + - "attributes\x12F\n" + - "\x06labels\x18\x05 \x03(\v2..machine.v1alpha1.NetworkInterface.LabelsEntryR\x06labels\x1a=\n" + + "attributes\x1a=\n" + "\x0fAttributesEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\x1a9\n" + - "\vLabelsEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xb1\x02\n" + "\vMachineSpec\x12-\n" + "\x05power\x18\x01 \x01(\x0e2\x17.machine.v1alpha1.PowerR\x05power\x121\n" + @@ -2669,7 +2657,7 @@ func file_machine_v1alpha1_api_proto_rawDescGZIP() []byte { } var file_machine_v1alpha1_api_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_machine_v1alpha1_api_proto_msgTypes = make([]protoimpl.MessageInfo, 55) +var file_machine_v1alpha1_api_proto_msgTypes = make([]protoimpl.MessageInfo, 54) var file_machine_v1alpha1_api_proto_goTypes = []any{ (Power)(0), // 0: machine.v1alpha1.Power (VolumeState)(0), // 1: machine.v1alpha1.VolumeState @@ -2728,10 +2716,9 @@ var file_machine_v1alpha1_api_proto_goTypes = []any{ nil, // 54: machine.v1alpha1.VolumeConnection.SecretDataEntry nil, // 55: machine.v1alpha1.VolumeConnection.EncryptionDataEntry nil, // 56: machine.v1alpha1.NetworkInterface.AttributesEntry - nil, // 57: machine.v1alpha1.NetworkInterface.LabelsEntry - nil, // 58: machine.v1alpha1.UpdateMachineAnnotationsRequest.AnnotationsEntry - (*v1alpha1.ObjectMetadata)(nil), // 59: meta.v1alpha1.ObjectMetadata - (*v1alpha11.Event)(nil), // 60: event.v1alpha1.Event + nil, // 57: machine.v1alpha1.UpdateMachineAnnotationsRequest.AnnotationsEntry + (*v1alpha1.ObjectMetadata)(nil), // 58: meta.v1alpha1.ObjectMetadata + (*v1alpha11.Event)(nil), // 59: event.v1alpha1.Event } var file_machine_v1alpha1_api_proto_depIdxs = []int32{ 48, // 0: machine.v1alpha1.VolumeSpec.attributes:type_name -> machine.v1alpha1.VolumeSpec.AttributesEntry @@ -2739,7 +2726,7 @@ var file_machine_v1alpha1_api_proto_depIdxs = []int32{ 50, // 2: machine.v1alpha1.MachineFilter.label_selector:type_name -> machine.v1alpha1.MachineFilter.LabelSelectorEntry 51, // 3: machine.v1alpha1.EventFilter.label_selector:type_name -> machine.v1alpha1.EventFilter.LabelSelectorEntry 52, // 4: machine.v1alpha1.MachineClassCapabilities.resources:type_name -> machine.v1alpha1.MachineClassCapabilities.ResourcesEntry - 59, // 5: machine.v1alpha1.Machine.metadata:type_name -> meta.v1alpha1.ObjectMetadata + 58, // 5: machine.v1alpha1.Machine.metadata:type_name -> meta.v1alpha1.ObjectMetadata 14, // 6: machine.v1alpha1.Machine.spec:type_name -> machine.v1alpha1.MachineSpec 15, // 7: machine.v1alpha1.Machine.status:type_name -> machine.v1alpha1.MachineStatus 53, // 8: machine.v1alpha1.VolumeConnection.attributes:type_name -> machine.v1alpha1.VolumeConnection.AttributesEntry @@ -2748,63 +2735,62 @@ var file_machine_v1alpha1_api_proto_depIdxs = []int32{ 10, // 11: machine.v1alpha1.Volume.empty_disk:type_name -> machine.v1alpha1.EmptyDisk 11, // 12: machine.v1alpha1.Volume.connection:type_name -> machine.v1alpha1.VolumeConnection 56, // 13: machine.v1alpha1.NetworkInterface.attributes:type_name -> machine.v1alpha1.NetworkInterface.AttributesEntry - 57, // 14: machine.v1alpha1.NetworkInterface.labels:type_name -> machine.v1alpha1.NetworkInterface.LabelsEntry - 0, // 15: machine.v1alpha1.MachineSpec.power:type_name -> machine.v1alpha1.Power - 9, // 16: machine.v1alpha1.MachineSpec.image:type_name -> machine.v1alpha1.ImageSpec - 12, // 17: machine.v1alpha1.MachineSpec.volumes:type_name -> machine.v1alpha1.Volume - 13, // 18: machine.v1alpha1.MachineSpec.network_interfaces:type_name -> machine.v1alpha1.NetworkInterface - 3, // 19: machine.v1alpha1.MachineStatus.state:type_name -> machine.v1alpha1.MachineState - 16, // 20: machine.v1alpha1.MachineStatus.volumes:type_name -> machine.v1alpha1.VolumeStatus - 17, // 21: machine.v1alpha1.MachineStatus.network_interfaces:type_name -> machine.v1alpha1.NetworkInterfaceStatus - 1, // 22: machine.v1alpha1.VolumeStatus.state:type_name -> machine.v1alpha1.VolumeState - 2, // 23: machine.v1alpha1.NetworkInterfaceStatus.state:type_name -> machine.v1alpha1.NetworkInterfaceState - 7, // 24: machine.v1alpha1.MachineClass.capabilities:type_name -> machine.v1alpha1.MachineClassCapabilities - 18, // 25: machine.v1alpha1.MachineClassStatus.machine_class:type_name -> machine.v1alpha1.MachineClass - 5, // 26: machine.v1alpha1.ListMachinesRequest.filter:type_name -> machine.v1alpha1.MachineFilter - 8, // 27: machine.v1alpha1.ListMachinesResponse.machines:type_name -> machine.v1alpha1.Machine - 6, // 28: machine.v1alpha1.ListEventsRequest.filter:type_name -> machine.v1alpha1.EventFilter - 60, // 29: machine.v1alpha1.ListEventsResponse.events:type_name -> event.v1alpha1.Event - 8, // 30: machine.v1alpha1.CreateMachineRequest.machine:type_name -> machine.v1alpha1.Machine - 8, // 31: machine.v1alpha1.CreateMachineResponse.machine:type_name -> machine.v1alpha1.Machine - 58, // 32: machine.v1alpha1.UpdateMachineAnnotationsRequest.annotations:type_name -> machine.v1alpha1.UpdateMachineAnnotationsRequest.AnnotationsEntry - 0, // 33: machine.v1alpha1.UpdateMachinePowerRequest.power:type_name -> machine.v1alpha1.Power - 12, // 34: machine.v1alpha1.AttachVolumeRequest.volume:type_name -> machine.v1alpha1.Volume - 12, // 35: machine.v1alpha1.UpdateVolumeRequest.volume:type_name -> machine.v1alpha1.Volume - 13, // 36: machine.v1alpha1.AttachNetworkInterfaceRequest.network_interface:type_name -> machine.v1alpha1.NetworkInterface - 19, // 37: machine.v1alpha1.StatusResponse.machine_class_status:type_name -> machine.v1alpha1.MachineClassStatus - 20, // 38: machine.v1alpha1.MachineRuntime.Version:input_type -> machine.v1alpha1.VersionRequest - 24, // 39: machine.v1alpha1.MachineRuntime.ListEvents:input_type -> machine.v1alpha1.ListEventsRequest - 22, // 40: machine.v1alpha1.MachineRuntime.ListMachines:input_type -> machine.v1alpha1.ListMachinesRequest - 26, // 41: machine.v1alpha1.MachineRuntime.CreateMachine:input_type -> machine.v1alpha1.CreateMachineRequest - 28, // 42: machine.v1alpha1.MachineRuntime.DeleteMachine:input_type -> machine.v1alpha1.DeleteMachineRequest - 30, // 43: machine.v1alpha1.MachineRuntime.UpdateMachineAnnotations:input_type -> machine.v1alpha1.UpdateMachineAnnotationsRequest - 32, // 44: machine.v1alpha1.MachineRuntime.UpdateMachinePower:input_type -> machine.v1alpha1.UpdateMachinePowerRequest - 34, // 45: machine.v1alpha1.MachineRuntime.AttachVolume:input_type -> machine.v1alpha1.AttachVolumeRequest - 36, // 46: machine.v1alpha1.MachineRuntime.DetachVolume:input_type -> machine.v1alpha1.DetachVolumeRequest - 38, // 47: machine.v1alpha1.MachineRuntime.UpdateVolume:input_type -> machine.v1alpha1.UpdateVolumeRequest - 40, // 48: machine.v1alpha1.MachineRuntime.AttachNetworkInterface:input_type -> machine.v1alpha1.AttachNetworkInterfaceRequest - 42, // 49: machine.v1alpha1.MachineRuntime.DetachNetworkInterface:input_type -> machine.v1alpha1.DetachNetworkInterfaceRequest - 44, // 50: machine.v1alpha1.MachineRuntime.Status:input_type -> machine.v1alpha1.StatusRequest - 46, // 51: machine.v1alpha1.MachineRuntime.Exec:input_type -> machine.v1alpha1.ExecRequest - 21, // 52: machine.v1alpha1.MachineRuntime.Version:output_type -> machine.v1alpha1.VersionResponse - 25, // 53: machine.v1alpha1.MachineRuntime.ListEvents:output_type -> machine.v1alpha1.ListEventsResponse - 23, // 54: machine.v1alpha1.MachineRuntime.ListMachines:output_type -> machine.v1alpha1.ListMachinesResponse - 27, // 55: machine.v1alpha1.MachineRuntime.CreateMachine:output_type -> machine.v1alpha1.CreateMachineResponse - 29, // 56: machine.v1alpha1.MachineRuntime.DeleteMachine:output_type -> machine.v1alpha1.DeleteMachineResponse - 31, // 57: machine.v1alpha1.MachineRuntime.UpdateMachineAnnotations:output_type -> machine.v1alpha1.UpdateMachineAnnotationsResponse - 33, // 58: machine.v1alpha1.MachineRuntime.UpdateMachinePower:output_type -> machine.v1alpha1.UpdateMachinePowerResponse - 35, // 59: machine.v1alpha1.MachineRuntime.AttachVolume:output_type -> machine.v1alpha1.AttachVolumeResponse - 37, // 60: machine.v1alpha1.MachineRuntime.DetachVolume:output_type -> machine.v1alpha1.DetachVolumeResponse - 39, // 61: machine.v1alpha1.MachineRuntime.UpdateVolume:output_type -> machine.v1alpha1.UpdateVolumeResponse - 41, // 62: machine.v1alpha1.MachineRuntime.AttachNetworkInterface:output_type -> machine.v1alpha1.AttachNetworkInterfaceResponse - 43, // 63: machine.v1alpha1.MachineRuntime.DetachNetworkInterface:output_type -> machine.v1alpha1.DetachNetworkInterfaceResponse - 45, // 64: machine.v1alpha1.MachineRuntime.Status:output_type -> machine.v1alpha1.StatusResponse - 47, // 65: machine.v1alpha1.MachineRuntime.Exec:output_type -> machine.v1alpha1.ExecResponse - 52, // [52:66] is the sub-list for method output_type - 38, // [38:52] is the sub-list for method input_type - 38, // [38:38] is the sub-list for extension type_name - 38, // [38:38] is the sub-list for extension extendee - 0, // [0:38] is the sub-list for field type_name + 0, // 14: machine.v1alpha1.MachineSpec.power:type_name -> machine.v1alpha1.Power + 9, // 15: machine.v1alpha1.MachineSpec.image:type_name -> machine.v1alpha1.ImageSpec + 12, // 16: machine.v1alpha1.MachineSpec.volumes:type_name -> machine.v1alpha1.Volume + 13, // 17: machine.v1alpha1.MachineSpec.network_interfaces:type_name -> machine.v1alpha1.NetworkInterface + 3, // 18: machine.v1alpha1.MachineStatus.state:type_name -> machine.v1alpha1.MachineState + 16, // 19: machine.v1alpha1.MachineStatus.volumes:type_name -> machine.v1alpha1.VolumeStatus + 17, // 20: machine.v1alpha1.MachineStatus.network_interfaces:type_name -> machine.v1alpha1.NetworkInterfaceStatus + 1, // 21: machine.v1alpha1.VolumeStatus.state:type_name -> machine.v1alpha1.VolumeState + 2, // 22: machine.v1alpha1.NetworkInterfaceStatus.state:type_name -> machine.v1alpha1.NetworkInterfaceState + 7, // 23: machine.v1alpha1.MachineClass.capabilities:type_name -> machine.v1alpha1.MachineClassCapabilities + 18, // 24: machine.v1alpha1.MachineClassStatus.machine_class:type_name -> machine.v1alpha1.MachineClass + 5, // 25: machine.v1alpha1.ListMachinesRequest.filter:type_name -> machine.v1alpha1.MachineFilter + 8, // 26: machine.v1alpha1.ListMachinesResponse.machines:type_name -> machine.v1alpha1.Machine + 6, // 27: machine.v1alpha1.ListEventsRequest.filter:type_name -> machine.v1alpha1.EventFilter + 59, // 28: machine.v1alpha1.ListEventsResponse.events:type_name -> event.v1alpha1.Event + 8, // 29: machine.v1alpha1.CreateMachineRequest.machine:type_name -> machine.v1alpha1.Machine + 8, // 30: machine.v1alpha1.CreateMachineResponse.machine:type_name -> machine.v1alpha1.Machine + 57, // 31: machine.v1alpha1.UpdateMachineAnnotationsRequest.annotations:type_name -> machine.v1alpha1.UpdateMachineAnnotationsRequest.AnnotationsEntry + 0, // 32: machine.v1alpha1.UpdateMachinePowerRequest.power:type_name -> machine.v1alpha1.Power + 12, // 33: machine.v1alpha1.AttachVolumeRequest.volume:type_name -> machine.v1alpha1.Volume + 12, // 34: machine.v1alpha1.UpdateVolumeRequest.volume:type_name -> machine.v1alpha1.Volume + 13, // 35: machine.v1alpha1.AttachNetworkInterfaceRequest.network_interface:type_name -> machine.v1alpha1.NetworkInterface + 19, // 36: machine.v1alpha1.StatusResponse.machine_class_status:type_name -> machine.v1alpha1.MachineClassStatus + 20, // 37: machine.v1alpha1.MachineRuntime.Version:input_type -> machine.v1alpha1.VersionRequest + 24, // 38: machine.v1alpha1.MachineRuntime.ListEvents:input_type -> machine.v1alpha1.ListEventsRequest + 22, // 39: machine.v1alpha1.MachineRuntime.ListMachines:input_type -> machine.v1alpha1.ListMachinesRequest + 26, // 40: machine.v1alpha1.MachineRuntime.CreateMachine:input_type -> machine.v1alpha1.CreateMachineRequest + 28, // 41: machine.v1alpha1.MachineRuntime.DeleteMachine:input_type -> machine.v1alpha1.DeleteMachineRequest + 30, // 42: machine.v1alpha1.MachineRuntime.UpdateMachineAnnotations:input_type -> machine.v1alpha1.UpdateMachineAnnotationsRequest + 32, // 43: machine.v1alpha1.MachineRuntime.UpdateMachinePower:input_type -> machine.v1alpha1.UpdateMachinePowerRequest + 34, // 44: machine.v1alpha1.MachineRuntime.AttachVolume:input_type -> machine.v1alpha1.AttachVolumeRequest + 36, // 45: machine.v1alpha1.MachineRuntime.DetachVolume:input_type -> machine.v1alpha1.DetachVolumeRequest + 38, // 46: machine.v1alpha1.MachineRuntime.UpdateVolume:input_type -> machine.v1alpha1.UpdateVolumeRequest + 40, // 47: machine.v1alpha1.MachineRuntime.AttachNetworkInterface:input_type -> machine.v1alpha1.AttachNetworkInterfaceRequest + 42, // 48: machine.v1alpha1.MachineRuntime.DetachNetworkInterface:input_type -> machine.v1alpha1.DetachNetworkInterfaceRequest + 44, // 49: machine.v1alpha1.MachineRuntime.Status:input_type -> machine.v1alpha1.StatusRequest + 46, // 50: machine.v1alpha1.MachineRuntime.Exec:input_type -> machine.v1alpha1.ExecRequest + 21, // 51: machine.v1alpha1.MachineRuntime.Version:output_type -> machine.v1alpha1.VersionResponse + 25, // 52: machine.v1alpha1.MachineRuntime.ListEvents:output_type -> machine.v1alpha1.ListEventsResponse + 23, // 53: machine.v1alpha1.MachineRuntime.ListMachines:output_type -> machine.v1alpha1.ListMachinesResponse + 27, // 54: machine.v1alpha1.MachineRuntime.CreateMachine:output_type -> machine.v1alpha1.CreateMachineResponse + 29, // 55: machine.v1alpha1.MachineRuntime.DeleteMachine:output_type -> machine.v1alpha1.DeleteMachineResponse + 31, // 56: machine.v1alpha1.MachineRuntime.UpdateMachineAnnotations:output_type -> machine.v1alpha1.UpdateMachineAnnotationsResponse + 33, // 57: machine.v1alpha1.MachineRuntime.UpdateMachinePower:output_type -> machine.v1alpha1.UpdateMachinePowerResponse + 35, // 58: machine.v1alpha1.MachineRuntime.AttachVolume:output_type -> machine.v1alpha1.AttachVolumeResponse + 37, // 59: machine.v1alpha1.MachineRuntime.DetachVolume:output_type -> machine.v1alpha1.DetachVolumeResponse + 39, // 60: machine.v1alpha1.MachineRuntime.UpdateVolume:output_type -> machine.v1alpha1.UpdateVolumeResponse + 41, // 61: machine.v1alpha1.MachineRuntime.AttachNetworkInterface:output_type -> machine.v1alpha1.AttachNetworkInterfaceResponse + 43, // 62: machine.v1alpha1.MachineRuntime.DetachNetworkInterface:output_type -> machine.v1alpha1.DetachNetworkInterfaceResponse + 45, // 63: machine.v1alpha1.MachineRuntime.Status:output_type -> machine.v1alpha1.StatusResponse + 47, // 64: machine.v1alpha1.MachineRuntime.Exec:output_type -> machine.v1alpha1.ExecResponse + 51, // [51:65] is the sub-list for method output_type + 37, // [37:51] is the sub-list for method input_type + 37, // [37:37] is the sub-list for extension type_name + 37, // [37:37] is the sub-list for extension extendee + 0, // [0:37] is the sub-list for field type_name } func init() { file_machine_v1alpha1_api_proto_init() } @@ -2818,7 +2804,7 @@ func file_machine_v1alpha1_api_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_machine_v1alpha1_api_proto_rawDesc), len(file_machine_v1alpha1_api_proto_rawDesc)), NumEnums: 4, - NumMessages: 55, + NumMessages: 54, NumExtensions: 0, NumServices: 1, }, diff --git a/iri/apis/machine/v1alpha1/api.proto b/iri/apis/machine/v1alpha1/api.proto index 76983e1f0..4e1fc95e6 100644 --- a/iri/apis/machine/v1alpha1/api.proto +++ b/iri/apis/machine/v1alpha1/api.proto @@ -84,7 +84,6 @@ message NetworkInterface { string network_id = 2; repeated string ips = 3; map attributes = 4; - map labels = 5; } enum Power { diff --git a/poollet/bucketpoollet/controllers/bucket_controller.go b/poollet/bucketpoollet/controllers/bucket_controller.go index 4223bb219..070e46422 100644 --- a/poollet/bucketpoollet/controllers/bucket_controller.go +++ b/poollet/bucketpoollet/controllers/bucket_controller.go @@ -24,13 +24,13 @@ import ( "github.com/ironcore-dev/ironcore/utils/predicates" "github.com/ironcore-dev/controller-utils/clientutils" + utilsmaps "github.com/ironcore-dev/ironcore/utils/maps" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" - "k8s.io/kubectl/pkg/util/fieldpath" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" @@ -64,12 +64,11 @@ func (r *BucketReconciler) iriBucketLabels(bucket *storagev1alpha1.Bucket) (map[ bucketpoolletv1alpha1.BucketNamespaceLabel: bucket.Namespace, bucketpoolletv1alpha1.BucketNameLabel: bucket.Name, } - for downwardAPILabelName, fieldPath := range r.DownwardAPILabels { - value, err := fieldpath.ExtractFieldPathAsString(bucket, fieldPath) - if err == nil && value != "" { - labels[poolletutils.DownwardAPILabel(bucketpoolletv1alpha1.BucketDownwardAPIPrefix, downwardAPILabelName)] = value - } + apiLabels, err := poolletutils.PrepareDownwardAPILabels(bucket, r.DownwardAPILabels, bucketpoolletv1alpha1.BucketDownwardAPIPrefix) + if err != nil { + return nil, err } + labels = utilsmaps.AppendMap(labels, apiLabels) return labels, nil } diff --git a/poollet/common/utils/utils.go b/poollet/common/utils/utils.go index a3b6882bf..67c1fd2b7 100644 --- a/poollet/common/utils/utils.go +++ b/poollet/common/utils/utils.go @@ -6,6 +6,12 @@ package utils import ( "fmt" "strings" + + computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1" + networkingv1alpha1 "github.com/ironcore-dev/ironcore/api/networking/v1alpha1" + storagev1alpha1 "github.com/ironcore-dev/ironcore/api/storage/v1alpha1" + + "k8s.io/kubectl/pkg/util/fieldpath" ) type ID struct { @@ -50,3 +56,38 @@ func DownwardAPILabel(label_prefix, name string) string { func DownwardAPIAnnotation(annotation_prefix, name string) string { return annotation_prefix + name } + +func PrepareDownwardAPILabels( + obj interface{}, + downwardAPILabels map[string]string, + prefix string, +) (map[string]string, error) { + labels := make(map[string]string) + + // Use reflection or type assertion to get fields by path + for name, fieldPath := range downwardAPILabels { + var value string + var err error + + switch o := obj.(type) { + case *computev1alpha1.Machine: + value, err = fieldpath.ExtractFieldPathAsString(o, fieldPath) + case *networkingv1alpha1.Network: + value, err = fieldpath.ExtractFieldPathAsString(o, fieldPath) + case *networkingv1alpha1.NetworkInterface: + value, err = fieldpath.ExtractFieldPathAsString(o, fieldPath) + case *storagev1alpha1.Volume: + value, err = fieldpath.ExtractFieldPathAsString(o, fieldPath) + case *storagev1alpha1.Bucket: + value, err = fieldpath.ExtractFieldPathAsString(o, fieldPath) + default: + return nil, fmt.Errorf("unsupported type for downward API label extraction") + } + + if err != nil { + return nil, fmt.Errorf("error extracting downward api label %q: %w", name, err) + } + labels[DownwardAPILabel(prefix, name)] = value + } + return labels, nil +} diff --git a/poollet/machinepoollet/api/v1alpha1/common_types.go b/poollet/machinepoollet/api/v1alpha1/common_types.go index abecc7ea6..91e9aba7c 100644 --- a/poollet/machinepoollet/api/v1alpha1/common_types.go +++ b/poollet/machinepoollet/api/v1alpha1/common_types.go @@ -20,6 +20,13 @@ const ( NetworkInterfaceNamespaceLabel = "machinepoollet.ironcore.dev/nic-namespace" NetworkInterfaceNameLabel = "machinepoollet.ironcore.dev/nic-name" + NetworkUIDLabel = "machinepoollet.ironcore.dev/network-uid" + NetworkNamespaceLabel = "machinepoollet.ironcore.dev/network-namespace" + NetworkNameLabel = "machinepoollet.ironcore.dev/network-name" + + NICLabelsAttributeKey = "rawNICLabels" + NetworkLabelsAttributeKey = "rawNetworkLabels" + MachineGenerationAnnotation = "machinepoollet.ironcore.dev/machine-generation" IRIMachineGenerationAnnotation = "machinepoollet.ironcore.dev/irimachine-generation" diff --git a/poollet/machinepoollet/cmd/machinepoollet/app/app.go b/poollet/machinepoollet/cmd/machinepoollet/app/app.go index 2bb93651d..67f3a23f5 100644 --- a/poollet/machinepoollet/cmd/machinepoollet/app/app.go +++ b/poollet/machinepoollet/cmd/machinepoollet/app/app.go @@ -77,8 +77,12 @@ type Options struct { MachineDownwardAPILabels map[string]string MachineDownwardAPIAnnotations map[string]string - NicDownwardAPILabels map[string]string - NicDownwardAPIAnnotations map[string]string + NicDownwardAPILabels map[string]string + NicDownwardAPIAnnotations map[string]string + + NetworkDownwardAPILabels map[string]string + NetworkDownwardAPIAnnotations map[string]string + ProviderID string MachineRuntimeEndpoint string MachineRuntimeSocketDiscoveryTimeout time.Duration @@ -122,6 +126,8 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) { fs.StringToStringVar(&o.MachineDownwardAPIAnnotations, "machine-downward-api-annotation", o.MachineDownwardAPIAnnotations, "Downward-API annotations to set on the iri machine.") fs.StringToStringVar(&o.NicDownwardAPILabels, "nic-downward-api-label", o.NicDownwardAPILabels, "Downward-API labels to set on the iri nic.") fs.StringToStringVar(&o.NicDownwardAPIAnnotations, "nic-downward-api-annotation", o.NicDownwardAPIAnnotations, "Downward-API annotations to set on the iri nic.") + 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.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.") @@ -423,6 +429,8 @@ func Run(ctx context.Context, opts Options) error { MachineDownwardAPIAnnotations: opts.MachineDownwardAPIAnnotations, NicDownwardAPILabels: opts.NicDownwardAPILabels, NicDownwardAPIAnnotations: opts.NicDownwardAPIAnnotations, + NetworkDownwardAPILabels: opts.NetworkDownwardAPILabels, + NetworkDownwardAPIAnnotations: opts.NetworkDownwardAPIAnnotations, WatchFilterValue: opts.WatchFilterValue, MaxConcurrentReconciles: opts.MaxConcurrentReconciles, }).SetupWithManager(mgr); err != nil { diff --git a/poollet/machinepoollet/controllers/controllers_suite_test.go b/poollet/machinepoollet/controllers/controllers_suite_test.go index d331e7bda..5b66ca4a9 100644 --- a/poollet/machinepoollet/controllers/controllers_suite_test.go +++ b/poollet/machinepoollet/controllers/controllers_suite_test.go @@ -239,6 +239,11 @@ func SetupTest() (*corev1.Namespace, *computev1alpha1.MachinePool, *computev1alp }, NicDownwardAPILabels: map[string]string{ fooDownwardAPILabel: fmt.Sprintf("metadata.annotations['%s']", fooAnnotation), + "root-nic-uid": "metadata.uid", + }, + NetworkDownwardAPILabels: map[string]string{ + fooDownwardAPILabel: fmt.Sprintf("metadata.annotations['%s']", fooAnnotation), + "root-network-uid": "metadata.uid", }, }).SetupWithManager(k8sManager)).To(Succeed()) diff --git a/poollet/machinepoollet/controllers/machine_controller.go b/poollet/machinepoollet/controllers/machine_controller.go index d2dd67b4d..7b8644635 100644 --- a/poollet/machinepoollet/controllers/machine_controller.go +++ b/poollet/machinepoollet/controllers/machine_controller.go @@ -28,7 +28,7 @@ import ( "github.com/ironcore-dev/ironcore/poollet/machinepoollet/controllers/events" "github.com/ironcore-dev/ironcore/poollet/machinepoollet/mcm" utilclient "github.com/ironcore-dev/ironcore/utils/client" - utilmaps "github.com/ironcore-dev/ironcore/utils/maps" + utilsmaps "github.com/ironcore-dev/ironcore/utils/maps" "github.com/ironcore-dev/ironcore/utils/predicates" corev1 "k8s.io/api/core/v1" @@ -63,6 +63,9 @@ type MachineReconciler struct { NicDownwardAPILabels map[string]string NicDownwardAPIAnnotations map[string]string + NetworkDownwardAPILabels map[string]string + NetworkDownwardAPIAnnotations map[string]string + WatchFilterValue string MaxConcurrentReconciles int @@ -348,14 +351,11 @@ func (r *MachineReconciler) iriMachineLabels(machine *computev1alpha1.Machine) ( v1alpha1.MachineNameLabel: machine.Name, } - for name, fieldPath := range r.MachineDownwardAPILabels { - value, err := fieldpath.ExtractFieldPathAsString(machine, fieldPath) - if err != nil { - return nil, fmt.Errorf("error extracting downward api label %q: %w", name, err) - } - - labels[poolletutils.DownwardAPILabel(v1alpha1.MachineDownwardAPIPrefix, name)] = value + apiLabels, err := poolletutils.PrepareDownwardAPILabels(machine, r.MachineDownwardAPILabels, v1alpha1.MachineDownwardAPIPrefix) + if err != nil { + return nil, err } + labels = utilsmaps.AppendMap(labels, apiLabels) return labels, nil } @@ -515,7 +515,7 @@ func (r *MachineReconciler) updateNetworkInterfaceStatus( continue } - nic, ok := utilmaps.Pop(unhandledNicByUID, ref.UID) + nic, ok := utilsmaps.Pop(unhandledNicByUID, ref.UID) if !ok { continue } diff --git a/poollet/machinepoollet/controllers/machine_controller_networkinterface.go b/poollet/machinepoollet/controllers/machine_controller_networkinterface.go index 042d99ac5..d64758e71 100644 --- a/poollet/machinepoollet/controllers/machine_controller_networkinterface.go +++ b/poollet/machinepoollet/controllers/machine_controller_networkinterface.go @@ -5,8 +5,10 @@ package controllers import ( "context" + "encoding/json" "errors" "fmt" + "maps" "github.com/go-logr/logr" commonv1alpha1 "github.com/ironcore-dev/ironcore/api/common/v1alpha1" @@ -15,18 +17,19 @@ import ( networkingv1alpha1 "github.com/ironcore-dev/ironcore/api/networking/v1alpha1" iri "github.com/ironcore-dev/ironcore/iri/apis/machine/v1alpha1" poolletutils "github.com/ironcore-dev/ironcore/poollet/common/utils" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + "github.com/ironcore-dev/ironcore/poollet/machinepoollet/api/v1alpha1" "github.com/ironcore-dev/ironcore/poollet/machinepoollet/controllers/events" "github.com/ironcore-dev/ironcore/utils/claimmanager" + utilsmaps "github.com/ironcore-dev/ironcore/utils/maps" utilslices "github.com/ironcore-dev/ironcore/utils/slices" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/kubectl/pkg/util/fieldpath" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -217,16 +220,30 @@ func (r *MachineReconciler) getNetworkInterfaceIPs( } func (r *MachineReconciler) iriNetworkInterfaceLabels(networkinterface *networkingv1alpha1.NetworkInterface) (map[string]string, error) { + labels := map[string]string{ + v1alpha1.NetworkInterfaceUIDLabel: string(networkinterface.UID), + v1alpha1.NetworkInterfaceNamespaceLabel: networkinterface.Namespace, + v1alpha1.NetworkInterfaceNameLabel: networkinterface.Name, + } + apiLabels, err := poolletutils.PrepareDownwardAPILabels(networkinterface, r.NicDownwardAPILabels, v1alpha1.MachineDownwardAPIPrefix) + if err != nil { + return nil, err + } + labels = utilsmaps.AppendMap(labels, apiLabels) + return labels, nil +} - labels := map[string]string{} - for name, fieldPath := range r.NicDownwardAPILabels { - value, err := fieldpath.ExtractFieldPathAsString(networkinterface, fieldPath) - if err != nil { - return nil, fmt.Errorf("error extracting downward api label %q: %w", name, err) - } - - labels[poolletutils.DownwardAPILabel(v1alpha1.MachineDownwardAPIPrefix, name)] = value +func (r *MachineReconciler) iriNetworkLabels(network *networkingv1alpha1.Network) (map[string]string, error) { + labels := map[string]string{ + v1alpha1.NetworkUIDLabel: string(network.UID), + v1alpha1.NetworkNamespaceLabel: network.Namespace, + v1alpha1.NetworkNameLabel: network.Name, + } + apiLabels, err := poolletutils.PrepareDownwardAPILabels(network, r.NetworkDownwardAPILabels, v1alpha1.MachineDownwardAPIPrefix) + if err != nil { + return nil, err } + labels = utilsmaps.AppendMap(labels, apiLabels) return labels, nil } @@ -245,25 +262,59 @@ func (r *MachineReconciler) prepareIRINetworkInterface( r.Eventf(machine, corev1.EventTypeNormal, events.NetworkInterfaceNotReady, "Network interface %s network %s not found", nic.Name, networkKey.Name) return nil, false, nil } - labels, err := r.iriNetworkInterfaceLabels(nic) + nicLabels, err := r.iriNetworkInterfaceLabels(nic) if err != nil { return nil, false, fmt.Errorf("error preparing iri networkinterface labels: %w", err) } + networkLabels, err := r.iriNetworkLabels(network) + if err != nil { + return nil, false, fmt.Errorf("error preparing iri network labels: %w", err) + } + + attributes, err := r.prepareNetworkInterfaceAttributes(nic, nicLabels, networkLabels) + if err != nil { + return nil, false, err + } + ips, ok, err := r.getNetworkInterfaceIPs(ctx, machine, nic) if err != nil || !ok { return nil, false, err } - return &iri.NetworkInterface{ Name: machineNicName, NetworkId: network.Spec.ProviderID, Ips: utilslices.Map(ips, commonv1alpha1.IP.String), - Attributes: nic.Spec.Attributes, - Labels: labels, + Attributes: attributes, }, true, nil } +func (r *MachineReconciler) prepareNetworkInterfaceAttributes( + nic *networkingv1alpha1.NetworkInterface, + nicLabels map[string]string, + networkLabels map[string]string, +) (map[string]string, error) { + var attributes map[string]string + if nic.Spec.Attributes != nil { + attributes = maps.Clone(nic.Spec.Attributes) + } else { + attributes = make(map[string]string) + } + nicLabelsJSON, err := json.Marshal(nicLabels) + if err != nil { + return nil, fmt.Errorf("error marshaling NIC labels: %w", err) + } + attributes[v1alpha1.NICLabelsAttributeKey] = string(nicLabelsJSON) + + networkLabelsJSON, err := json.Marshal(networkLabels) + if err != nil { + return nil, fmt.Errorf("error marshaling network labels: %w", err) + } + attributes[v1alpha1.NetworkLabelsAttributeKey] = string(networkLabelsJSON) + + return attributes, nil +} + func (r *MachineReconciler) getExistingIRINetworkInterfacesForMachine( ctx context.Context, log logr.Logger, diff --git a/poollet/machinepoollet/controllers/machine_controller_test.go b/poollet/machinepoollet/controllers/machine_controller_test.go index 56eb7cd28..6f72f605f 100644 --- a/poollet/machinepoollet/controllers/machine_controller_test.go +++ b/poollet/machinepoollet/controllers/machine_controller_test.go @@ -4,6 +4,7 @@ package controllers_test import ( + "encoding/json" "fmt" . "github.com/afritzler/protoequal" @@ -34,10 +35,14 @@ var _ = Describe("MachineController", func() { It("Should create a machine with an ephemeral NIC and ensure claimed networkInterfaceRef matches the ephemeral NIC", func(ctx SpecContext) { By("creating a network") + const fooAnnotationValue = "bar" network := &networkingv1alpha1.Network{ ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, GenerateName: "network-", + Annotations: map[string]string{ + fooAnnotation: fooAnnotationValue, + }, }, Spec: networkingv1alpha1.NetworkSpec{ ProviderID: "foo", @@ -72,7 +77,6 @@ var _ = Describe("MachineController", func() { })).Should(Succeed()) By("creating a machine") - const fooAnnotationValue = "bar" machine := &computev1alpha1.Machine{ ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, @@ -156,8 +160,21 @@ var _ = Describe("MachineController", func() { Name: "primary", NetworkId: "foo", Ips: []string{"10.0.0.11"}, - Labels: map[string]string{ - poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + Attributes: map[string]string{ + machinepoolletv1alpha1.NICLabelsAttributeKey: string(mustMarshalJSON(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-nic-uid"): string(nic.UID), + machinepoolletv1alpha1.NetworkInterfaceUIDLabel: string(nic.UID), + machinepoolletv1alpha1.NetworkInterfaceNamespaceLabel: string(nic.Namespace), + machinepoolletv1alpha1.NetworkInterfaceNameLabel: string(nic.Name), + })), + machinepoolletv1alpha1.NetworkLabelsAttributeKey: string(mustMarshalJSON(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-network-uid"): string(network.UID), + machinepoolletv1alpha1.NetworkUIDLabel: string(network.UID), + machinepoolletv1alpha1.NetworkNamespaceLabel: string(network.Namespace), + machinepoolletv1alpha1.NetworkNameLabel: string(network.Name), + })), }, }))) @@ -207,6 +224,9 @@ var _ = Describe("MachineController", func() { ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, GenerateName: "network-", + Annotations: map[string]string{ + fooAnnotation: fooAnnotationValue, + }, }, Spec: networkingv1alpha1.NetworkSpec{ ProviderID: "foo", @@ -315,8 +335,21 @@ var _ = Describe("MachineController", func() { Name: "primary", NetworkId: "foo", Ips: []string{"10.0.0.1"}, - Labels: map[string]string{ - poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + Attributes: map[string]string{ + machinepoolletv1alpha1.NICLabelsAttributeKey: string(mustMarshalJSON(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-nic-uid"): string(nic.UID), + machinepoolletv1alpha1.NetworkInterfaceUIDLabel: string(nic.UID), + machinepoolletv1alpha1.NetworkInterfaceNamespaceLabel: string(nic.Namespace), + machinepoolletv1alpha1.NetworkInterfaceNameLabel: string(nic.Name), + })), + machinepoolletv1alpha1.NetworkLabelsAttributeKey: string(mustMarshalJSON(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-network-uid"): string(network.UID), + machinepoolletv1alpha1.NetworkUIDLabel: string(network.UID), + machinepoolletv1alpha1.NetworkNamespaceLabel: string(network.Namespace), + machinepoolletv1alpha1.NetworkNameLabel: string(network.Name), + })), }, }))) @@ -784,3 +817,11 @@ func GetSingleMapEntry[K comparable, V any](m map[K]V) (K, V) { } panic("unreachable") } + +func mustMarshalJSON(v interface{}) string { + data, err := json.Marshal(v) + if err != nil { + panic(err) + } + return string(data) +} diff --git a/poollet/volumepoollet/controllers/volume_controller.go b/poollet/volumepoollet/controllers/volume_controller.go index 8da1370ed..7483878a2 100644 --- a/poollet/volumepoollet/controllers/volume_controller.go +++ b/poollet/volumepoollet/controllers/volume_controller.go @@ -22,6 +22,7 @@ import ( volumepoolletv1alpha1 "github.com/ironcore-dev/ironcore/poollet/volumepoollet/api/v1alpha1" "github.com/ironcore-dev/ironcore/poollet/volumepoollet/controllers/events" "github.com/ironcore-dev/ironcore/poollet/volumepoollet/vcm" + utilsmaps "github.com/ironcore-dev/ironcore/utils/maps" ironcoreclient "github.com/ironcore-dev/ironcore/utils/client" "github.com/ironcore-dev/ironcore/utils/predicates" @@ -34,7 +35,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" - "k8s.io/kubectl/pkg/util/fieldpath" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" @@ -69,14 +69,11 @@ func (r *VolumeReconciler) iriVolumeLabels(volume *storagev1alpha1.Volume) (map[ volumepoolletv1alpha1.VolumeNamespaceLabel: volume.Namespace, volumepoolletv1alpha1.VolumeNameLabel: volume.Name, } - for name, fieldPath := range r.DownwardAPILabels { - value, err := fieldpath.ExtractFieldPathAsString(volume, fieldPath) - if err != nil { - return nil, fmt.Errorf("error extracting downward api label %q: %w", name, err) - } - - labels[poolletutils.DownwardAPILabel(volumepoolletv1alpha1.VolumeDownwardAPIPrefix, name)] = value + apiLabels, err := poolletutils.PrepareDownwardAPILabels(volume, r.DownwardAPILabels, volumepoolletv1alpha1.VolumeDownwardAPIPrefix) + if err != nil { + return nil, err } + labels = utilsmaps.AppendMap(labels, apiLabels) return labels, nil }