diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml index b95c298..f8ae30c 100644 --- a/.github/workflows/publish-docker.yml +++ b/.github/workflows/publish-docker.yml @@ -66,7 +66,6 @@ jobs: endpoint: builders - name: Login to GHCR - if: github.event_name != 'pull_request' uses: docker/login-action@v3 with: registry: ghcr.io @@ -79,6 +78,6 @@ jobs: with: context: . platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'pull_request' }} + push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/cmd/machine-controller/main.go b/cmd/machine-controller/main.go index d503ce5..ed569fb 100644 --- a/cmd/machine-controller/main.go +++ b/cmd/machine-controller/main.go @@ -7,6 +7,8 @@ import ( "fmt" "os" + ipamv1alpha1 "github.com/ironcore-dev/ironcore/api/ipam/v1alpha1" + "github.com/gardener/machine-controller-manager/pkg/client/clientset/versioned/scheme" _ "github.com/gardener/machine-controller-manager/pkg/util/client/metrics/prometheus" // for client metric registration "github.com/gardener/machine-controller-manager/pkg/util/provider/app" @@ -71,6 +73,7 @@ func getIroncoreClientAndNamespace() (client.Client, string, error) { utilruntime.Must(scheme.AddToScheme(s)) utilruntime.Must(computev1alpha1.AddToScheme(s)) utilruntime.Must(corev1.AddToScheme(s)) + utilruntime.Must(ipamv1alpha1.AddToScheme(s)) ironcoreKubeconfigData, err := os.ReadFile(IroncoreKubeconfigPath) if err != nil { diff --git a/docs/provider-spec.md b/docs/provider-spec.md index ad91e9f..e8d7650 100644 --- a/docs/provider-spec.md +++ b/docs/provider-spec.md @@ -100,11 +100,11 @@ string -prefixName +prefixNames -string +[]string diff --git a/pkg/api/v1alpha1/provider.go b/pkg/api/v1alpha1/provider.go index 15e1554..0f73a57 100644 --- a/pkg/api/v1alpha1/provider.go +++ b/pkg/api/v1alpha1/provider.go @@ -33,7 +33,7 @@ type ProviderSpec struct { // NetworkName is the Network to be used for the Machine's NetworkInterface. NetworkName string `json:"networkName"` // PrefixName is the parent Prefix from which an IP should be allocated for the Machine's NetworkInterface. - PrefixName string `json:"prefixName"` + PrefixNames []string `json:"prefixNames"` // Labels are used to tag resources which the MCM creates, so they can be identified later. Labels map[string]string `json:"labels,omitempty"` // DnsServers is a list of DNS resolvers which should be configured on the host. diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index d2d9941..aa89650 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -52,8 +52,8 @@ func validateIroncoreMachineClassSpec(spec *v1alpha1.ProviderSpec, fldPath *fiel allErrs = append(allErrs, field.Required(fldPath.Child("networkName"), "networkName is required")) } - if spec.PrefixName == "" { - allErrs = append(allErrs, field.Required(fldPath.Child("prefixName"), "prefixName is required")) + if len(spec.PrefixNames) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("prefixNames"), "prefixNames is required")) } for i, ip := range spec.DnsServers { diff --git a/pkg/api/validation/validation_test.go b/pkg/api/validation/validation_test.go index 966af1d..7e137ad 100644 --- a/pkg/api/validation/validation_test.go +++ b/pkg/api/validation/validation_test.go @@ -74,12 +74,12 @@ var _ = Describe("Machine", func() { ), Entry("no prefix name", &v1alpha1.ProviderSpec{ - PrefixName: "", - RootDisk: &v1alpha1.RootDisk{}, + PrefixNames: []string{}, + RootDisk: &v1alpha1.RootDisk{}, }, &corev1.Secret{}, fldPath, - ContainElement(field.Required(fldPath.Child("spec.prefixName"), "prefixName is required")), + ContainElement(field.Required(fldPath.Child("spec.prefixNames"), "prefixNames is required")), ), Entry("invalid dns server ip", &v1alpha1.ProviderSpec{ diff --git a/pkg/ironcore/create_machine.go b/pkg/ironcore/create_machine.go index 95d2065..9750039 100644 --- a/pkg/ironcore/create_machine.go +++ b/pkg/ironcore/create_machine.go @@ -8,6 +8,8 @@ import ( "encoding/json" "fmt" + ipamv1alpha1 "github.com/ironcore-dev/ironcore/api/ipam/v1alpha1" + machinev1alpha1 "github.com/gardener/machine-controller-manager/pkg/apis/machine/v1alpha1" "github.com/gardener/machine-controller-manager/pkg/util/provider/driver" "github.com/gardener/machine-controller-manager/pkg/util/provider/machinecodes/codes" @@ -21,7 +23,6 @@ import ( "github.com/ironcore-dev/ironcore/api/common/v1alpha1" computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1" corev1alpha1 "github.com/ironcore-dev/ironcore/api/core/v1alpha1" - ipamv1alpha1 "github.com/ironcore-dev/ironcore/api/ipam/v1alpha1" networkingv1alpha1 "github.com/ironcore-dev/ironcore/api/networking/v1alpha1" storagev1alpha1 "github.com/ironcore-dev/ironcore/api/storage/v1alpha1" apiv1alpha1 "github.com/ironcore-dev/machine-controller-manager-provider-ironcore/pkg/api/v1alpha1" @@ -129,22 +130,6 @@ func (d *ironcoreDriver) applyIronCoreMachine(ctx context.Context, req *driver.C NetworkRef: corev1.LocalObjectReference{ Name: providerSpec.NetworkName, }, - IPFamilies: []corev1.IPFamily{corev1.IPv4Protocol}, - IPs: []networkingv1alpha1.IPSource{ - { - Ephemeral: &networkingv1alpha1.EphemeralPrefixSource{ - PrefixTemplate: &ipamv1alpha1.PrefixTemplateSpec{ - Spec: ipamv1alpha1.PrefixSpec{ - // request single IP - PrefixLength: 32, - ParentRef: &corev1.LocalObjectReference{ - Name: providerSpec.PrefixName, - }, - }, - }, - }, - }, - }, }, }, }, @@ -157,6 +142,45 @@ func (d *ironcoreDriver) applyIronCoreMachine(ctx context.Context, req *driver.C }, }, } + for _, prefixName := range providerSpec.PrefixNames { + prefix := &ipamv1alpha1.Prefix{} + if err := d.IroncoreClient.Get(ctx, client.ObjectKey{Name: prefixName, Namespace: d.IroncoreNamespace}, prefix); err != nil { + return nil, status.Error(codes.Internal, fmt.Sprintf("error getting prefix %s:%s", prefixName, err.Error())) + } + var machinePrefixLength int32 = 32 + if prefix.Spec.IPFamily == corev1.IPv6Protocol { + machinePrefixLength = 128 + nodePrefixIPv6 := networkingv1alpha1.PrefixSource{ + Ephemeral: &networkingv1alpha1.EphemeralPrefixSource{ + PrefixTemplate: &ipamv1alpha1.PrefixTemplateSpec{ + Spec: ipamv1alpha1.PrefixSpec{ + IPFamily: corev1.IPv6Protocol, + PrefixLength: 112, + ParentRef: &corev1.LocalObjectReference{Name: prefixName}, + }, + }, + }, + } + ironcoreMachine.Spec.NetworkInterfaces[0].NetworkInterfaceSource.Ephemeral.NetworkInterfaceTemplate.Spec.Prefixes = + append(ironcoreMachine.Spec.NetworkInterfaces[0].NetworkInterfaceSource.Ephemeral.NetworkInterfaceTemplate.Spec.Prefixes, nodePrefixIPv6) + } + ip := networkingv1alpha1.IPSource{ + Ephemeral: &networkingv1alpha1.EphemeralPrefixSource{ + PrefixTemplate: &ipamv1alpha1.PrefixTemplateSpec{ + Spec: ipamv1alpha1.PrefixSpec{ + PrefixLength: machinePrefixLength, + ParentRef: &corev1.LocalObjectReference{ + Name: prefixName, + }, + }, + }, + }, + } + ironcoreMachine.Spec.NetworkInterfaces[0].NetworkInterfaceSource.Ephemeral.NetworkInterfaceTemplate.Spec.IPs = + append(ironcoreMachine.Spec.NetworkInterfaces[0].NetworkInterfaceSource.Ephemeral.NetworkInterfaceTemplate.Spec.IPs, ip) + ironcoreMachine.Spec.NetworkInterfaces[0].NetworkInterfaceSource.Ephemeral.NetworkInterfaceTemplate.Spec.IPFamilies = + append(ironcoreMachine.Spec.NetworkInterfaces[0].NetworkInterfaceSource.Ephemeral.NetworkInterfaceTemplate.Spec.IPFamilies, prefix.Spec.IPFamily) + } if providerSpec.RootDisk == nil { ironcoreMachine.Spec.Image = providerSpec.Image diff --git a/pkg/ironcore/suite_test.go b/pkg/ironcore/suite_test.go index caa70c3..334b103 100644 --- a/pkg/ironcore/suite_test.go +++ b/pkg/ironcore/suite_test.go @@ -11,6 +11,10 @@ import ( "testing" "time" + commonv1alpha1 "github.com/ironcore-dev/ironcore/api/common/v1alpha1" + + ipamv1alpha1 "github.com/ironcore-dev/ironcore/api/ipam/v1alpha1" + gardenermachinev1alpha1 "github.com/gardener/machine-controller-manager/pkg/apis/machine/v1alpha1" "github.com/gardener/machine-controller-manager/pkg/util/provider/driver" "github.com/ironcore-dev/controller-utils/buildutils" @@ -97,6 +101,7 @@ var _ = BeforeSuite(func() { DeferCleanup(envtestutils.StopWithExtensions, testEnv, testEnvExt) Expect(computev1alpha1.AddToScheme(scheme.Scheme)).To(Succeed()) + Expect(ipamv1alpha1.AddToScheme(scheme.Scheme)).To(Succeed()) Expect(gardenermachinev1alpha1.AddToScheme(scheme.Scheme)).To(Succeed()) // Init package-level k8sClient @@ -176,6 +181,18 @@ func SetupTest() (*corev1.Namespace, *corev1.Secret, *driver.Driver) { } Expect(k8sClient.Create(ctx, secret)).To(Succeed()) + prefix := &ipamv1alpha1.Prefix{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-prefix", + Namespace: ns.Name, + }, + Spec: ipamv1alpha1.PrefixSpec{ + IPFamily: corev1.IPv4Protocol, + Prefix: commonv1alpha1.MustParseNewIPPrefix("192.168.0.0/24"), + }, + } + Expect(k8sClient.Create(ctx, prefix)).To(Succeed()) + drv = NewDriver(userClient, ns.Name, DefaultCSIDriverName) }) diff --git a/pkg/ironcore/testing/testing.go b/pkg/ironcore/testing/testing.go index 726156c..463aae6 100644 --- a/pkg/ironcore/testing/testing.go +++ b/pkg/ironcore/testing/testing.go @@ -14,7 +14,7 @@ var ( "machineClassName": "foo", "machinePoolName": "foo", "networkName": "my-network", - "prefixName": "my-prefix", + "prefixNames": []string{"my-prefix"}, "rootDisk": map[string]string{ "volumeClassName": "foo", "size": "10Gi",