diff --git a/Makefile b/Makefile index 7c92e1ac..06f89cac 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ LEADER_ELECT := "true" # If Integration Test Suite is to be run locally against clusters then export the below variable # with MCM deployment name in the cluster MACHINE_CONTROLLER_MANAGER_DEPLOYMENT_NAME := machine-controller-manager +PLATFORM ?= linux/amd64 ######################################### # Tools & Cleanup @@ -116,7 +117,6 @@ test-integration: .PHONY: release release: docker-image docker-push -PLATFORM ?= linux/amd64 .PHONY: docker-image docker-image: @docker buildx build --platform $(PLATFORM) -t $(IMAGE_NAME):$(VERSION) -t $(IMAGE_NAME):latest . diff --git a/hack/api-reference/api.md b/hack/api-reference/api.md index bdb43a3f..8c98dc70 100644 --- a/hack/api-reference/api.md +++ b/hack/api-reference/api.md @@ -156,7 +156,21 @@ string -

PodNetworkCidr is the CIDR range for the pods assigned to this instance.

+(Optional) +

PodNetworkCidr is the CIDR range for the pods assigned to this instance. +Deprecated: use PodNetworkCIDRs instead

+ + + + +podNetworkCIDRs
+ +[]string + + + +(Optional) +

PodNetworkCIDRs is the CIDR ranges for the pods assigned to this instance.

@@ -360,7 +374,21 @@ string -

PodNetworkCidr is the CIDR range for the pods assigned to this instance.

+(Optional) +

PodNetworkCidr is the CIDR range for the pods assigned to this instance. +Deprecated: use PodNetworkCIDRs instead

+ + + + +podNetworkCIDRs
+ +[]string + + + +(Optional) +

PodNetworkCIDRs is the CIDR ranges for the pods assigned to this instance.

diff --git a/pkg/apis/openstack/types.go b/pkg/apis/openstack/types.go index c9ee233d..e6ecaac0 100644 --- a/pkg/apis/openstack/types.go +++ b/pkg/apis/openstack/types.go @@ -40,7 +40,10 @@ type MachineProviderConfigSpec struct { // SubnetID is the ID of the subnet the instance should belong to. If SubnetID is not specified SubnetID *string // PodNetworkCidr is the CIDR range for the pods assigned to this instance. + // Deprecated - use `PodNetworkCIDRs` instead. PodNetworkCidr string + // PodNetworkCidr is the CIDR ranges for the pods assigned to this instance. + PodNetworkCIDRs []string // The size of the root disk used for the instance. RootDiskSize int // The type of the root disk type used for the instance diff --git a/pkg/apis/openstack/v1alpha1/types.go b/pkg/apis/openstack/v1alpha1/types.go index 9c3cf699..7687f392 100644 --- a/pkg/apis/openstack/v1alpha1/types.go +++ b/pkg/apis/openstack/v1alpha1/types.go @@ -43,7 +43,12 @@ type MachineProviderConfigSpec struct { // +optional SubnetID *string `json:"subnetID,omitempty"` // PodNetworkCidr is the CIDR range for the pods assigned to this instance. + // Deprecated: use PodNetworkCIDRs instead + // +optional PodNetworkCidr string `json:"podNetworkCidr"` + // PodNetworkCIDRs is the CIDR ranges for the pods assigned to this instance. + // +optional + PodNetworkCIDRs []string `json:"podNetworkCIDRs"` // The size of the root disk used for the instance. RootDiskSize int `json:"rootDiskSize,omitempty"` // in GB // The type of the root disk used for the instance. diff --git a/pkg/apis/openstack/v1alpha1/zz_generated.conversion.go b/pkg/apis/openstack/v1alpha1/zz_generated.conversion.go index 53c1b6b8..52a19d1f 100644 --- a/pkg/apis/openstack/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/openstack/v1alpha1/zz_generated.conversion.go @@ -93,6 +93,7 @@ func autoConvert_v1alpha1_MachineProviderConfigSpec_To_openstack_MachineProvider out.NetworkID = in.NetworkID out.SubnetID = (*string)(unsafe.Pointer(in.SubnetID)) out.PodNetworkCidr = in.PodNetworkCidr + out.PodNetworkCIDRs = *(*[]string)(unsafe.Pointer(&in.PodNetworkCIDRs)) out.RootDiskSize = in.RootDiskSize out.RootDiskType = (*string)(unsafe.Pointer(in.RootDiskType)) out.UseConfigDrive = (*bool)(unsafe.Pointer(in.UseConfigDrive)) @@ -118,6 +119,7 @@ func autoConvert_openstack_MachineProviderConfigSpec_To_v1alpha1_MachineProvider out.NetworkID = in.NetworkID out.SubnetID = (*string)(unsafe.Pointer(in.SubnetID)) out.PodNetworkCidr = in.PodNetworkCidr + out.PodNetworkCIDRs = *(*[]string)(unsafe.Pointer(&in.PodNetworkCIDRs)) out.RootDiskSize = in.RootDiskSize out.RootDiskType = (*string)(unsafe.Pointer(in.RootDiskType)) out.UseConfigDrive = (*bool)(unsafe.Pointer(in.UseConfigDrive)) diff --git a/pkg/apis/openstack/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/openstack/v1alpha1/zz_generated.deepcopy.go index 5d3efb81..f6872f7c 100644 --- a/pkg/apis/openstack/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/openstack/v1alpha1/zz_generated.deepcopy.go @@ -59,6 +59,11 @@ func (in *MachineProviderConfigSpec) DeepCopyInto(out *MachineProviderConfigSpec *out = new(string) **out = **in } + if in.PodNetworkCIDRs != nil { + in, out := &in.PodNetworkCIDRs, &out.PodNetworkCIDRs + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.RootDiskType != nil { in, out := &in.RootDiskType, &out.RootDiskType *out = new(string) diff --git a/pkg/apis/openstack/zz_generated.deepcopy.go b/pkg/apis/openstack/zz_generated.deepcopy.go index 9d78e6df..cd076d08 100644 --- a/pkg/apis/openstack/zz_generated.deepcopy.go +++ b/pkg/apis/openstack/zz_generated.deepcopy.go @@ -59,6 +59,11 @@ func (in *MachineProviderConfigSpec) DeepCopyInto(out *MachineProviderConfigSpec *out = new(string) **out = **in } + if in.PodNetworkCIDRs != nil { + in, out := &in.PodNetworkCIDRs, &out.PodNetworkCIDRs + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.RootDiskType != nil { in, out := &in.RootDiskType, &out.RootDiskType *out = new(string) diff --git a/pkg/apis/validation/validation.go b/pkg/apis/validation/validation.go index 5714db12..1a6e6327 100644 --- a/pkg/apis/validation/validation.go +++ b/pkg/apis/validation/validation.go @@ -57,20 +57,20 @@ func validateMachineProviderConfig(providerConfig *openstack.MachineProviderConf if "" == providerConfig.Spec.NetworkID && len(providerConfig.Spec.Networks) == 0 { allErrs = append(allErrs, field.Forbidden(fldPath.Child("networkID"), "both \"networks\" and \"networkID\" should not be empty")) } - if "" == providerConfig.Spec.PodNetworkCidr { - allErrs = append(allErrs, field.Required(fldPath.Child("podNetworkCidr"), "PodNetworkCidr is required")) + if len(providerConfig.Spec.PodNetworkCIDRs) == 0 && len(providerConfig.Spec.PodNetworkCidr) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("PodNetworkCIDRs"), "PodNetworkCIDRs is required")) } if providerConfig.Spec.RootDiskSize < 0 { allErrs = append(allErrs, field.Required(fldPath.Child("rootDiskSize"), "RootDiskSize can not be negative")) } - allErrs = append(allErrs, validateNetworks(providerConfig.Spec.Networks, providerConfig.Spec.PodNetworkCidr, field.NewPath("spec.networks"))...) + allErrs = append(allErrs, validateNetworks(providerConfig.Spec.Networks, providerConfig.Spec.PodNetworkCidr, providerConfig.Spec.PodNetworkCIDRs, field.NewPath("spec.networks"))...) allErrs = append(allErrs, validateClassSpecTags(providerConfig.Spec.Tags, field.NewPath("spec.tags"))...) return allErrs } -func validateNetworks(networks []openstack.OpenStackNetwork, podNetworkCidr string, fldPath *field.Path) field.ErrorList { +func validateNetworks(networks []openstack.OpenStackNetwork, podNetworkCidr string, podNetworkCIDRs []string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for index, network := range networks { @@ -81,7 +81,7 @@ func validateNetworks(networks []openstack.OpenStackNetwork, podNetworkCidr stri if "" != network.Id && "" != network.Name { allErrs = append(allErrs, field.Forbidden(fldPath, "simultaneous use of network \"id\" and \"name\" is forbidden")) } - if "" == podNetworkCidr && network.PodNetwork { + if len(podNetworkCIDRs) == 0 && len(podNetworkCidr) == 0 && network.PodNetwork { allErrs = append(allErrs, field.Required(fldPath.Child("podNetwork"), "\"podNetwork\" switch should not be used in absence of \"spec.podNetworkCidr\"")) } } diff --git a/pkg/apis/validation/validation_test.go b/pkg/apis/validation/validation_test.go index 6af9c414..81426531 100644 --- a/pkg/apis/validation/validation_test.go +++ b/pkg/apis/validation/validation_test.go @@ -36,13 +36,13 @@ var _ = Describe("Validation", func() { fmt.Sprintf("%s-foo", ServerTagRolePrefix): "1", fmt.Sprintf("%s-foo", ServerTagClusterPrefix): "1", }, - NetworkID: "networkID", - SubnetID: nil, - PodNetworkCidr: "10.0.0.1/8", - RootDiskSize: 0, - UseConfigDrive: nil, - ServerGroupID: nil, - Networks: nil, + NetworkID: "networkID", + SubnetID: nil, + PodNetworkCIDRs: []string{"10.0.0.1/8"}, + RootDiskSize: 0, + UseConfigDrive: nil, + ServerGroupID: nil, + Networks: nil, }, } }) @@ -59,7 +59,7 @@ var _ = Describe("Validation", func() { spec.FlavorName = "" spec.AvailabilityZone = "" spec.KeyName = "" - spec.PodNetworkCidr = "" + spec.PodNetworkCIDRs = nil err := validateMachineProviderConfig(machineProviderConfig) Expect(err).To(ConsistOf( @@ -81,7 +81,7 @@ var _ = Describe("Validation", func() { })), PointTo(MatchFields(IgnoreExtras, Fields{ "Type": BeEquivalentTo("FieldValueRequired"), - "Field": Equal("spec.podNetworkCidr"), + "Field": Equal("spec.PodNetworkCIDRs"), })), )) }) diff --git a/pkg/driver/executor/executor.go b/pkg/driver/executor/executor.go index 99cec5db..c2c5be9a 100644 --- a/pkg/driver/executor/executor.go +++ b/pkg/driver/executor/executor.go @@ -19,7 +19,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/klog/v2" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" api "github.com/gardener/machine-controller-manager-provider-openstack/pkg/apis/openstack" "github.com/gardener/machine-controller-manager-provider-openstack/pkg/client" @@ -134,7 +134,7 @@ func (ex *Executor) resolveServerNetworks(ctx context.Context, machineName strin return serverNetworks, nil } - if !isEmptyString(pointer.StringPtr(networkID)) { + if !isEmptyString(ptr.To(networkID)) { klog.V(3).Infof("deploying in network [ID=%q]", networkID) serverNetworks = append(serverNetworks, servers.Network{UUID: ex.Config.Spec.NetworkID}) return serverNetworks, nil @@ -145,7 +145,7 @@ func (ex *Executor) resolveServerNetworks(ctx context.Context, machineName strin resolvedNetworkID string err error ) - if isEmptyString(pointer.StringPtr(network.Id)) { + if isEmptyString(ptr.To(network.Id)) { resolvedNetworkID, err = ex.Network.NetworkIDFromName(network.Name) if err != nil { return nil, err @@ -383,27 +383,34 @@ func (ex *Executor) patchServerPortsForPodNetwork(serverID string) error { return fmt.Errorf("failed to resolve network IDs for the pod network %v", err) } + // coalesce all pod network CIDRs into a single slice. + podCIDRs := sets.NewString(ex.Config.Spec.PodNetworkCIDRs...) + if ex.Config.Spec.PodNetworkCidr != "" { + podCIDRs.Insert(ex.Config.Spec.PodNetworkCidr) + } + for _, port := range allPorts { - if podNetworkIDs.Has(port.NetworkID) { - addressPairFound := false - - for _, pair := range port.AllowedAddressPairs { - if pair.IPAddress == ex.Config.Spec.PodNetworkCidr { - klog.V(3).Infof("port [ID=%q] already allows pod network CIDR range. Skipping update...", port.ID) - addressPairFound = true - // break inner loop if target found - break - } - } - // continue outer loop if target found - if addressPairFound { - continue - } + // if the port is not part of the networks we care about, continue. + if !podNetworkIDs.Has(port.NetworkID) { + continue + } - if err := ex.Network.UpdatePort(port.ID, ports.UpdateOpts{ - AllowedAddressPairs: &[]ports.AddressPair{{IPAddress: ex.Config.Spec.PodNetworkCidr}}, - }); err != nil { - return fmt.Errorf("failed to update allowed address pair for port [ID=%q]: %v", port.ID, err) + for _, cidr := range podCIDRs.List() { + if err := func() error { + for _, pair := range port.AllowedAddressPairs { + if pair.IPAddress == cidr { + klog.V(3).Infof("port [ID=%q] already allows pod network CIDR range. Skipping update...", port.ID) + return nil + } + } + if err := ex.Network.UpdatePort(port.ID, ports.UpdateOpts{ + AllowedAddressPairs: &[]ports.AddressPair{{IPAddress: cidr}}, + }); err != nil { + return fmt.Errorf("failed to update allowed address pair for port [ID=%q]: %v", port.ID, err) + } + return nil + }(); err != nil { + return err } } } @@ -411,14 +418,14 @@ func (ex *Executor) patchServerPortsForPodNetwork(serverID string) error { } // resolveNetworkIDsForPodNetwork resolves the networks that accept traffic from the pod CIDR range. -func (ex *Executor) resolveNetworkIDsForPodNetwork() (sets.String, error) { +func (ex *Executor) resolveNetworkIDsForPodNetwork() (sets.Set[string], error) { var ( networkID = ex.Config.Spec.NetworkID networks = ex.Config.Spec.Networks - podNetworkIDs = sets.NewString() + podNetworkIDs = sets.New[string]() ) - if !isEmptyString(pointer.StringPtr(networkID)) { + if !isEmptyString(ptr.To(networkID)) { podNetworkIDs.Insert(networkID) return podNetworkIDs, nil } @@ -428,7 +435,7 @@ func (ex *Executor) resolveNetworkIDsForPodNetwork() (sets.String, error) { resolvedNetworkID string err error ) - if isEmptyString(pointer.StringPtr(network.Id)) { + if isEmptyString(ptr.To(network.Id)) { resolvedNetworkID, err = ex.Network.NetworkIDFromName(network.Name) if err != nil { return nil, err @@ -451,7 +458,7 @@ func (ex *Executor) DeleteMachine(ctx context.Context, machineName, providerID s err error ) - if !isEmptyString(pointer.StringPtr(providerID)) { + if !isEmptyString(ptr.To(providerID)) { serverID := decodeProviderID(providerID) server, err = ex.getMachineByID(ctx, serverID) } else { @@ -514,11 +521,10 @@ func (ex *Executor) getOrCreatePort(_ context.Context, machineName string) (stri } port, err := ex.Network.CreatePort(&ports.CreateOpts{ - Name: machineName, - NetworkID: ex.Config.Spec.NetworkID, - FixedIPs: []ports.IP{{SubnetID: *ex.Config.Spec.SubnetID}}, - AllowedAddressPairs: []ports.AddressPair{{IPAddress: ex.Config.Spec.PodNetworkCidr}}, - SecurityGroups: &securityGroupIDs, + Name: machineName, + NetworkID: ex.Config.Spec.NetworkID, + FixedIPs: []ports.IP{{SubnetID: *ex.Config.Spec.SubnetID}}, + SecurityGroups: &securityGroupIDs, }) if err != nil { return "", err @@ -695,5 +701,5 @@ func (ex *Executor) listServers(_ context.Context) ([]servers.Server, error) { // isUserManagedNetwork returns true if the port used by the machine will be created and managed by MCM. func (ex *Executor) isUserManagedNetwork() bool { - return !isEmptyString(pointer.StringPtr(ex.Config.Spec.NetworkID)) && !isEmptyString(ex.Config.Spec.SubnetID) + return !isEmptyString(ptr.To(ex.Config.Spec.NetworkID)) && !isEmptyString(ex.Config.Spec.SubnetID) }