Skip to content

Commit f9f1bae

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 f9f1bae

12 files changed

+281
-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: 56 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(scope.Logger(), 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,56 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
430436
return ctrl.Result{}, nil
431437
}
432438

439+
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 {
440+
logger.Info("Reconciling security groups to instance")
441+
442+
desiredSecurityGroups := []*infrav1.SecurityGroup{}
443+
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+
}
459+
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+
}
467+
468+
if len(desiredSecurityGroups) > 0 {
469+
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
475+
attachedInterfaces, err := computeService.GetAttachedInterfaces(instanceID)
476+
if err != nil {
477+
return fmt.Errorf("get attached interfaces for instance %q: %w", instanceStatus.Name(), err)
478+
}
479+
err = networkingService.ReconcileSecurityGroupsToInstanceAttachedInterfaces(logger, openStackMachine, attachedInterfaces, desiredSecurityGroupsIDs)
480+
if err != nil {
481+
return fmt.Errorf("reconcile security groups %q to instance %q: %w", desiredSecurityGroupsIDs, instanceStatus.Name(), err)
482+
}
483+
}
484+
485+
logger.Info("Reconciled security groups to instance successfully")
486+
return nil
487+
}
488+
433489
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) {
434490
instanceStatus, err := computeService.GetInstanceStatusByName(openStackMachine, openStackMachine.Name)
435491
if err != nil {
@@ -496,20 +552,6 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *
496552

497553
instanceSpec.Tags = machineTags
498554

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-
513555
instanceSpec.Ports = openStackMachine.Spec.Ports
514556

515557
return &instanceSpec

0 commit comments

Comments
 (0)