Skip to content

Commit 17c4091

Browse files
committed
Bastion is enabled by default if specified
Bastion.Enabled is a wart. Ideally it would not be required, but because of limitations in how we delete the bastion we require an intermediate 'disabled' step before removal. Ultimately we intend to remove this limitation. Eventually we would like to be able to ignore enabled entirely. e.g. To create a Bastion just specify it: ```yaml spec: bastion: spec: ... floatingIP: x.x.x.x ``` and to delete it just remove the bastion field. Right now with enabled defaulting to `false`, doing the above will not result in the creation of a bastion, because enabled must be explicitly set to true. Paving the way for the eventual deprecation of Bastion.Enabled, we change the default value of enabled to be true so the above does today what we eventually want it to do. This is also generally more intuitive: why would you include a bastion and a spec if you didn't want to create a bastion? Having to also set enabled to true is currently a trip hazard. Until we resolve the limitations of bastion deletion, though, we still need to be able to disable the bastion. For this case enabled can be explicitly set to false. In the future when we remove the requirement to disable the bastion before deletion the user can simply ignore Bastion.Enabled, which will continue to work but without the limitations.
1 parent 4e2150f commit 17c4091

19 files changed

+116
-54
lines changed

api/v1alpha5/zz_generated.conversion.go

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

api/v1alpha6/openstackcluster_conversion.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
416416

417417
optional.RestoreString(&(*previous).FloatingIP, &(*dst).FloatingIP)
418418
optional.RestoreString(&(*previous).AvailabilityZone, &(*dst).AvailabilityZone)
419+
optional.RestoreBool(&(*previous).Enabled, &(*dst).Enabled)
419420
}
420421

421422
func Convert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Bastion, s apiconversion.Scope) error {

api/v1alpha6/zz_generated.conversion.go

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

api/v1alpha7/openstackcluster_conversion.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
384384

385385
optional.RestoreString(&(*previous).FloatingIP, &(*dst).FloatingIP)
386386
optional.RestoreString(&(*previous).AvailabilityZone, &(*dst).AvailabilityZone)
387+
optional.RestoreBool(&(*previous).Enabled, &(*dst).Enabled)
387388
}
388389
}
389390

api/v1alpha7/zz_generated.conversion.go

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

api/v1beta1/types.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -719,12 +719,18 @@ var (
719719
)
720720

721721
// Bastion represents basic information about the bastion node. If you enable bastion, the spec has to be specified.
722-
// +kubebuilder:validation:XValidation:rule="!self.enabled || has(self.spec)",message="you need to specify the spec if bastion is enabled"
722+
// +kubebuilder:validation:XValidation:rule="!self.enabled || has(self.spec)",message="spec is required if bastion is enabled"
723723
type Bastion struct {
724-
// Enabled means that bastion is enabled. Defaults to false.
725-
// +kubebuilder:validation:Required
726-
// +kubebuilder:default:=false
727-
Enabled bool `json:"enabled"`
724+
// Enabled means that bastion is enabled. The bastion is enabled by
725+
// default if this field is not specified. Set this field to false to disable the
726+
// bastion.
727+
//
728+
// It is not currently possible to remove the bastion from the cluster
729+
// spec without first disabling it by setting this field to false and
730+
// waiting until the bastion has been deleted.
731+
// +kubebuilder:default:=true
732+
// +optional
733+
Enabled optional.Bool `json:"enabled,omitempty"`
728734

729735
// Spec for the bastion itself
730736
Spec *OpenStackMachineSpec `json:"spec,omitempty"`
@@ -741,6 +747,13 @@ type Bastion struct {
741747
FloatingIP optional.String `json:"floatingIP,omitempty"`
742748
}
743749

750+
func (b *Bastion) IsEnabled() bool {
751+
if b == nil {
752+
return false
753+
}
754+
return b.Enabled == nil || *b.Enabled
755+
}
756+
744757
type APIServerLoadBalancer struct {
745758
// Enabled defines whether a load balancer should be created. This value
746759
// defaults to true if an APIServerLoadBalancer is given.

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 5 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_openstackclusters.yaml

Lines changed: 10 additions & 5 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_openstackclustertemplates.yaml

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

controllers/openstackcluster_controller.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ func contains(arr []string, target string) bool {
219219

220220
func resolveBastionResources(scope *scope.WithLogger, clusterResourceName string, openStackCluster *infrav1.OpenStackCluster) (bool, error) {
221221
// Resolve and store resources for the bastion
222-
if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
222+
if openStackCluster.Spec.Bastion.IsEnabled() {
223223
if openStackCluster.Status.Bastion == nil {
224224
openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
225225
}
@@ -406,7 +406,7 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS
406406
}
407407

408408
// No Bastion defined
409-
if openStackCluster.Spec.Bastion == nil || !openStackCluster.Spec.Bastion.Enabled {
409+
if !openStackCluster.Spec.Bastion.IsEnabled() {
410410
// Delete any existing bastion
411411
if openStackCluster.Status.Bastion != nil {
412412
if err := deleteBastion(scope, cluster, openStackCluster); err != nil {
@@ -440,6 +440,8 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS
440440
return nil, fmt.Errorf("failed computing bastion hash from instance spec: %w", err)
441441
}
442442
if bastionHashHasChanged(bastionHash, openStackCluster.ObjectMeta.Annotations) {
443+
scope.Logger().Info("Bastion instance spec has changed, deleting existing bastion")
444+
443445
if err := deleteBastion(scope, cluster, openStackCluster); err != nil {
444446
return nil, err
445447
}
@@ -544,7 +546,7 @@ func bastionAddFloatingIP(openStackCluster *infrav1.OpenStackCluster, clusterRes
544546
func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *clusterv1.Cluster) (*compute.InstanceSpec, error) {
545547
bastion := openStackCluster.Spec.Bastion
546548
if bastion == nil {
547-
return nil, fmt.Errorf("bastion spec is nil")
549+
bastion = &infrav1.Bastion{}
548550
}
549551
if bastion.Spec == nil {
550552
// For the case when Bastion is deleted but we don't have spec, let's use an empty one.

controllers/openstackcluster_controller_test.go

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,10 @@ var _ = Describe("OpenStackCluster controller", func() {
196196
Expect(err).To(MatchError(clientCreateErr))
197197
Expect(result).To(Equal(reconcile.Result{}))
198198
})
199-
It("should be able to reconcile when bastion is disabled and does not exist", func() {
200-
testCluster.SetName("no-bastion")
199+
It("should be able to reconcile when bastion is explicitly disabled and does not exist", func() {
200+
testCluster.SetName("no-bastion-explicit")
201201
testCluster.Spec = infrav1.OpenStackClusterSpec{
202-
Bastion: &infrav1.Bastion{},
202+
Bastion: &infrav1.Bastion{Enabled: pointer.Bool(false)},
203203
}
204204
err := k8sClient.Create(ctx, testCluster)
205205
Expect(err).To(BeNil())
@@ -228,7 +228,7 @@ var _ = Describe("OpenStackCluster controller", func() {
228228
testCluster.SetName("adopt-existing-bastion")
229229
testCluster.Spec = infrav1.OpenStackClusterSpec{
230230
Bastion: &infrav1.Bastion{
231-
Enabled: true,
231+
Enabled: pointer.Bool(true),
232232
Spec: &bastionSpec,
233233
},
234234
}
@@ -311,7 +311,7 @@ var _ = Describe("OpenStackCluster controller", func() {
311311
testCluster.SetName("requeue-bastion")
312312
testCluster.Spec = infrav1.OpenStackClusterSpec{
313313
Bastion: &infrav1.Bastion{
314-
Enabled: true,
314+
Enabled: pointer.Bool(true),
315315
Spec: &bastionSpec,
316316
},
317317
}
@@ -393,7 +393,7 @@ var _ = Describe("OpenStackCluster controller", func() {
393393
testCluster.SetName("requeue-bastion")
394394
testCluster.Spec = infrav1.OpenStackClusterSpec{
395395
Bastion: &infrav1.Bastion{
396-
Enabled: true,
396+
Enabled: pointer.Bool(true),
397397
Spec: &bastionSpec,
398398
},
399399
}
@@ -467,9 +467,7 @@ var _ = Describe("OpenStackCluster controller", func() {
467467
})
468468
It("should delete an existing bastion even if its uuid is not stored in status", func() {
469469
testCluster.SetName("delete-existing-bastion")
470-
testCluster.Spec = infrav1.OpenStackClusterSpec{
471-
Bastion: &infrav1.Bastion{},
472-
}
470+
testCluster.Spec = infrav1.OpenStackClusterSpec{}
473471
err := k8sClient.Create(ctx, testCluster)
474472
Expect(err).To(BeNil())
475473
err = k8sClient.Create(ctx, capiCluster)
@@ -516,7 +514,7 @@ var _ = Describe("OpenStackCluster controller", func() {
516514
testCluster.SetName("subnet-filtering")
517515
testCluster.Spec = infrav1.OpenStackClusterSpec{
518516
Bastion: &infrav1.Bastion{
519-
Enabled: true,
517+
Enabled: pointer.Bool(true),
520518
Spec: &bastionSpec,
521519
},
522520
DisableAPIServerFloatingIP: pointer.Bool(true),
@@ -586,7 +584,7 @@ var _ = Describe("OpenStackCluster controller", func() {
586584
testCluster.SetName("subnet-filtering")
587585
testCluster.Spec = infrav1.OpenStackClusterSpec{
588586
Bastion: &infrav1.Bastion{
589-
Enabled: true,
587+
Enabled: pointer.Bool(true),
590588
Spec: &bastionSpec,
591589
},
592590
DisableAPIServerFloatingIP: pointer.Bool(true),

docs/book/src/api/v1beta1/api.md

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

docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
- [Change to image](#change-to-image)
1515
- [Removal of imageUUID](#removal-of-imageuuid)
1616
- [Changes to ports](#changes-to-ports)
17-
- [Additon of floatingIPPoolRef](#additon-of-floatingippoolref)
17+
- [Addition of floatingIPPoolRef](#addition-of-floatingippoolref)
1818
- [`OpenStackCluster`](#openstackcluster)
1919
- [Removal of cloudName](#removal-of-cloudname-1)
2020
- [identityRef is now required](#identityref-is-now-required)
@@ -367,6 +367,8 @@ spec:
367367

368368
#### Changes to bastion
369369

370+
In v1beta1 the Bastion is enabled by default if a bastion is specified in `OpenStackCluster.spec.bastion` but `enabled` is not included. However, it is still required to set `enabled` explicitly to `false` before removing the bastion. We intend to remove this requirement in the future at which point the `enabled` field will be redundant.
371+
370372
In v1beta1, `OpenStackCluster.spec.bastion.instance` becomes `OpenStackCluster.spec.bastion.spec`.
371373

372374
```yaml

pkg/cloud/services/networking/securitygroups.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func (s *Service) ReconcileSecurityGroups(openStackCluster *infrav1.OpenStackClu
4747
return nil
4848
}
4949

50-
bastionEnabled := openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled
50+
bastionEnabled := openStackCluster.Spec.Bastion.IsEnabled()
5151

5252
secControlPlaneGroupName := getSecControlPlaneGroupName(clusterResourceName)
5353
secWorkerGroupName := getSecWorkerGroupName(clusterResourceName)
@@ -212,7 +212,7 @@ func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCl
212212

213213
desiredSecGroupsBySuffix := make(map[string]securityGroupSpec)
214214

215-
if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
215+
if openStackCluster.Spec.Bastion.IsEnabled() {
216216
controlPlaneRules = append(controlPlaneRules, getSGControlPlaneSSH(secBastionGroupID)...)
217217
workerRules = append(workerRules, getSGWorkerSSH(secBastionGroupID)...)
218218

@@ -357,7 +357,7 @@ func (s *Service) DeleteSecurityGroups(openStackCluster *infrav1.OpenStackCluste
357357
getSecWorkerGroupName(clusterResourceName),
358358
}
359359

360-
if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
360+
if openStackCluster.Spec.Bastion.IsEnabled() {
361361
secGroupNames = append(secGroupNames, getSecBastionGroupName(clusterResourceName))
362362
}
363363

pkg/cloud/services/networking/securitygroups_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ func TestService_ReconcileSecurityGroups(t *testing.T) {
533533
name: "Default control plane, worker, and bastion security groups",
534534
openStackClusterSpec: infrav1.OpenStackClusterSpec{
535535
Bastion: &infrav1.Bastion{
536-
Enabled: true,
536+
Enabled: pointer.Bool(true),
537537
},
538538
ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{},
539539
},

pkg/webhooks/openstackcluster_webhook.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, new
110110

111111
// Allow to remove the bastion spec only if it was disabled before.
112112
if newObj.Spec.Bastion == nil {
113-
if oldObj.Spec.Bastion != nil && oldObj.Spec.Bastion.Enabled {
113+
if oldObj.Spec.Bastion.IsEnabled() {
114114
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "bastion"), "cannot be removed before disabling it"))
115115
}
116116
}

0 commit comments

Comments
 (0)