Skip to content

Commit 0ff2b62

Browse files
authored
Merge pull request #678 from shiftstack/port-binding-immutable
port: make hostID immutable
2 parents f1fbda2 + f72c9a3 commit 0ff2b62

11 files changed

Lines changed: 34 additions & 96 deletions

File tree

api/v1alpha1/port_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,13 @@ type PortResourceSpec struct {
202202
MACAddress string `json:"macAddress,omitempty"`
203203

204204
// hostID specifies the host where the port will be bound.
205+
// Note that when the port is attached to a server, OpenStack may
206+
// rebind the port to the server's actual compute host, which may
207+
// differ from the specified hostID if no matching scheduler hint
208+
// is used. In this case the port's status will reflect the actual
209+
// binding host, not the value specified here.
205210
// +optional
211+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="hostID is immutable"
206212
HostID *HostID `json:"hostID,omitempty"`
207213
}
208214

cmd/models-schema/zz_generated.openapi.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/openstack.k-orc.cloud_ports.yaml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,13 @@ spec:
300300
minLength: 1
301301
type: string
302302
hostID:
303-
description: hostID specifies the host where the port will be
304-
bound.
303+
description: |-
304+
hostID specifies the host where the port will be bound.
305+
Note that when the port is attached to a server, OpenStack may
306+
rebind the port to the server's actual compute host, which may
307+
differ from the specified hostID if no matching scheduler hint
308+
is used. In this case the port's status will reflect the actual
309+
binding host, not the value specified here.
305310
maxProperties: 1
306311
minProperties: 1
307312
properties:
@@ -322,6 +327,8 @@ spec:
322327
type: string
323328
type: object
324329
x-kubernetes-validations:
330+
- message: hostID is immutable
331+
rule: self == oldSelf
325332
- message: exactly one of id or serverRef must be set
326333
rule: (has(self.id) && size(self.id) > 0) != (has(self.serverRef)
327334
&& size(self.serverRef) > 0)

internal/controllers/port/actuator.go

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -377,14 +377,6 @@ func (actuator portActuator) updateResource(ctx context.Context, obj orcObjectPT
377377
reconcileStatus := progress.NewReconcileStatus().
378378
WithReconcileStatus(secGroupDepRS)
379379

380-
// Resolve hostID if specified
381-
var resolvedHostID string
382-
if resource.HostID != nil {
383-
var hostIDReconcileStatus progress.ReconcileStatus
384-
resolvedHostID, hostIDReconcileStatus = resolveHostID(ctx, actuator.k8sClient, obj, resource.HostID)
385-
reconcileStatus = reconcileStatus.WithReconcileStatus(hostIDReconcileStatus)
386-
}
387-
388380
needsReschedule, _ := reconcileStatus.NeedsReschedule()
389381
if needsReschedule {
390382
return reconcileStatus
@@ -403,7 +395,7 @@ func (actuator portActuator) updateResource(ctx context.Context, obj orcObjectPT
403395
updateOpts = baseUpdateOpts
404396
}
405397

406-
updateOpts = handlePortBindingUpdate(updateOpts, resource, osResource, resolvedHostID)
398+
updateOpts = handlePortBindingUpdate(updateOpts, resource, osResource)
407399
updateOpts = handlePortSecurityUpdate(updateOpts, resource, osResource)
408400

409401
needsUpdate, err := needsUpdate(updateOpts)
@@ -529,7 +521,7 @@ func handleSecurityGroupRefsUpdate(updateOpts *ports.UpdateOpts, resource *resou
529521
}
530522
}
531523

532-
func handlePortBindingUpdate(updateOpts ports.UpdateOptsBuilder, resource *resourceSpecT, osResource *osResourceT, resolvedHostID string) ports.UpdateOptsBuilder {
524+
func handlePortBindingUpdate(updateOpts ports.UpdateOptsBuilder, resource *resourceSpecT, osResource *osResourceT) ports.UpdateOptsBuilder {
533525
if resource.VNICType != "" {
534526
if resource.VNICType != osResource.VNICType {
535527
updateOpts = &portsbinding.UpdateOptsExt{
@@ -539,15 +531,6 @@ func handlePortBindingUpdate(updateOpts ports.UpdateOptsBuilder, resource *resou
539531
}
540532
}
541533

542-
if resolvedHostID != "" {
543-
if resolvedHostID != osResource.HostID {
544-
updateOpts = &portsbinding.UpdateOptsExt{
545-
UpdateOptsBuilder: updateOpts,
546-
HostID: &resolvedHostID,
547-
}
548-
}
549-
}
550-
551534
return updateOpts
552535
}
553536

internal/controllers/port/actuator_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ func TestHandlePortBindingUpdate(t *testing.T) {
359359
},
360360
}
361361

362-
updateOpts := handlePortBindingUpdate(&ports.UpdateOpts{}, resource, osResource, "")
362+
updateOpts := handlePortBindingUpdate(&ports.UpdateOpts{}, resource, osResource)
363363

364364
got, _ := needsUpdate(updateOpts)
365365
if got != tt.expectChange {

internal/controllers/port/tests/port-update/00-assert.yaml

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,13 @@ resourceRefs:
66
kind: port
77
name: port-update
88
ref: port
9-
- apiVersion: openstack.k-orc.cloud/v1alpha1
10-
kind: port
11-
name: port-update-admin
12-
ref: portAdmin
139
assertAll:
1410
- celExpr: "port.status.id != ''"
1511
- celExpr: "port.status.resource.createdAt != ''"
1612
- celExpr: "port.status.resource.updatedAt != ''"
1713
- celExpr: "port.status.resource.macAddress != ''"
1814
- celExpr: "!has(port.status.resource.fixedIPs)"
1915
- celExpr: "!has(port.status.resource.description)"
20-
# Following the network API reference, the default value for
21-
# hostID field is an empty string.
22-
- celExpr: "portAdmin.status.resource.hostID == ''"
2316
---
2417
apiVersion: openstack.k-orc.cloud/v1alpha1
2518
kind: Port
@@ -43,26 +36,3 @@ status:
4336
message: OpenStack resource is up to date
4437
status: "False"
4538
reason: Success
46-
---
47-
apiVersion: openstack.k-orc.cloud/v1alpha1
48-
kind: Port
49-
metadata:
50-
name: port-update-admin
51-
status:
52-
resource:
53-
name: port-update-admin
54-
adminStateUp: true
55-
portSecurityEnabled: true
56-
propagateUplinkStatus: false
57-
revisionNumber: 1
58-
status: DOWN
59-
vnicType: normal
60-
conditions:
61-
- type: Available
62-
message: OpenStack resource is available
63-
status: "True"
64-
reason: Success
65-
- type: Progressing
66-
message: OpenStack resource is up to date
67-
status: "False"
68-
reason: Success

internal/controllers/port/tests/port-update/00-minimal-resource.yaml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,3 @@ spec:
1212
portSecurity: Disabled
1313
# Need to set the default values to revert them correctly in the 02-revert-resource step.
1414
vnicType: normal
15-
---
16-
# This port is intended to be used only to test fields editable
17-
# by admin users
18-
apiVersion: openstack.k-orc.cloud/v1alpha1
19-
kind: Port
20-
metadata:
21-
name: port-update-admin
22-
spec:
23-
cloudCredentialsRef:
24-
cloudName: openstack-admin
25-
secretName: openstack-clouds
26-
managementPolicy: managed
27-
resource:
28-
networkRef: port-update

internal/controllers/port/tests/port-update/01-assert.yaml

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,3 @@ status:
4949
- type: Progressing
5050
status: "False"
5151
reason: Success
52-
---
53-
apiVersion: openstack.k-orc.cloud/v1alpha1
54-
kind: Port
55-
metadata:
56-
name: port-update-admin
57-
status:
58-
resource:
59-
hostID: devstack
60-
conditions:
61-
- type: Available
62-
status: "True"
63-
reason: Success
64-
- type: Progressing
65-
status: "False"
66-
reason: Success

internal/controllers/port/tests/port-update/01-updated-resource.yaml

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,3 @@ spec:
2020
- tag1
2121
vnicType: direct
2222
portSecurity: Enabled
23-
---
24-
apiVersion: openstack.k-orc.cloud/v1alpha1
25-
kind: Port
26-
metadata:
27-
name: port-update-admin
28-
spec:
29-
cloudCredentialsRef:
30-
cloudName: openstack-admin
31-
secretName: openstack-clouds
32-
managementPolicy: managed
33-
resource:
34-
hostID:
35-
id: devstack

test/apivalidations/port_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,20 @@ var _ = Describe("ORC Port API validations", func() {
123123
Expect(applyObj(ctx, port, patch)).To(MatchError(ContainSubstring("spec.resource.vnicType: Too long: may not be longer than 64")))
124124
})
125125

126+
It("should not allow hostID to be modified", func(ctx context.Context) {
127+
port := portStub(namespace)
128+
patch := basePortPatch(port)
129+
patch.Spec.WithResource(applyconfigv1alpha1.PortResourceSpec().
130+
WithNetworkRef(networkName).
131+
WithHostID(applyconfigv1alpha1.HostID().WithID("host-a")))
132+
Expect(applyObj(ctx, port, patch)).To(Succeed())
133+
134+
patch.Spec.WithResource(applyconfigv1alpha1.PortResourceSpec().
135+
WithNetworkRef(networkName).
136+
WithHostID(applyconfigv1alpha1.HostID().WithID("host-b")))
137+
Expect(applyObj(ctx, port, patch)).To(MatchError(ContainSubstring("hostID is immutable")))
138+
})
139+
126140
// Note: we can't create a test for when the portSecurity is set to Inherit and the securityGroupRefs are set, because
127141
// the validation is done in the OpenStack API and not in the ORC API. The OpenStack API will return an error if
128142
// the network has port security disabled and the port has security group references.

0 commit comments

Comments
 (0)