Skip to content

Commit 1bc5fd9

Browse files
committed
Reconcile SecurityGroups <-> Instances separately
Originally, we were adding the SecurityGroups to the instanceSpec. Now, the openstackmachine controller will first create the instances without security groups. Then we have a loop that will reconcile the desired security groups that we want to apply in the cluster[1] with the ones that are added to the instance's ports. [1] for now, we have 2 sets of rules: the one that can be added to `OpenStackMachine.Spec.SecurityGroups` and the one managed by `OpenStackCluster.Spec.ManagedSecurityGroups`.
1 parent 85aed76 commit 1bc5fd9

12 files changed

+273
-106
lines changed

api/v1alpha5/conversion.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,3 +456,14 @@ func Convert_v1alpha7_Bastion_To_v1alpha5_Bastion(in *infrav1.Bastion, out *Bast
456456
in.FloatingIP = out.Instance.FloatingIP
457457
return nil
458458
}
459+
460+
func Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
461+
err := autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in, out, s)
462+
if err != nil {
463+
return err
464+
}
465+
466+
in.SecurityGroups = nil
467+
468+
return nil
469+
}

api/v1alpha5/zz_generated.conversion.go

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

api/v1alpha6/conversion.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,3 +682,14 @@ func Convert_v1alpha7_Bastion_To_v1alpha6_Bastion(in *infrav1.Bastion, out *Bast
682682
in.FloatingIP = out.Instance.FloatingIP
683683
return nil
684684
}
685+
686+
func Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s apiconversion.Scope) error {
687+
err := autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in, out, s)
688+
if err != nil {
689+
return err
690+
}
691+
692+
in.SecurityGroups = nil
693+
694+
return nil
695+
}

api/v1alpha6/zz_generated.conversion.go

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

api/v1alpha7/conditions_consts.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ const (
4242
InstanceDeleteFailedReason = "InstanceDeleteFailed"
4343
// OpenstackErrorReason used when there is an error communicating with OpenStack.
4444
OpenStackErrorReason = "OpenStackError"
45+
// SecurityGroupAppliedFailedCondition used when the security group could not be applied.
46+
SecurityGroupApplyFailedReason = "SecurityGroupAppliedFailed"
4547
)
4648

4749
const (

api/v1alpha7/openstackmachine_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ 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.
112+
// +optional
113+
SecurityGroups []SecurityGroup `json:"securityGroups,omitempty"`
114+
110115
FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"`
111116

112117
// FailureMessage will be set in the event that there is a terminal problem

api/v1alpha7/zz_generated.deepcopy.go

Lines changed: 7 additions & 0 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: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,61 @@ spec:
16011601
ready:
16021602
description: Ready is true when the provider resource is ready.
16031603
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
16041659
type: object
16051660
type: object
16061661
served: true

controllers/openstackmachine_controller.go

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,12 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
334334
return ctrl.Result{}, err
335335
}
336336

337+
err = r.reconcileSecurityGroupsToInstance(openStackCluster, machine, openStackMachine, instanceStatus, computeService, networkingService)
338+
if err != nil {
339+
conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.SecurityGroupApplyFailedReason, clusterv1.ConditionSeverityError, "Applying security groups failed: %v", err)
340+
return ctrl.Result{}, fmt.Errorf("add security groups to instance: %w", err)
341+
}
342+
337343
// TODO(sbueringer) From CAPA: TODO(ncdc): move this validation logic into a validating webhook (for us: create validation logic in webhook)
338344

339345
openStackMachine.Spec.ProviderID = pointer.String(fmt.Sprintf("openstack:///%s", instanceStatus.ID()))
@@ -430,6 +436,53 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
430436
return ctrl.Result{}, nil
431437
}
432438

439+
func (r *OpenStackMachineReconciler) reconcileSecurityGroupsToInstance(openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, instanceStatus *compute.InstanceStatus, computeService *compute.Service, networkingService *networking.Service) error {
440+
desiredSecurityGroups := []*infrav1.SecurityGroup{}
441+
442+
// These security groups are currently not managed by CAPO and provided by the user
443+
// Later we'll have an API to manage them.
444+
for _, sg := range openStackMachine.Spec.SecurityGroups {
445+
if sg.ID == "" {
446+
// lookup security group by name
447+
securityGroup, err := networkingService.GetSecurityGroupByName(sg.Name)
448+
if err != nil {
449+
return fmt.Errorf("get security group %q: %w", sg.Name, err)
450+
}
451+
sg.ID = securityGroup.ID
452+
}
453+
desiredSecurityGroups = append(desiredSecurityGroups, &infrav1.SecurityGroup{
454+
ID: sg.ID,
455+
})
456+
}
457+
458+
if openStackCluster.Spec.ManagedSecurityGroups {
459+
if util.IsControlPlaneMachine(machine) && openStackCluster.Status.ControlPlaneSecurityGroup != nil {
460+
desiredSecurityGroups = append(desiredSecurityGroups, openStackCluster.Status.ControlPlaneSecurityGroup)
461+
} else if openStackCluster.Status.WorkerSecurityGroup != nil {
462+
desiredSecurityGroups = append(desiredSecurityGroups, openStackCluster.Status.WorkerSecurityGroup)
463+
}
464+
}
465+
466+
if len(desiredSecurityGroups) > 0 {
467+
instanceID := instanceStatus.ID()
468+
desiredSecurityGroupsIDs := make([]string, len(desiredSecurityGroups))
469+
for i, sg := range desiredSecurityGroups {
470+
desiredSecurityGroupsIDs[i] = sg.ID
471+
}
472+
// Security Groups are attached to ports, not instances so we need to get the ports first
473+
attachedInterfaces, err := computeService.GetAttachedInterfaces(instanceID)
474+
if err != nil {
475+
return fmt.Errorf("get attached interfaces for instance %q: %w", instanceStatus.Name(), err)
476+
}
477+
err = networkingService.ReconcileSecurityGroupsToInstanceAttachedInterfaces(openStackMachine, attachedInterfaces, desiredSecurityGroupsIDs)
478+
if err != nil {
479+
return fmt.Errorf("reconcile security groups %q to instance %q: %w", desiredSecurityGroupsIDs, instanceStatus.Name(), err)
480+
}
481+
}
482+
483+
return nil
484+
}
485+
433486
func (r *OpenStackMachineReconciler) getOrCreate(logger logr.Logger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, computeService *compute.Service, userData string) (*compute.InstanceStatus, error) {
434487
instanceStatus, err := computeService.GetInstanceStatusByName(openStackMachine, openStackMachine.Name)
435488
if err != nil {
@@ -496,20 +549,6 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *
496549

497550
instanceSpec.Tags = machineTags
498551

499-
instanceSpec.SecurityGroups = openStackMachine.Spec.SecurityGroups
500-
if openStackCluster.Spec.ManagedSecurityGroups {
501-
var managedSecurityGroup string
502-
if util.IsControlPlaneMachine(machine) && openStackCluster.Status.ControlPlaneSecurityGroup != nil {
503-
managedSecurityGroup = openStackCluster.Status.ControlPlaneSecurityGroup.ID
504-
} else if openStackCluster.Status.WorkerSecurityGroup != nil {
505-
managedSecurityGroup = openStackCluster.Status.WorkerSecurityGroup.ID
506-
}
507-
508-
instanceSpec.SecurityGroups = append(instanceSpec.SecurityGroups, infrav1.SecurityGroupFilter{
509-
ID: managedSecurityGroup,
510-
})
511-
}
512-
513552
instanceSpec.Ports = openStackMachine.Spec.Ports
514553

515554
return &instanceSpec

0 commit comments

Comments
 (0)