Skip to content

Commit 92bd149

Browse files
Huy Mailentzi90
authored andcommitted
Ensure that existing ports also have correct tags and trunks
Signed-off-by: Huy Mai <huy.mai@est.tech>
1 parent 72611bc commit 92bd149

File tree

5 files changed

+83
-37
lines changed

5 files changed

+83
-37
lines changed

controllers/openstackserver_controller.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -418,11 +418,7 @@ func getOrCreateServerPorts(openStackServer *infrav1alpha1.OpenStackServer, netw
418418
}
419419
desiredPorts := resolved.Ports
420420

421-
if len(desiredPorts) == len(resources.Ports) {
422-
return nil
423-
}
424-
425-
if err := networkingService.CreatePorts(openStackServer, desiredPorts, resources); err != nil {
421+
if err := networkingService.EnsurePorts(openStackServer, desiredPorts, resources); err != nil {
426422
return fmt.Errorf("creating ports: %w", err)
427423
}
428424

controllers/openstackserver_controller_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ func Test_OpenStackServerReconcileCreate(t *testing.T) {
479479
listDefaultPortsNotFound(r)
480480
createDefaultPort(r)
481481
listDefaultServerNotFound(r)
482+
listDefaultPortsNotFound(r)
482483
createDefaultServer(r)
483484
},
484485
},
@@ -499,6 +500,7 @@ func Test_OpenStackServerReconcileCreate(t *testing.T) {
499500
},
500501
},
501502
expect: func(r *recorders) {
503+
listDefaultPorts(r)
502504
listDefaultPorts(r)
503505
listDefaultServerFound(r)
504506
},

pkg/cloud/services/networking/port.go

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,49 @@ func (s *Service) GetPortForExternalNetwork(instanceID string, externalNetworkID
124124
return nil, nil
125125
}
126126

127-
func (s *Service) CreatePort(eventObject runtime.Object, portSpec *infrav1.ResolvedPortSpec) (*ports.Port, error) {
127+
// ensurePortTagsAndTrunk ensures that the provided port has the tags and trunk defined in portSpec.
128+
func (s *Service) ensurePortTagsAndTrunk(port *ports.Port, eventObject runtime.Object, portSpec *infrav1.ResolvedPortSpec) error {
129+
if len(portSpec.Tags) > 0 {
130+
if err := s.replaceAllAttributesTags(eventObject, portResource, port.ID, portSpec.Tags); err != nil {
131+
record.Warnf(eventObject, "FailedReplaceTags", "Failed to replace port tags %s: %v", portSpec.Name, err)
132+
return err
133+
}
134+
}
135+
if ptr.Deref(portSpec.Trunk, false) {
136+
trunk, err := s.getOrCreateTrunkForPort(eventObject, port)
137+
if err != nil {
138+
record.Warnf(eventObject, "FailedCreateTrunk", "Failed to create trunk for port %s: %v", port.Name, err)
139+
return err
140+
}
141+
if err = s.replaceAllAttributesTags(eventObject, trunkResource, trunk.ID, portSpec.Tags); err != nil {
142+
record.Warnf(eventObject, "FailedReplaceTags", "Failed to replace trunk tags %s: %v", port.Name, err)
143+
return err
144+
}
145+
}
146+
return nil
147+
}
148+
149+
// EnsurePort ensure that a port defined with portSpec Name and NetworkID exists,
150+
// and that the port has suitable tags and trunk.
151+
func (s *Service) EnsurePort(eventObject runtime.Object, portSpec *infrav1.ResolvedPortSpec) (*ports.Port, error) {
152+
existingPorts, err := s.client.ListPort(ports.ListOpts{
153+
Name: portSpec.Name,
154+
NetworkID: portSpec.NetworkID,
155+
})
156+
if err != nil {
157+
return nil, fmt.Errorf("searching for existing port for server: %v", err)
158+
}
159+
if len(existingPorts) > 1 {
160+
return nil, fmt.Errorf("multiple ports found with name \"%s\"", portSpec.Name)
161+
}
162+
163+
if len(existingPorts) == 1 {
164+
port := &existingPorts[0]
165+
if err = s.ensurePortTagsAndTrunk(port, eventObject, portSpec); err != nil {
166+
return nil, err
167+
}
168+
return port, nil
169+
}
128170
var addressPairs []ports.AddressPair
129171
if !ptr.Deref(portSpec.DisablePortSecurity, false) {
130172
for _, ap := range portSpec.AllowedAddressPairs {
@@ -200,24 +242,10 @@ func (s *Service) CreatePort(eventObject runtime.Object, portSpec *infrav1.Resol
200242
return nil, err
201243
}
202244

203-
if len(portSpec.Tags) > 0 {
204-
if err = s.replaceAllAttributesTags(eventObject, portResource, port.ID, portSpec.Tags); err != nil {
205-
record.Warnf(eventObject, "FailedReplaceTags", "Failed to replace port tags %s: %v", portSpec.Name, err)
206-
return nil, err
207-
}
245+
if err = s.ensurePortTagsAndTrunk(port, eventObject, portSpec); err != nil {
246+
return nil, err
208247
}
209248
record.Eventf(eventObject, "SuccessfulCreatePort", "Created port %s with id %s", port.Name, port.ID)
210-
if ptr.Deref(portSpec.Trunk, false) {
211-
trunk, err := s.getOrCreateTrunkForPort(eventObject, port)
212-
if err != nil {
213-
record.Warnf(eventObject, "FailedCreateTrunk", "Failed to create trunk for port %s: %v", port.Name, err)
214-
return nil, err
215-
}
216-
if err = s.replaceAllAttributesTags(eventObject, trunkResource, trunk.ID, portSpec.Tags); err != nil {
217-
record.Warnf(eventObject, "FailedReplaceTags", "Failed to replace trunk tags %s: %v", port.Name, err)
218-
return nil, err
219-
}
220-
}
221249

222250
return port, nil
223251
}
@@ -328,16 +356,12 @@ func getPortName(baseName string, portSpec *infrav1.PortOpts, netIndex int) stri
328356
return fmt.Sprintf("%s-%d", baseName, netIndex)
329357
}
330358

331-
func (s *Service) CreatePorts(eventObject runtime.Object, desiredPorts []infrav1.ResolvedPortSpec, resources *infrav1alpha1.ServerResources) error {
332-
for i := range desiredPorts {
333-
// Skip creation of ports which already exist
334-
if i < len(resources.Ports) {
335-
continue
336-
}
337-
338-
portSpec := &desiredPorts[i]
339-
// Events are recorded in CreatePort
340-
port, err := s.CreatePort(eventObject, portSpec)
359+
// EnsurePorts ensures that every one of desiredPorts is created and has
360+
// expected trunk and tags.
361+
func (s *Service) EnsurePorts(eventObject runtime.Object, desiredPorts []infrav1.ResolvedPortSpec, resources *infrav1alpha1.ServerResources) error {
362+
for _, portSpec := range desiredPorts {
363+
// Events are recorded in EnsurePort
364+
port, err := s.EnsurePort(eventObject, &portSpec)
341365
if err != nil {
342366
return err
343367
}

pkg/cloud/services/networking/port_test.go

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import (
4141
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
4242
)
4343

44-
func Test_CreatePort(t *testing.T) {
44+
func Test_EnsurePort(t *testing.T) {
4545
// Arbitrary values used in the tests
4646
const (
4747
netID = "7fd24ceb-788a-441f-ad0a-d8e2f5d31a1d"
@@ -60,8 +60,8 @@ func Test_CreatePort(t *testing.T) {
6060
name string
6161
port infrav1.ResolvedPortSpec
6262
expect func(m *mock.MockNetworkClientMockRecorder, g Gomega)
63-
// Note the 'wanted' port isn't so important, since it will be whatever we tell ListPort or CreatePort to return.
64-
// Mostly in this test suite, we're checking that CreatePort is called with the expected port opts.
63+
// Note the 'wanted' port isn't so important, since it will be whatever we tell ListPort or EnsurePort to return.
64+
// Mostly in this test suite, we're checking that EnsurePort is called with the expected port opts.
6565
want *ports.Port
6666
wantErr bool
6767
}{
@@ -157,6 +157,10 @@ func Test_CreatePort(t *testing.T) {
157157
},
158158
}
159159

160+
m.ListPort(ports.ListOpts{
161+
Name: "foo-port-1",
162+
NetworkID: netID,
163+
}).Return(nil, nil)
160164
// The following allows us to use gomega to
161165
// compare the argument instead of gomock.
162166
// Gomock's output in the case of a mismatch is
@@ -184,6 +188,10 @@ func Test_CreatePort(t *testing.T) {
184188
expectedCreateOpts = portsbinding.CreateOptsExt{
185189
CreateOptsBuilder: expectedCreateOpts,
186190
}
191+
m.ListPort(ports.ListOpts{
192+
Name: "test-port",
193+
NetworkID: netID,
194+
}).Return(nil, nil)
187195
m.CreatePort(gomock.Any()).DoAndReturn(func(builder ports.CreateOptsBuilder) (*ports.Port, error) {
188196
gotCreateOpts := builder.(portsbinding.CreateOptsExt)
189197
g.Expect(gotCreateOpts).To(Equal(expectedCreateOpts), cmp.Diff(gotCreateOpts, expectedCreateOpts))
@@ -203,6 +211,10 @@ func Test_CreatePort(t *testing.T) {
203211
SecurityGroups: []string{portSecurityGroupID},
204212
},
205213
expect: func(m *mock.MockNetworkClientMockRecorder, _ Gomega) {
214+
m.ListPort(ports.ListOpts{
215+
Name: "test-port",
216+
NetworkID: netID,
217+
}).Return(nil, nil)
206218
m.CreatePort(gomock.Any()).Times(0)
207219
},
208220
wantErr: true,
@@ -235,6 +247,10 @@ func Test_CreatePort(t *testing.T) {
235247
expectedCreateOpts = portsbinding.CreateOptsExt{
236248
CreateOptsBuilder: expectedCreateOpts,
237249
}
250+
m.ListPort(ports.ListOpts{
251+
Name: "test-port",
252+
NetworkID: netID,
253+
}).Return(nil, nil)
238254
m.CreatePort(gomock.Any()).DoAndReturn(func(builder ports.CreateOptsBuilder) (*ports.Port, error) {
239255
gotCreateOpts := builder.(portsbinding.CreateOptsExt)
240256
g.Expect(gotCreateOpts).To(Equal(expectedCreateOpts), cmp.Diff(gotCreateOpts, expectedCreateOpts))
@@ -277,6 +293,10 @@ func Test_CreatePort(t *testing.T) {
277293
expectedCreateOpts = portsbinding.CreateOptsExt{
278294
CreateOptsBuilder: expectedCreateOpts,
279295
}
296+
m.ListPort(ports.ListOpts{
297+
Name: "test-port",
298+
NetworkID: netID,
299+
}).Return(nil, nil)
280300
m.CreatePort(gomock.Any()).DoAndReturn(func(builder ports.CreateOptsBuilder) (*ports.Port, error) {
281301
gotCreateOpts := builder.(portsbinding.CreateOptsExt)
282302
g.Expect(gotCreateOpts).To(Equal(expectedCreateOpts), cmp.Diff(gotCreateOpts, expectedCreateOpts))
@@ -303,6 +323,10 @@ func Test_CreatePort(t *testing.T) {
303323
CreateOptsBuilder: expectedCreateOpts,
304324
}
305325

326+
m.ListPort(ports.ListOpts{
327+
Name: "test-port",
328+
NetworkID: netID,
329+
}).Return(nil, nil)
306330
// Create the port
307331
m.CreatePort(gomock.Any()).DoAndReturn(func(builder ports.CreateOptsBuilder) (*ports.Port, error) {
308332
gotCreateOpts := builder.(portsbinding.CreateOptsExt)
@@ -349,7 +373,7 @@ func Test_CreatePort(t *testing.T) {
349373
s := Service{
350374
client: mockClient,
351375
}
352-
got, err := s.CreatePort(
376+
got, err := s.EnsurePort(
353377
eventObject,
354378
&tt.port,
355379
)

test/e2e/data/e2e_conf.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ intervals:
188188
default/wait-cluster: ["20m", "10s"]
189189
default/wait-control-plane: ["30m", "10s"]
190190
default/wait-worker-nodes: ["30m", "10s"]
191-
default/wait-delete-cluster: ["5m", "10s"]
191+
default/wait-delete-cluster: ["10m", "10s"]
192192
default/wait-alt-az: ["20m", "30s"]
193193
default/wait-machine-upgrade: ["30m", "10s"]
194194
default/wait-nodes-ready: ["15m", "10s"]

0 commit comments

Comments
 (0)