Skip to content

Commit 051f8ea

Browse files
committed
Iteration 2 after Matt's comments
1 parent f9f1bae commit 051f8ea

File tree

10 files changed

+108
-112
lines changed

10 files changed

+108
-112
lines changed

api/v1alpha5/conversion.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,8 @@ func Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(
463463
return err
464464
}
465465

466-
in.SecurityGroups = nil
466+
in.AppliedSecurityGroupIDs = nil
467+
in.MachineSecurityGroupIDs = nil
467468

468469
return nil
469470
}

api/v1alpha5/zz_generated.conversion.go

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

api/v1alpha6/conversion.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,8 @@ func Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(
689689
return err
690690
}
691691

692-
in.SecurityGroups = nil
692+
in.AppliedSecurityGroupIDs = nil
693+
in.MachineSecurityGroupIDs = nil
693694

694695
return nil
695696
}

api/v1alpha6/zz_generated.conversion.go

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

api/v1alpha7/openstackmachine_types.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,14 @@ type OpenStackMachineStatus struct {
107107
// +optional
108108
InstanceState *InstanceState `json:"instanceState,omitempty"`
109109

110-
// SecurityGroups is the list of security groups that were applied to the ports
111-
// attached to the instance.
110+
// AppliedSecurityGroupIDs is a list of the security group IDs applied to the instance.
112111
// +optional
113-
SecurityGroups []SecurityGroup `json:"securityGroups,omitempty"`
112+
AppliedSecurityGroupIDs []string `json:"appliedSecurityGroupIDs,omitempty"`
113+
114+
// MachineSecurityGroupIDs is a list of IDs of the security groups that have been
115+
// defined in the OpenStackMachine.Spec.SecurityGroups field.
116+
// +optional
117+
MachineSecurityGroupIDs []string `json:"machineSecurityGroupIDs,omitempty"`
114118

115119
FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"`
116120

api/v1alpha7/zz_generated.deepcopy.go

Lines changed: 9 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml

Lines changed: 13 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,6 +1529,12 @@ spec:
15291529
- type
15301530
type: object
15311531
type: array
1532+
appliedSecurityGroupIDs:
1533+
description: AppliedSecurityGroupIDs is a list of the security group
1534+
IDs applied to the instance.
1535+
items:
1536+
type: string
1537+
type: array
15321538
conditions:
15331539
description: Conditions provide observations of the operational state
15341540
of a Cluster API resource.
@@ -1598,64 +1604,16 @@ spec:
15981604
description: InstanceState is the state of the OpenStack instance
15991605
for this machine.
16001606
type: string
1607+
machineSecurityGroupIDs:
1608+
description: MachineSecurityGroupIDs is a list of IDs of the security
1609+
groups that have been defined in the OpenStackMachine.Spec.SecurityGroups
1610+
field.
1611+
items:
1612+
type: string
1613+
type: array
16011614
ready:
16021615
description: Ready is true when the provider resource is ready.
16031616
type: boolean
1604-
securityGroups:
1605-
description: SecurityGroups is the list of security groups that were
1606-
applied to the ports attached to the instance.
1607-
items:
1608-
description: SecurityGroup represents the basic information of the
1609-
associated OpenStack Neutron Security Group.
1610-
properties:
1611-
id:
1612-
type: string
1613-
name:
1614-
type: string
1615-
rules:
1616-
items:
1617-
description: SecurityGroupRule represent the basic information
1618-
of the associated OpenStack Security Group Role.
1619-
properties:
1620-
description:
1621-
type: string
1622-
direction:
1623-
type: string
1624-
etherType:
1625-
type: string
1626-
name:
1627-
type: string
1628-
portRangeMax:
1629-
type: integer
1630-
portRangeMin:
1631-
type: integer
1632-
protocol:
1633-
type: string
1634-
remoteGroupID:
1635-
type: string
1636-
remoteIPPrefix:
1637-
type: string
1638-
securityGroupID:
1639-
type: string
1640-
required:
1641-
- description
1642-
- direction
1643-
- etherType
1644-
- name
1645-
- portRangeMax
1646-
- portRangeMin
1647-
- protocol
1648-
- remoteGroupID
1649-
- remoteIPPrefix
1650-
- securityGroupID
1651-
type: object
1652-
type: array
1653-
required:
1654-
- id
1655-
- name
1656-
- rules
1657-
type: object
1658-
type: array
16591617
type: object
16601618
type: object
16611619
served: true

controllers/openstackmachine_controller.go

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,14 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
328328
return ctrl.Result{}, err
329329
}
330330

331+
if len(openStackMachine.Spec.SecurityGroups) != len(openStackMachine.Status.MachineSecurityGroupIDs) {
332+
machineSecurityGroups, err := networkingService.GetSecurityGroups(openStackMachine.Spec.SecurityGroups)
333+
if err != nil {
334+
return ctrl.Result{}, fmt.Errorf("get security groups %q: %w", openStackMachine.Spec.SecurityGroups, err)
335+
}
336+
openStackMachine.Status.MachineSecurityGroupIDs = machineSecurityGroups
337+
}
338+
331339
instanceStatus, err := r.getOrCreate(scope.Logger(), cluster, openStackCluster, machine, openStackMachine, computeService, userData)
332340
if err != nil {
333341
// Conditions set in getOrCreate
@@ -436,50 +444,46 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
436444
return ctrl.Result{}, nil
437445
}
438446

447+
func normalize(set []string) []string {
448+
seen := make(map[string]struct{}, len(set))
449+
normalized := make([]string, 0, len(set))
450+
for _, s := range set {
451+
if _, ok := seen[s]; !ok {
452+
seen[s] = struct{}{}
453+
normalized = append(normalized, s)
454+
}
455+
}
456+
return normalized
457+
}
458+
439459
func (r *OpenStackMachineReconciler) reconcileSecurityGroupsToInstance(logger logr.Logger, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, instanceStatus *compute.InstanceStatus, computeService *compute.Service, networkingService *networking.Service) error {
440460
logger.Info("Reconciling security groups to instance")
441461

442-
desiredSecurityGroups := []*infrav1.SecurityGroup{}
462+
desiredSecurityGroupIDs := []string{}
443463

444-
// These security groups are currently not managed by CAPO and provided by the user
445-
// Later we'll have an API to manage them.
446-
for _, sg := range openStackMachine.Spec.SecurityGroups {
447-
if sg.ID == "" {
448-
// lookup security group by name
449-
securityGroup, err := networkingService.GetSecurityGroupByName(sg.Name)
450-
if err != nil {
451-
return fmt.Errorf("get security group %q: %w", sg.Name, err)
452-
}
453-
sg.ID = securityGroup.ID
454-
}
455-
desiredSecurityGroups = append(desiredSecurityGroups, &infrav1.SecurityGroup{
456-
ID: sg.ID,
457-
})
458-
}
464+
desiredSecurityGroupIDs = append(desiredSecurityGroupIDs, openStackMachine.Status.MachineSecurityGroupIDs...)
459465

460-
if openStackCluster.Spec.ManagedSecurityGroups {
461-
if util.IsControlPlaneMachine(machine) && openStackCluster.Status.ControlPlaneSecurityGroup != nil {
462-
desiredSecurityGroups = append(desiredSecurityGroups, openStackCluster.Status.ControlPlaneSecurityGroup)
463-
} else if openStackCluster.Status.WorkerSecurityGroup != nil {
464-
desiredSecurityGroups = append(desiredSecurityGroups, openStackCluster.Status.WorkerSecurityGroup)
465-
}
466+
if util.IsControlPlaneMachine(machine) && openStackCluster.Status.ControlPlaneSecurityGroup != nil {
467+
desiredSecurityGroupIDs = append(desiredSecurityGroupIDs, openStackCluster.Status.ControlPlaneSecurityGroup.ID)
468+
} else if openStackCluster.Status.WorkerSecurityGroup != nil {
469+
desiredSecurityGroupIDs = append(desiredSecurityGroupIDs, openStackCluster.Status.WorkerSecurityGroup.ID)
466470
}
467471

468-
if len(desiredSecurityGroups) > 0 {
472+
desiredSecurityGroupIDs = normalize(desiredSecurityGroupIDs)
473+
appliedSecurityGroupIDs := normalize(openStackMachine.Status.AppliedSecurityGroupIDs)
474+
if !reflect.DeepEqual(desiredSecurityGroupIDs, appliedSecurityGroupIDs) {
469475
instanceID := instanceStatus.ID()
470-
desiredSecurityGroupsIDs := make([]string, len(desiredSecurityGroups))
471-
for i, sg := range desiredSecurityGroups {
472-
desiredSecurityGroupsIDs[i] = sg.ID
473-
}
474-
// Security Groups are attached to ports, not instances so we need to get the ports first
475476
attachedInterfaces, err := computeService.GetAttachedInterfaces(instanceID)
476477
if err != nil {
477478
return fmt.Errorf("get attached interfaces for instance %q: %w", instanceStatus.Name(), err)
478479
}
479-
err = networkingService.ReconcileSecurityGroupsToInstanceAttachedInterfaces(logger, openStackMachine, attachedInterfaces, desiredSecurityGroupsIDs)
480+
err = networkingService.ReconcileSecurityGroupsToInstanceAttachedInterfaces(logger, openStackMachine, attachedInterfaces, desiredSecurityGroupIDs)
480481
if err != nil {
481-
return fmt.Errorf("reconcile security groups %q to instance %q: %w", desiredSecurityGroupsIDs, instanceStatus.Name(), err)
482+
return fmt.Errorf("reconcile security groups %q to instance %q: %w", desiredSecurityGroupIDs, instanceStatus.Name(), err)
482483
}
484+
} else {
485+
logger.Info("No security groups to instance to reconcile")
486+
return nil
483487
}
484488

485489
logger.Info("Reconciled security groups to instance successfully")

controllers/openstackmachine_controller_test.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package controllers
1818

1919
import (
20+
"reflect"
2021
"testing"
2122

2223
"github.com/go-logr/logr"
@@ -171,7 +172,7 @@ func Test_reconcileSecurityGroupsToInstance(t *testing.T) {
171172
name string
172173
openStackMachine *infrav1.OpenStackMachine
173174
expectedError bool
174-
expectedSecurityGroups []infrav1.SecurityGroup
175+
expectedSecurityGroups []string
175176
}{
176177
{
177178
name: "NoSecurityGroups",
@@ -191,7 +192,40 @@ func Test_reconcileSecurityGroupsToInstance(t *testing.T) {
191192
} else {
192193
Expect(err).NotTo(HaveOccurred())
193194
}
194-
Expect(tt.openStackMachine.Status.SecurityGroups).To(Equal(tt.expectedSecurityGroups))
195+
Expect(tt.openStackMachine.Status.AppliedSecurityGroupIDs).To(Equal(tt.expectedSecurityGroups))
196+
})
197+
}
198+
}
199+
200+
func Test_normalize(t *testing.T) {
201+
tests := []struct {
202+
name string
203+
set []string
204+
expected []string
205+
}{
206+
{
207+
name: "EmptySet",
208+
set: []string{},
209+
expected: []string{},
210+
},
211+
{
212+
name: "NoDuplicates",
213+
set: []string{"a", "b", "c"},
214+
expected: []string{"a", "b", "c"},
215+
},
216+
{
217+
name: "WithDuplicates",
218+
set: []string{"a", "b", "a", "c", "b"},
219+
expected: []string{"a", "b", "c"},
220+
},
221+
}
222+
223+
for _, tt := range tests {
224+
t.Run(tt.name, func(t *testing.T) {
225+
got := normalize(tt.set)
226+
if !reflect.DeepEqual(got, tt.expected) {
227+
t.Errorf("normalize() = %v, want %v", got, tt.expected)
228+
}
195229
})
196230
}
197231
}

pkg/cloud/services/networking/securitygroups.go

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -425,15 +425,13 @@ func (s *Service) ReconcileSecurityGroupsToInstanceAttachedInterfaces(logger log
425425
if !contains(port.SecurityGroups, securityGroupID) {
426426
logger.Info("Port doesn't have desired security group", "portID", portID, "securityGroupID", securityGroupID)
427427
portUpdateNeeded = true
428-
break
429428
}
430429
}
431430
// check if port has security groups that are not desired
432431
for _, securityGroupID := range port.SecurityGroups {
433432
if !contains(desiredSecurityGroupIDs, securityGroupID) {
434433
logger.Info("Port has security group that is not desired", "portID", portID, "securityGroupID", securityGroupID)
435434
portUpdateNeeded = true
436-
break
437435
}
438436
}
439437

@@ -449,16 +447,7 @@ func (s *Service) ReconcileSecurityGroupsToInstanceAttachedInterfaces(logger log
449447
}
450448
}
451449

452-
appliedSecurityGroups := make([]infrav1.SecurityGroup, len(desiredSecurityGroupIDs))
453-
for i, securityGroupID := range desiredSecurityGroupIDs {
454-
securityGroup, err := s.client.GetSecGroup(securityGroupID)
455-
if err != nil {
456-
return fmt.Errorf("error getting security group %s: %v", securityGroupID, err)
457-
}
458-
appliedSecurityGroups[i] = *convertOSSecGroupToConfigSecGroup(*securityGroup)
459-
}
460-
logger.Info("Updating openStackMachine.Status.SecurityGroups", "securityGroups", appliedSecurityGroups)
461-
openStackMachine.Status.SecurityGroups = appliedSecurityGroups
450+
openStackMachine.Status.AppliedSecurityGroupIDs = desiredSecurityGroupIDs
462451

463452
return nil
464453
}

0 commit comments

Comments
 (0)