From a7347c49be33b5030050d8854507519c8068336f Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Thu, 9 Oct 2025 11:51:38 +0530 Subject: [PATCH] add `downward-api` labels support for `volumes` created by `MachineBroker` --- .../server/machine_networkinterface_attach.go | 6 +- .../server/machine_volume_attach.go | 37 ++++++- .../server/machine_volume_attach_test.go | 13 +++ .../machinebroker/server/server_suite_test.go | 1 + .../manager/manager.yaml | 6 ++ .../api/v1alpha1/common_types.go | 5 + .../cmd/machinepoollet/app/app.go | 8 ++ .../controllers/controllers_suite_test.go | 4 + .../controllers/machine_controller.go | 3 + .../controllers/machine_controller_test.go | 100 +++++++++++++++++- .../controllers/machine_controller_volume.go | 49 ++++++++- 11 files changed, 221 insertions(+), 11 deletions(-) diff --git a/broker/machinebroker/server/machine_networkinterface_attach.go b/broker/machinebroker/server/machine_networkinterface_attach.go index 18a30f0fc..e4543b457 100644 --- a/broker/machinebroker/server/machine_networkinterface_attach.go +++ b/broker/machinebroker/server/machine_networkinterface_attach.go @@ -43,7 +43,7 @@ func (s *Server) getIronCoreNetworkInterfaceConfig(iriNIC *iri.NetworkInterface) var preparedNicLabels, preparedNetworkLabels map[string]string attributes := iriNIC.GetAttributes() if attributes != nil { - preparedNicLabels, preparedNetworkLabels, err = s.prepareLabelsFromAttributes(iriNIC.GetAttributes()) + preparedNicLabels, preparedNetworkLabels, err = s.prepareLabelsFromAttributes(attributes) if err != nil { return nil, err } @@ -63,13 +63,13 @@ func (s *Server) prepareLabelsFromAttributes(attrs map[string]string) (map[strin 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) + return nil, nil, fmt.Errorf("error unmarshaling NIC 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) + return nil, nil, fmt.Errorf("error unmarshaling network labels: %w", err) } } preparedNicLabels := brokerutils.PrepareDownwardAPILabels(nicLabels, s.brokerDownwardAPILabels, machinepoolletv1alpha1.MachineDownwardAPIPrefix) diff --git a/broker/machinebroker/server/machine_volume_attach.go b/broker/machinebroker/server/machine_volume_attach.go index 9664cce2a..bad2ceedd 100644 --- a/broker/machinebroker/server/machine_volume_attach.go +++ b/broker/machinebroker/server/machine_volume_attach.go @@ -5,6 +5,7 @@ package server import ( "context" + "encoding/json" "fmt" "github.com/go-logr/logr" @@ -13,8 +14,12 @@ import ( corev1alpha1 "github.com/ironcore-dev/ironcore/api/core/v1alpha1" storagev1alpha1 "github.com/ironcore-dev/ironcore/api/storage/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" iri "github.com/ironcore-dev/ironcore/iri/apis/machine/v1alpha1" + machinepoolletv1alpha1 "github.com/ironcore-dev/ironcore/poollet/machinepoollet/api/v1alpha1" + + utilsmaps "github.com/ironcore-dev/ironcore/utils/maps" metautils "github.com/ironcore-dev/ironcore/utils/meta" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -27,6 +32,7 @@ type IronCoreVolumeConfig struct { Device string EmptyDisk *IronCoreVolumeEmptyDiskConfig Remote *IronCoreVolumeRemoteConfig + Labels map[string]string } type IronCoreVolumeEmptyDiskConfig struct { @@ -68,15 +74,40 @@ func (s *Server) getIronCoreVolumeConfig(volume *iri.Volume) (*IronCoreVolumeCon default: return nil, fmt.Errorf("unrecognized volume %#v", volume) } - + labels, err := s.prepareLabels(volume.Connection) + if err != nil { + return nil, err + } return &IronCoreVolumeConfig{ Name: volume.Name, Device: volume.Device, EmptyDisk: emptyDisk, Remote: remote, + Labels: labels, }, nil } +func (s *Server) prepareLabels(conn *iri.VolumeConnection) (map[string]string, error) { + attrs := conn.GetAttributes() + if attrs == nil { + return nil, nil + } + return s.prepareVolumeLabelsFromAttributes(attrs) +} + +func (s *Server) prepareVolumeLabelsFromAttributes(attrs map[string]string) (map[string]string, error) { + var labels map[string]string + + if labelsString, ok := attrs[machinepoolletv1alpha1.VolumeLabelsAttributeKey]; ok { + if err := json.Unmarshal([]byte(labelsString), &labels); err != nil { + return nil, fmt.Errorf("error unmarshaling volume labels: %w", err) + } + } + preparedVolumeLabels := brokerutils.PrepareDownwardAPILabels(labels, s.brokerDownwardAPILabels, machinepoolletv1alpha1.MachineDownwardAPIPrefix) + + return preparedVolumeLabels, nil +} + func (s *Server) createIronCoreVolume( ctx context.Context, log logr.Logger, @@ -121,9 +152,9 @@ func (s *Server) createIronCoreVolume( Annotations: map[string]string{ commonv1alpha1.ManagedByAnnotation: machinebrokerv1alpha1.MachineBrokerManager, }, - Labels: map[string]string{ + Labels: utilsmaps.AppendMap(cfg.Labels, map[string]string{ machinebrokerv1alpha1.ManagerLabel: machinebrokerv1alpha1.MachineBrokerManager, - }, + }), }, Spec: storagev1alpha1.VolumeSpec{ ClaimRef: s.optionalLocalUIDReference(optIronCoreMachine), diff --git a/broker/machinebroker/server/machine_volume_attach_test.go b/broker/machinebroker/server/machine_volume_attach_test.go index 2f3b3c3d9..81c06abb0 100644 --- a/broker/machinebroker/server/machine_volume_attach_test.go +++ b/broker/machinebroker/server/machine_volume_attach_test.go @@ -6,7 +6,10 @@ package server_test import ( computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1" storagev1alpha1 "github.com/ironcore-dev/ironcore/api/storage/v1alpha1" + machinebrokerv1alpha1 "github.com/ironcore-dev/ironcore/broker/machinebroker/api/v1alpha1" 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/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gstruct" @@ -37,6 +40,9 @@ var _ = Describe("AttachVolume", func() { machineID := createMachineRes.Machine.Metadata.Id By("attaching a volume") + labels := map[string]string{ + machinepoolletv1alpha1.VolumeUIDLabel: "bar", + } Expect(srv.AttachVolume(ctx, &iri.AttachVolumeRequest{ MachineId: machineID, Volume: &iri.Volume{ @@ -46,6 +52,7 @@ var _ = Describe("AttachVolume", func() { Driver: "ceph", Handle: "mycephvolume", Attributes: map[string]string{ + machinepoolletv1alpha1.VolumeLabelsAttributeKey: string(mustMarshalJSON(labels)), "foo": "bar", }, SecretData: map[string][]byte{ @@ -86,10 +93,16 @@ var _ = Describe("AttachVolume", func() { "Driver": Equal("ceph"), "Handle": Equal("mycephvolume"), "VolumeAttributes": Equal(map[string]string{ + machinepoolletv1alpha1.VolumeLabelsAttributeKey: string(mustMarshalJSON(labels)), "foo": "bar", }), }))) + Expect(volume.Labels).To(Equal(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-volume-uid"): "bar", + machinebrokerv1alpha1.ManagerLabel: machinebrokerv1alpha1.MachineBrokerManager, + })) + By("inspecting the effective storage resource is set for volume") Expect(volume.Status.Resources.Storage().String()).Should(Equal("2k")) diff --git a/broker/machinebroker/server/server_suite_test.go b/broker/machinebroker/server/server_suite_test.go index 21645410f..8afa09bd9 100644 --- a/broker/machinebroker/server/server_suite_test.go +++ b/broker/machinebroker/server/server_suite_test.go @@ -137,6 +137,7 @@ func SetupTest() (*corev1.Namespace, *server.Server) { BaseURL: baseURL, BrokerDownwardAPILabels: map[string]string{ "root-machine-uid": machinepoolletv1alpha1.MachineUIDLabel, + "root-volume-uid": machinepoolletv1alpha1.VolumeUIDLabel, "root-nic-uid": machinepoolletv1alpha1.NetworkInterfaceUIDLabel, "root-network-uid": machinepoolletv1alpha1.NetworkUIDLabel, }, diff --git a/config/machinepoollet-broker/manager/manager.yaml b/config/machinepoollet-broker/manager/manager.yaml index 69582c4b0..f99c42135 100644 --- a/config/machinepoollet-broker/manager/manager.yaml +++ b/config/machinepoollet-broker/manager/manager.yaml @@ -35,6 +35,9 @@ spec: - --machine-downward-api-label=root-machine-namespace=metadata.labels['downward-api.machinepoollet.ironcore.dev/root-machine-namespace'] - --machine-downward-api-label=root-machine-name=metadata.labels['downward-api.machinepoollet.ironcore.dev/root-machine-name'] - --machine-downward-api-label=root-machine-uid=metadata.labels['downward-api.machinepoollet.ironcore.dev/root-machine-uid'] + - --volume-downward-api-label=root-volume-namespace=metadata.labels['downward-api.machinepoollet.ironcore.dev/root-volume-namespace'] + - --volume-downward-api-label=root-volume-name=metadata.labels['downward-api.machinepoollet.ironcore.dev/root-volume-name'] + - --volume-downward-api-label=root-volume-uid=metadata.labels['downward-api.machinepoollet.ironcore.dev/root-volume-uid'] - --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'] @@ -86,6 +89,9 @@ spec: - --broker-downward-api-label=root-machine-namespace=machinepoollet.ironcore.dev/machine-namespace - --broker-downward-api-label=root-machine-name=machinepoollet.ironcore.dev/machine-name - --broker-downward-api-label=root-machine-uid=machinepoollet.ironcore.dev/machine-uid + - --broker-downward-api-label=root-volume-namespace=machinepoollet.ironcore.dev/volume-namespace + - --broker-downward-api-label=root-volume-name=machinepoollet.ironcore.dev/volume-name + - --broker-downward-api-label=root-volume-uid=machinepoollet.ironcore.dev/volume-uid - --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 diff --git a/poollet/machinepoollet/api/v1alpha1/common_types.go b/poollet/machinepoollet/api/v1alpha1/common_types.go index 6853f315d..77899b08f 100644 --- a/poollet/machinepoollet/api/v1alpha1/common_types.go +++ b/poollet/machinepoollet/api/v1alpha1/common_types.go @@ -15,6 +15,10 @@ const ( MachineNamespaceLabel = "machinepoollet.ironcore.dev/machine-namespace" MachineNameLabel = "machinepoollet.ironcore.dev/machine-name" + VolumeUIDLabel = "machinepoollet.ironcore.dev/volume-uid" + VolumeNamespaceLabel = "machinepoollet.ironcore.dev/volume-namespace" + VolumeNameLabel = "machinepoollet.ironcore.dev/volume-name" + NetworkInterfaceUIDLabel = "machinepoollet.ironcore.dev/nic-uid" NetworkInterfaceNamespaceLabel = "machinepoollet.ironcore.dev/nic-namespace" NetworkInterfaceNameLabel = "machinepoollet.ironcore.dev/nic-name" @@ -25,6 +29,7 @@ const ( NICLabelsAttributeKey = "rawNICLabels" NetworkLabelsAttributeKey = "rawNetworkLabels" + VolumeLabelsAttributeKey = "rawVolumeLabels" 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 0cc405d9d..e688652ba 100644 --- a/poollet/machinepoollet/cmd/machinepoollet/app/app.go +++ b/poollet/machinepoollet/cmd/machinepoollet/app/app.go @@ -78,6 +78,9 @@ type Options struct { MachineDownwardAPILabels map[string]string MachineDownwardAPIAnnotations map[string]string + VolumeDownwardAPILabels map[string]string + VolumeDownwardAPIAnnotations map[string]string + NicDownwardAPILabels map[string]string NicDownwardAPIAnnotations map[string]string @@ -126,10 +129,13 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&o.MachinePoolName, "machine-pool-name", o.MachinePoolName, "Name of the machine pool to announce / watch") fs.StringToStringVar(&o.MachineDownwardAPILabels, "machine-downward-api-label", o.MachineDownwardAPILabels, "Downward-API labels to set on the iri machine.") fs.StringToStringVar(&o.MachineDownwardAPIAnnotations, "machine-downward-api-annotation", o.MachineDownwardAPIAnnotations, "Downward-API annotations to set on the iri machine.") + fs.StringToStringVar(&o.VolumeDownwardAPILabels, "volume-downward-api-label", o.VolumeDownwardAPILabels, "Downward-API labels to set on the iri volume.") + fs.StringToStringVar(&o.VolumeDownwardAPIAnnotations, "volume-downward-api-annotation", o.VolumeDownwardAPIAnnotations, "Downward-API annotations to set on the iri volume.") 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.") @@ -430,6 +436,8 @@ func Run(ctx context.Context, opts Options) error { MachinePoolName: opts.MachinePoolName, MachineDownwardAPILabels: opts.MachineDownwardAPILabels, MachineDownwardAPIAnnotations: opts.MachineDownwardAPIAnnotations, + VolumeDownwardAPILabels: opts.VolumeDownwardAPILabels, + VolumeDownwardAPIAnnotations: opts.VolumeDownwardAPIAnnotations, NicDownwardAPILabels: opts.NicDownwardAPILabels, NicDownwardAPIAnnotations: opts.NicDownwardAPIAnnotations, NetworkDownwardAPILabels: opts.NetworkDownwardAPILabels, diff --git a/poollet/machinepoollet/controllers/controllers_suite_test.go b/poollet/machinepoollet/controllers/controllers_suite_test.go index a1e9c0e56..dd593849e 100644 --- a/poollet/machinepoollet/controllers/controllers_suite_test.go +++ b/poollet/machinepoollet/controllers/controllers_suite_test.go @@ -235,6 +235,10 @@ func SetupTest() (*corev1.Namespace, *computev1alpha1.MachinePool, *computev1alp MachineDownwardAPILabels: map[string]string{ fooDownwardAPILabel: fmt.Sprintf("metadata.annotations['%s']", fooAnnotation), }, + VolumeDownwardAPILabels: map[string]string{ + fooDownwardAPILabel: fmt.Sprintf("metadata.annotations['%s']", fooAnnotation), + "root-volume-uid": "metadata.uid", + }, NicDownwardAPILabels: map[string]string{ fooDownwardAPILabel: fmt.Sprintf("metadata.annotations['%s']", fooAnnotation), "root-nic-uid": "metadata.uid", diff --git a/poollet/machinepoollet/controllers/machine_controller.go b/poollet/machinepoollet/controllers/machine_controller.go index e95596afc..92880022d 100644 --- a/poollet/machinepoollet/controllers/machine_controller.go +++ b/poollet/machinepoollet/controllers/machine_controller.go @@ -64,6 +64,9 @@ type MachineReconciler struct { NicDownwardAPILabels map[string]string NicDownwardAPIAnnotations map[string]string + VolumeDownwardAPILabels map[string]string + VolumeDownwardAPIAnnotations map[string]string + NetworkDownwardAPILabels map[string]string NetworkDownwardAPIAnnotations map[string]string diff --git a/poollet/machinepoollet/controllers/machine_controller_test.go b/poollet/machinepoollet/controllers/machine_controller_test.go index 0185e652c..a74a86ec7 100644 --- a/poollet/machinepoollet/controllers/machine_controller_test.go +++ b/poollet/machinepoollet/controllers/machine_controller_test.go @@ -61,6 +61,9 @@ var _ = Describe("MachineController", func() { ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, GenerateName: "volume-", + Annotations: map[string]string{ + fooAnnotation: fooAnnotationValue, + }, }, Spec: storagev1alpha1.VolumeSpec{}, } @@ -140,7 +143,6 @@ var _ = Describe("MachineController", func() { }).Should(Succeed()) _, iriMachine := GetSingleMapEntry(srv.Machines) - By("inspecting the iri machine") Expect(iriMachine.Metadata.Labels).To(HaveKeyWithValue(poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel), fooAnnotationValue)) Expect(iriMachine.Metadata.Labels).To(HaveKeyWithValue(machinepoolletv1alpha1.MachineUIDLabel, string(machine.UID))) @@ -152,6 +154,15 @@ var _ = Describe("MachineController", func() { Connection: &iri.VolumeConnection{ Driver: "test", Handle: "testhandle", + Attributes: map[string]string{ + machinepoolletv1alpha1.VolumeLabelsAttributeKey: string(mustMarshalJSON(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-volume-uid"): string(volume.UID), + machinepoolletv1alpha1.VolumeUIDLabel: string(volume.UID), + machinepoolletv1alpha1.VolumeNamespaceLabel: string(volume.Namespace), + machinepoolletv1alpha1.VolumeNameLabel: string(volume.Name), + })), + }, }, }))) @@ -264,6 +275,9 @@ var _ = Describe("MachineController", func() { ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, GenerateName: "volume-", + Annotations: map[string]string{ + fooAnnotation: fooAnnotationValue, + }, }, Spec: storagev1alpha1.VolumeSpec{}, } @@ -329,6 +343,15 @@ var _ = Describe("MachineController", func() { Connection: &iri.VolumeConnection{ Driver: "test", Handle: "testhandle", + Attributes: map[string]string{ + machinepoolletv1alpha1.VolumeLabelsAttributeKey: string(mustMarshalJSON(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-volume-uid"): string(volume.UID), + machinepoolletv1alpha1.VolumeUIDLabel: string(volume.UID), + machinepoolletv1alpha1.VolumeNamespaceLabel: string(volume.Namespace), + machinepoolletv1alpha1.VolumeNameLabel: string(volume.Name), + })), + }, }, }))) Expect(iriMachine.Spec.NetworkInterfaces).To(ConsistOf(ProtoEqual(&iri.NetworkInterface{ @@ -488,6 +511,11 @@ var _ = Describe("MachineController", func() { VolumeSource: computev1alpha1.VolumeSource{ Ephemeral: &computev1alpha1.EphemeralVolumeSource{ VolumeTemplate: &storagev1alpha1.VolumeTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + fooAnnotation: fooAnnotationValue, + }, + }, Spec: storagev1alpha1.VolumeSpec{}, }, }, @@ -536,6 +564,15 @@ var _ = Describe("MachineController", func() { Connection: &iri.VolumeConnection{ Driver: "test", Handle: "testhandle", + Attributes: map[string]string{ + machinepoolletv1alpha1.VolumeLabelsAttributeKey: string(mustMarshalJSON(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-volume-uid"): string(ephemeralVolume.UID), + machinepoolletv1alpha1.VolumeUIDLabel: string(ephemeralVolume.UID), + machinepoolletv1alpha1.VolumeNamespaceLabel: string(ephemeralVolume.Namespace), + machinepoolletv1alpha1.VolumeNameLabel: string(ephemeralVolume.Name), + })), + }, }, }))) @@ -562,6 +599,7 @@ var _ = Describe("MachineController", func() { }) It("should validate IRI volume update for machine", func(ctx SpecContext) { + const fooAnnotationValue = "bar" By("creating a network") network := &networkingv1alpha1.Network{ ObjectMeta: metav1.ObjectMeta{ @@ -601,6 +639,9 @@ var _ = Describe("MachineController", func() { ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, GenerateName: "volume-", + Annotations: map[string]string{ + fooAnnotation: fooAnnotationValue, + }, }, Spec: storagev1alpha1.VolumeSpec{}, } @@ -620,6 +661,9 @@ var _ = Describe("MachineController", func() { ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, GenerateName: "volume-", + Annotations: map[string]string{ + fooAnnotation: fooAnnotationValue, + }, }, Spec: storagev1alpha1.VolumeSpec{}, } @@ -636,7 +680,6 @@ var _ = Describe("MachineController", func() { })).Should(Succeed()) By("creating a machine") - const fooAnnotationValue = "bar" machine := &computev1alpha1.Machine{ ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, @@ -689,6 +732,15 @@ var _ = Describe("MachineController", func() { Connection: &iri.VolumeConnection{ Driver: "test", Handle: "testhandle", + Attributes: map[string]string{ + machinepoolletv1alpha1.VolumeLabelsAttributeKey: string(mustMarshalJSON(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-volume-uid"): string(volume.UID), + machinepoolletv1alpha1.VolumeUIDLabel: string(volume.UID), + machinepoolletv1alpha1.VolumeNamespaceLabel: string(volume.Namespace), + machinepoolletv1alpha1.VolumeNameLabel: string(volume.Name), + })), + }, }, }, &iri.Volume{ @@ -697,6 +749,15 @@ var _ = Describe("MachineController", func() { Connection: &iri.VolumeConnection{ Driver: "test", Handle: "testhandle", + Attributes: map[string]string{ + machinepoolletv1alpha1.VolumeLabelsAttributeKey: string(mustMarshalJSON(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-volume-uid"): string(secondaryVolume.UID), + machinepoolletv1alpha1.VolumeUIDLabel: string(secondaryVolume.UID), + machinepoolletv1alpha1.VolumeNamespaceLabel: string(secondaryVolume.Namespace), + machinepoolletv1alpha1.VolumeNameLabel: string(secondaryVolume.Name), + })), + }, }, }, )) @@ -715,16 +776,29 @@ var _ = Describe("MachineController", func() { Connection: &iri.VolumeConnection{ Driver: "test", Handle: "testhandle", + Attributes: map[string]string{ + machinepoolletv1alpha1.VolumeLabelsAttributeKey: string(mustMarshalJSON(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-volume-uid"): string(volume.UID), + machinepoolletv1alpha1.VolumeUIDLabel: string(volume.UID), + machinepoolletv1alpha1.VolumeNamespaceLabel: string(volume.Namespace), + machinepoolletv1alpha1.VolumeNameLabel: string(volume.Name), + })), + }, }, })) }) It("should correctly update volume size", func(ctx SpecContext) { + const fooAnnotationValue = "bar" By("creating a volume") volume := &storagev1alpha1.Volume{ ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, GenerateName: "volume-", + Annotations: map[string]string{ + fooAnnotation: fooAnnotationValue, + }, }, Spec: storagev1alpha1.VolumeSpec{}, } @@ -781,6 +855,15 @@ var _ = Describe("MachineController", func() { Driver: "test", Handle: "testhandle", EffectiveStorageBytes: resource.NewQuantity(1*1024*1024*1024, resource.BinarySI).Value(), + Attributes: map[string]string{ + machinepoolletv1alpha1.VolumeLabelsAttributeKey: string(mustMarshalJSON(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-volume-uid"): string(volume.UID), + machinepoolletv1alpha1.VolumeUIDLabel: string(volume.UID), + machinepoolletv1alpha1.VolumeNamespaceLabel: string(volume.Namespace), + machinepoolletv1alpha1.VolumeNameLabel: string(volume.Name), + })), + }, }, }))) @@ -799,8 +882,17 @@ var _ = Describe("MachineController", func() { Name: "primary", Device: "oda", Connection: &iri.VolumeConnection{ - Driver: "test", - Handle: "testhandle", + Driver: "test", + Handle: "testhandle", + Attributes: map[string]string{ + machinepoolletv1alpha1.VolumeLabelsAttributeKey: string(mustMarshalJSON(map[string]string{ + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, fooDownwardAPILabel): fooAnnotationValue, + poolletutils.DownwardAPILabel(machinepoolletv1alpha1.MachineDownwardAPIPrefix, "root-volume-uid"): string(volume.UID), + machinepoolletv1alpha1.VolumeUIDLabel: string(volume.UID), + machinepoolletv1alpha1.VolumeNamespaceLabel: string(volume.Namespace), + machinepoolletv1alpha1.VolumeNameLabel: string(volume.Name), + })), + }, EffectiveStorageBytes: resource.NewQuantity(2*1024*1024*1024, resource.BinarySI).Value(), }, }))) diff --git a/poollet/machinepoollet/controllers/machine_controller_volume.go b/poollet/machinepoollet/controllers/machine_controller_volume.go index 121118c79..adc38643a 100644 --- a/poollet/machinepoollet/controllers/machine_controller_volume.go +++ b/poollet/machinepoollet/controllers/machine_controller_volume.go @@ -5,6 +5,7 @@ package controllers import ( "context" + "encoding/json" "errors" "fmt" @@ -12,9 +13,14 @@ import ( commonv1alpha1 "github.com/ironcore-dev/ironcore/api/common/v1alpha1" computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1" storagev1alpha1 "github.com/ironcore-dev/ironcore/api/storage/v1alpha1" + "golang.org/x/exp/maps" + iri "github.com/ironcore-dev/ironcore/iri/apis/machine/v1alpha1" + poolletutils "github.com/ironcore-dev/ironcore/poollet/common/utils" + "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" @@ -110,6 +116,39 @@ func (r *MachineReconciler) getVolumesForMachine(ctx context.Context, machine *c return volumes, errors.Join(errs...) } +func (r *MachineReconciler) iriVolumeLabels(volume *storagev1alpha1.Volume) (map[string]string, error) { + labels := map[string]string{ + v1alpha1.VolumeUIDLabel: string(volume.UID), + v1alpha1.VolumeNamespaceLabel: volume.Namespace, + v1alpha1.VolumeNameLabel: volume.Name, + } + apiLabels, err := poolletutils.PrepareDownwardAPILabels(volume, r.VolumeDownwardAPILabels, v1alpha1.MachineDownwardAPIPrefix) + if err != nil { + return nil, err + } + labels = utilsmaps.AppendMap(labels, apiLabels) + return labels, nil +} + +func (r *MachineReconciler) prepareVolumeAttributes( + volAttributes map[string]string, + labels map[string]string, +) (map[string]string, error) { + var attributes map[string]string + if volAttributes != nil { + attributes = maps.Clone(volAttributes) + } else { + attributes = make(map[string]string) + } + labelsJSON, err := json.Marshal(labels) + if err != nil { + return nil, fmt.Errorf("error marshaling volume labels: %w", err) + } + attributes[v1alpha1.VolumeLabelsAttributeKey] = string(labelsJSON) + + return attributes, nil +} + func (r *MachineReconciler) prepareRemoteIRIVolume( ctx context.Context, machine *computev1alpha1.Machine, @@ -166,6 +205,14 @@ func (r *MachineReconciler) prepareRemoteIRIVolume( if resources := volume.Status.Resources; resources != nil { effectiveSize = resources.Storage().Value() } + labels, err := r.iriVolumeLabels(volume) + if err != nil { + return nil, false, fmt.Errorf("error preparing iri volume labels: %w", err) + } + attributes, err := r.prepareVolumeAttributes(access.VolumeAttributes, labels) + if err != nil { + return nil, false, err + } return &iri.Volume{ Name: machineVolume.Name, @@ -173,7 +220,7 @@ func (r *MachineReconciler) prepareRemoteIRIVolume( Connection: &iri.VolumeConnection{ Driver: access.Driver, Handle: access.Handle, - Attributes: access.VolumeAttributes, + Attributes: attributes, SecretData: secretData, EncryptionData: encryptionData, EffectiveStorageBytes: effectiveSize,