diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index da07b7eee..7a2b155ed 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -36,7 +36,9 @@ jobs: with: enable_workaround_docker_io: 'false' branch: ${{ matrix.openstack_version }} - enabled_services: "openstack-cli-server" + enabled_services: "openstack-cli-server,neutron-uplink-status-propagation" + conf_overrides: | + enable_plugin neutron https://opendev.org/openstack/neutron.git ${{ matrix.openstack_version }} - name: Deploy a Kind Cluster uses: helm/kind-action@92086f6be054225fa813e0a4b13787fc9088faab diff --git a/api/v1alpha1/port_types.go b/api/v1alpha1/port_types.go index 9e51d0153..055e1855e 100644 --- a/api/v1alpha1/port_types.go +++ b/api/v1alpha1/port_types.go @@ -185,6 +185,12 @@ type PortResourceSpec struct { // +kubebuilder:validation:MaxLength=36 // +optional HostID string `json:"hostID,omitempty"` + + // propagateUplinkStatus represents the uplink status propagation of + // the port. + // +optional + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="propagateUplinkStatus is immutable" + PropagateUplinkStatus *bool `json:"propagateUplinkStatus,omitempty"` } type PortResourceStatus struct { diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 74fd9dcdf..28a9f0c77 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -2529,6 +2529,11 @@ func (in *PortResourceSpec) DeepCopyInto(out *PortResourceSpec) { *out = new(KubernetesNameRef) **out = **in } + if in.PropagateUplinkStatus != nil { + in, out := &in.PropagateUplinkStatus, &out.PropagateUplinkStatus + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortResourceSpec. diff --git a/cmd/models-schema/zz_generated.openapi.go b/cmd/models-schema/zz_generated.openapi.go index 3b90d275e..1beb237d8 100644 --- a/cmd/models-schema/zz_generated.openapi.go +++ b/cmd/models-schema/zz_generated.openapi.go @@ -4918,6 +4918,13 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_PortResourceSpec(ref c Format: "", }, }, + "propagateUplinkStatus": { + SchemaProps: spec.SchemaProps{ + Description: "propagateUplinkStatus represents the uplink status propagation of the port.", + Type: []string{"boolean"}, + Format: "", + }, + }, }, Required: []string{"networkRef"}, }, diff --git a/config/crd/bases/openstack.k-orc.cloud_ports.yaml b/config/crd/bases/openstack.k-orc.cloud_ports.yaml index c14173d71..1bc2ea45c 100644 --- a/config/crd/bases/openstack.k-orc.cloud_ports.yaml +++ b/config/crd/bases/openstack.k-orc.cloud_ports.yaml @@ -347,6 +347,14 @@ spec: x-kubernetes-validations: - message: projectRef is immutable rule: self == oldSelf + propagateUplinkStatus: + description: |- + propagateUplinkStatus represents the uplink status propagation of + the port. + type: boolean + x-kubernetes-validations: + - message: propagateUplinkStatus is immutable + rule: self == oldSelf securityGroupRefs: description: |- securityGroupRefs are the names of the security groups associated diff --git a/internal/controllers/port/actuator.go b/internal/controllers/port/actuator.go index 822f6a5be..cc26b393a 100644 --- a/internal/controllers/port/actuator.go +++ b/internal/controllers/port/actuator.go @@ -171,12 +171,13 @@ func (actuator portActuator) CreateResource(ctx context.Context, obj *orcv1alpha } createOpts := ports.CreateOpts{ - NetworkID: *network.Status.ID, - Name: getResourceName(obj), - Description: string(ptr.Deref(resource.Description, "")), - ProjectID: projectID, - AdminStateUp: resource.AdminStateUp, - MACAddress: resource.MACAddress, + NetworkID: *network.Status.ID, + Name: getResourceName(obj), + Description: string(ptr.Deref(resource.Description, "")), + ProjectID: projectID, + AdminStateUp: resource.AdminStateUp, + MACAddress: resource.MACAddress, + PropagateUplinkStatus: resource.PropagateUplinkStatus, } if len(resource.AllowedAddressPairs) > 0 { diff --git a/internal/controllers/port/status.go b/internal/controllers/port/status.go index 379e91e70..221f0dcf0 100644 --- a/internal/controllers/port/status.go +++ b/internal/controllers/port/status.go @@ -67,7 +67,6 @@ func (portStatusWriter) ApplyResourceStatus(log logr.Logger, osResource *osResou WithNetworkID(osResource.NetworkID). WithTags(osResource.Tags...). WithSecurityGroups(osResource.SecurityGroups...). - WithPropagateUplinkStatus(osResource.PropagateUplinkStatus). WithVNICType(osResource.VNICType). WithPortSecurityEnabled(osResource.PortSecurityEnabled). WithRevisionNumber(int64(osResource.RevisionNumber)). @@ -104,5 +103,9 @@ func (portStatusWriter) ApplyResourceStatus(log logr.Logger, osResource *osResou resourceStatus.WithFixedIPs(fixedIPs...) } + if osResource.PropagateUplinkStatusPtr != nil { + resourceStatus.WithPropagateUplinkStatus(*osResource.PropagateUplinkStatusPtr) + } + statusApply.WithResource(resourceStatus) } diff --git a/internal/controllers/port/tests/port-create-full/00-create-resource.yaml b/internal/controllers/port/tests/port-create-full/00-create-resource.yaml index bbb52641d..22c97ca52 100644 --- a/internal/controllers/port/tests/port-create-full/00-create-resource.yaml +++ b/internal/controllers/port/tests/port-create-full/00-create-resource.yaml @@ -86,3 +86,4 @@ spec: projectRef: port-create-full macAddress: fa:16:3e:23:fd:d7 hostID: devstack + propagateUplinkStatus: false diff --git a/internal/controllers/port/tests/port-create-minimal/00-assert.yaml b/internal/controllers/port/tests/port-create-minimal/00-assert.yaml index 9c6d861fc..ba68844fe 100644 --- a/internal/controllers/port/tests/port-create-minimal/00-assert.yaml +++ b/internal/controllers/port/tests/port-create-minimal/00-assert.yaml @@ -8,7 +8,7 @@ status: name: port-create-minimal adminStateUp: true portSecurityEnabled: true - propagateUplinkStatus: false + propagateUplinkStatus: true revisionNumber: 1 status: DOWN vnicType: normal diff --git a/internal/controllers/port/tests/port-create-sriov/00-assert.yaml b/internal/controllers/port/tests/port-create-sriov/00-assert.yaml index 3277dfaea..180f4a512 100644 --- a/internal/controllers/port/tests/port-create-sriov/00-assert.yaml +++ b/internal/controllers/port/tests/port-create-sriov/00-assert.yaml @@ -9,7 +9,7 @@ status: description: Port from "create sriov" test adminStateUp: true portSecurityEnabled: false - propagateUplinkStatus: false + propagateUplinkStatus: true status: DOWN vnicType: direct tags: @@ -35,4 +35,4 @@ assertAll: - celExpr: "port.status.resource.fixedIPs[0].subnetID == subnet.status.id" - celExpr: "port.status.resource.fixedIPs[0].ip == '192.168.155.122'" - celExpr: "!has(port.status.resource.allowedAddressPairs)" - - celExpr: "!has(port.status.resource.securityGroups)" \ No newline at end of file + - celExpr: "!has(port.status.resource.securityGroups)" diff --git a/internal/controllers/port/tests/port-update/00-assert.yaml b/internal/controllers/port/tests/port-update/00-assert.yaml index 6ec7e451d..836189292 100644 --- a/internal/controllers/port/tests/port-update/00-assert.yaml +++ b/internal/controllers/port/tests/port-update/00-assert.yaml @@ -30,7 +30,7 @@ status: name: port-update adminStateUp: true portSecurityEnabled: false - propagateUplinkStatus: false + propagateUplinkStatus: true revisionNumber: 1 status: DOWN vnicType: normal @@ -53,7 +53,7 @@ status: name: port-update-admin adminStateUp: true portSecurityEnabled: true - propagateUplinkStatus: false + propagateUplinkStatus: true revisionNumber: 1 status: DOWN vnicType: normal diff --git a/internal/controllers/port/tests/port-update/01-assert.yaml b/internal/controllers/port/tests/port-update/01-assert.yaml index 1bcaf2d7f..a751a1cdd 100644 --- a/internal/controllers/port/tests/port-update/01-assert.yaml +++ b/internal/controllers/port/tests/port-update/01-assert.yaml @@ -34,7 +34,6 @@ status: description: port-update-updated adminStateUp: true portSecurityEnabled: true - propagateUplinkStatus: false status: DOWN vnicType: direct allowedAddressPairs: @@ -63,4 +62,4 @@ status: reason: Success - type: Progressing status: "False" - reason: Success + reason: Success diff --git a/internal/controllers/port/tests/port-update/02-assert.yaml b/internal/controllers/port/tests/port-update/02-assert.yaml index 314caa5b0..ec19a5fd8 100644 --- a/internal/controllers/port/tests/port-update/02-assert.yaml +++ b/internal/controllers/port/tests/port-update/02-assert.yaml @@ -24,7 +24,7 @@ status: name: port-update adminStateUp: true portSecurityEnabled: false - propagateUplinkStatus: false + propagateUplinkStatus: true status: DOWN vnicType: normal conditions: @@ -35,4 +35,4 @@ status: - type: Progressing message: OpenStack resource is up to date status: "False" - reason: Success \ No newline at end of file + reason: Success diff --git a/internal/osclients/networking.go b/internal/osclients/networking.go index 99156d64e..69b6cf753 100644 --- a/internal/osclients/networking.go +++ b/internal/osclients/networking.go @@ -52,10 +52,19 @@ type NetworkExt struct { provider.NetworkProviderExt } +// NOTE(winiciusallan): This is a temporary extension struct to +// workaround a missing pointer on Gophercloud and must be +// removed in future releases. +// See https://github.com/gophercloud/gophercloud/issues/3605 +type PortTmpExt struct { + PropagateUplinkStatusPtr *bool `json:"propagate_uplink_status,omitempty"` +} + type PortExt struct { ports.Port portsecurity.PortSecurityExt portsbinding.PortsBindingExt + PortTmpExt //nolint:govet } type NetworkClient interface { diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/portresourcespec.go b/pkg/clients/applyconfiguration/api/v1alpha1/portresourcespec.go index aab07d8bc..a157e70ff 100644 --- a/pkg/clients/applyconfiguration/api/v1alpha1/portresourcespec.go +++ b/pkg/clients/applyconfiguration/api/v1alpha1/portresourcespec.go @@ -25,19 +25,20 @@ import ( // PortResourceSpecApplyConfiguration represents a declarative configuration of the PortResourceSpec type for use // with apply. type PortResourceSpecApplyConfiguration struct { - Name *apiv1alpha1.OpenStackName `json:"name,omitempty"` - Description *apiv1alpha1.NeutronDescription `json:"description,omitempty"` - NetworkRef *apiv1alpha1.KubernetesNameRef `json:"networkRef,omitempty"` - Tags []apiv1alpha1.NeutronTag `json:"tags,omitempty"` - AllowedAddressPairs []AllowedAddressPairApplyConfiguration `json:"allowedAddressPairs,omitempty"` - Addresses []AddressApplyConfiguration `json:"addresses,omitempty"` - AdminStateUp *bool `json:"adminStateUp,omitempty"` - SecurityGroupRefs []apiv1alpha1.OpenStackName `json:"securityGroupRefs,omitempty"` - VNICType *string `json:"vnicType,omitempty"` - PortSecurity *apiv1alpha1.PortSecurityState `json:"portSecurity,omitempty"` - ProjectRef *apiv1alpha1.KubernetesNameRef `json:"projectRef,omitempty"` - MACAddress *string `json:"macAddress,omitempty"` - HostID *string `json:"hostID,omitempty"` + Name *apiv1alpha1.OpenStackName `json:"name,omitempty"` + Description *apiv1alpha1.NeutronDescription `json:"description,omitempty"` + NetworkRef *apiv1alpha1.KubernetesNameRef `json:"networkRef,omitempty"` + Tags []apiv1alpha1.NeutronTag `json:"tags,omitempty"` + AllowedAddressPairs []AllowedAddressPairApplyConfiguration `json:"allowedAddressPairs,omitempty"` + Addresses []AddressApplyConfiguration `json:"addresses,omitempty"` + AdminStateUp *bool `json:"adminStateUp,omitempty"` + SecurityGroupRefs []apiv1alpha1.OpenStackName `json:"securityGroupRefs,omitempty"` + VNICType *string `json:"vnicType,omitempty"` + PortSecurity *apiv1alpha1.PortSecurityState `json:"portSecurity,omitempty"` + ProjectRef *apiv1alpha1.KubernetesNameRef `json:"projectRef,omitempty"` + MACAddress *string `json:"macAddress,omitempty"` + HostID *string `json:"hostID,omitempty"` + PropagateUplinkStatus *bool `json:"propagateUplinkStatus,omitempty"` } // PortResourceSpecApplyConfiguration constructs a declarative configuration of the PortResourceSpec type for use with @@ -163,3 +164,11 @@ func (b *PortResourceSpecApplyConfiguration) WithHostID(value string) *PortResou b.HostID = &value return b } + +// WithPropagateUplinkStatus sets the PropagateUplinkStatus field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the PropagateUplinkStatus field is set to the value of the last call. +func (b *PortResourceSpecApplyConfiguration) WithPropagateUplinkStatus(value bool) *PortResourceSpecApplyConfiguration { + b.PropagateUplinkStatus = &value + return b +} diff --git a/pkg/clients/applyconfiguration/internal/internal.go b/pkg/clients/applyconfiguration/internal/internal.go index abaeca27f..b6805275f 100644 --- a/pkg/clients/applyconfiguration/internal/internal.go +++ b/pkg/clients/applyconfiguration/internal/internal.go @@ -1351,6 +1351,9 @@ var schemaYAML = typed.YAMLObject(`types: - name: projectRef type: scalar: string + - name: propagateUplinkStatus + type: + scalar: boolean - name: securityGroupRefs type: list: diff --git a/website/docs/crd-reference.md b/website/docs/crd-reference.md index 32018f962..ae1df1118 100644 --- a/website/docs/crd-reference.md +++ b/website/docs/crd-reference.md @@ -2172,6 +2172,7 @@ _Appears in:_ | `projectRef` _[KubernetesNameRef](#kubernetesnameref)_ | projectRef is a reference to the ORC Project this resource is associated with.
Typically, only used by admin. | | MaxLength: 253
MinLength: 1
| | `macAddress` _string_ | macAddress is the MAC address of the port. | | MaxLength: 32
| | `hostID` _string_ | hostID is the ID of host where the port resides. | | MaxLength: 36
| +| `propagateUplinkStatus` _boolean_ | propagateUplinkStatus represents the uplink status propagation of
the port. | | | #### PortResourceStatus