Skip to content

Commit 8ca470a

Browse files
authored
Merge pull request #1866 from shiftstack/issue_1855
🐛 Prevent the bastion to be removed before it's been disabled
2 parents 622defd + 20f2a3c commit 8ca470a

7 files changed

+82
-10
lines changed

api/v1alpha8/openstackcluster_types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ type OpenStackClusterSpec struct {
155155
// Bastion is the OpenStack instance to login the nodes
156156
//
157157
// As a rolling update is not ideal during a bastion host session, we
158-
// prevent changes to a running bastion configuration. Set `enabled: false` to
159-
// make changes.
158+
// prevent changes to a running bastion configuration. To make changes, it's required
159+
// to first set `enabled: false` which will remove the bastion and then changes can be made.
160160
//+optional
161161
Bastion *Bastion `json:"bastion,omitempty"`
162162

api/v1alpha8/openstackcluster_webhook.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,13 @@ func (r *OpenStackCluster) ValidateUpdate(oldRaw runtime.Object) (admission.Warn
116116
r.Spec.APIServerPort = 0
117117
}
118118

119+
// Allow to remove the bastion spec only if it was disabled before.
120+
if r.Spec.Bastion == nil {
121+
if old.Spec.Bastion != nil && old.Spec.Bastion.Enabled {
122+
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "bastion"), "cannot be removed before disabling it"))
123+
}
124+
}
125+
119126
// Allow changes to the bastion spec.
120127
old.Spec.Bastion = &Bastion{}
121128
r.Spec.Bastion = &Bastion{}

api/v1alpha8/openstackcluster_webhook_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,42 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
358358
},
359359
wantErr: true,
360360
},
361+
{
362+
name: "Removing OpenStackCluster.Spec.Bastion when it is enabled is not allowed",
363+
oldTemplate: &OpenStackCluster{
364+
Spec: OpenStackClusterSpec{
365+
Bastion: &Bastion{
366+
Enabled: true,
367+
Instance: OpenStackMachineSpec{
368+
Flavor: "m1.small",
369+
Image: ImageFilter{Name: "ubuntu"},
370+
},
371+
},
372+
},
373+
},
374+
newTemplate: &OpenStackCluster{
375+
Spec: OpenStackClusterSpec{},
376+
},
377+
wantErr: true,
378+
},
379+
{
380+
name: "Removing OpenStackCluster.Spec.Bastion when it is disabled is allowed",
381+
oldTemplate: &OpenStackCluster{
382+
Spec: OpenStackClusterSpec{
383+
Bastion: &Bastion{
384+
Enabled: false,
385+
Instance: OpenStackMachineSpec{
386+
Flavor: "m1.small",
387+
Image: ImageFilter{Name: "ubuntu"},
388+
},
389+
},
390+
},
391+
},
392+
newTemplate: &OpenStackCluster{
393+
Spec: OpenStackClusterSpec{},
394+
},
395+
wantErr: false,
396+
},
361397
}
362398
for _, tt := range tests {
363399
t.Run(tt.name, func(t *testing.T) {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4899,8 +4899,8 @@ spec:
48994899
49004900
49014901
As a rolling update is not ideal during a bastion host session, we
4902-
prevent changes to a running bastion configuration. Set `enabled: false` to
4903-
make changes.
4902+
prevent changes to a running bastion configuration. To make changes, it's required
4903+
to first set `enabled: false` which will remove the bastion and then changes can be made.
49044904
properties:
49054905
availabilityZone:
49064906
type: string

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,8 +2324,8 @@ spec:
23242324
23252325
23262326
As a rolling update is not ideal during a bastion host session, we
2327-
prevent changes to a running bastion configuration. Set `enabled: false` to
2328-
make changes.
2327+
prevent changes to a running bastion configuration. To make changes, it's required
2328+
to first set `enabled: false` which will remove the bastion and then changes can be made.
23292329
properties:
23302330
availabilityZone:
23312331
type: string

controllers/openstackcluster_controller.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,10 @@ func deleteBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackClust
263263
}
264264
}
265265

266-
instanceSpec := bastionToInstanceSpec(openStackCluster, cluster.Name)
266+
instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster.Name)
267+
if err != nil {
268+
return err
269+
}
267270
if err = computeService.DeleteInstance(openStackCluster, openStackCluster, instanceStatus, instanceSpec); err != nil {
268271
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete bastion: %w", err))
269272
return fmt.Errorf("failed to delete bastion: %w", err)
@@ -346,7 +349,10 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
346349
return reconcile.Result{}, err
347350
}
348351

349-
instanceSpec := bastionToInstanceSpec(openStackCluster, cluster.Name)
352+
instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster.Name)
353+
if err != nil {
354+
return reconcile.Result{}, err
355+
}
350356
bastionHash, err := compute.HashInstanceSpec(instanceSpec)
351357
if err != nil {
352358
return reconcile.Result{}, fmt.Errorf("failed computing bastion hash from instance spec: %w", err)
@@ -437,7 +443,15 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
437443
return ctrl.Result{}, nil
438444
}
439445

440-
func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterName string) *compute.InstanceSpec {
446+
func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterName string) (*compute.InstanceSpec, error) {
447+
if openStackCluster.Spec.Bastion == nil {
448+
return nil, fmt.Errorf("bastion spec is nil")
449+
}
450+
451+
if openStackCluster.Status.Bastion == nil {
452+
return nil, fmt.Errorf("bastion status is nil")
453+
}
454+
441455
instanceSpec := &compute.InstanceSpec{
442456
Name: bastionName(clusterName),
443457
Flavor: openStackCluster.Spec.Bastion.Instance.Flavor,
@@ -458,7 +472,7 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterNa
458472

459473
instanceSpec.Ports = openStackCluster.Spec.Bastion.Instance.Ports
460474

461-
return instanceSpec
475+
return instanceSpec, nil
462476
}
463477

464478
func bastionName(clusterName string) string {

docs/book/src/clusteropenstack/configuration.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
- [Custom pod network CIDR](#custom-pod-network-cidr)
3636
- [Accessing nodes through the bastion host via SSH](#accessing-nodes-through-the-bastion-host-via-ssh)
3737
- [Enabling the bastion host](#enabling-the-bastion-host)
38+
- [Making changes to the bastion host](#making-changes-to-the-bastion-host)
39+
- [Disabling the bastion](#disabling-the-bastion)
3840
- [Obtain floating IP address of the bastion node](#obtain-floating-ip-address-of-the-bastion-node)
3941

4042
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -654,6 +656,19 @@ spec:
654656

655657
If `managedSecurityGroups: true`, security group rule opening 22/tcp is added to security groups for bastion, controller, and worker nodes respectively. Otherwise, you have to add `securityGroups` to the `bastion` in `OpenStackCluster` spec and `OpenStackMachineTemplate` spec template respectively.
656658

659+
### Making changes to the bastion host
660+
661+
Changes can be made to the bastion instance, like for example changing the flavor.
662+
First, you have to disable the bastion host by setting `enabled: false` in the `OpenStackCluster.Spec.Bastion` field.
663+
The bastion will be deleted, you can check the status of the bastion host by running `kubectl get openstackcluster` and looking at the `Bastion` field in status.
664+
Once it's gone, you can re-enable the bastion host by setting `enabled: true` and then making changes to the bastion instance spec by modifying the `OpenStackCluster.Spec.Bastion.Instance` field.
665+
The bastion host will be re-created with the new instance spec.
666+
667+
### Disabling the bastion
668+
669+
To disable the bastion host, set `enabled: false` in the `OpenStackCluster.Spec.Bastion` field. The bastion host will be deleted, you can check the status of the bastion host by running `kubectl get openstackcluster` and looking at the `Bastion` field in status.
670+
Once it's gone, you can now remove the `OpenStackCluster.Spec.Bastion` field from the `OpenStackCluster` spec.
671+
657672
### Obtain floating IP address of the bastion node
658673

659674
Once the workload cluster is up and running after being configured for an SSH bastion host, you can use the kubectl get openstackcluster command to look up the floating IP address of the bastion host (make sure the kubectl context is set to the management cluster). The output will look something like this:

0 commit comments

Comments
 (0)