diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go index 2c5a688927..7ef2f85215 100644 --- a/api/v1alpha5/zz_generated.conversion.go +++ b/api/v1alpha5/zz_generated.conversion.go @@ -486,7 +486,9 @@ func Convert_v1beta1_AddressPair_To_v1alpha5_AddressPair(in *v1beta1.AddressPair } func autoConvert_v1alpha5_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error { - out.Enabled = in.Enabled + if err := optional.Convert_bool_To_optional_Bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } // WARNING: in.Instance requires manual conversion: does not exist in peer-type if err := optional.Convert_string_To_optional_String(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { return err @@ -495,7 +497,9 @@ func autoConvert_v1alpha5_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.B } func autoConvert_v1beta1_Bastion_To_v1alpha5_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error { - out.Enabled = in.Enabled + if err := optional.Convert_optional_Bool_To_bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } // WARNING: in.Spec requires manual conversion: does not exist in peer-type if err := optional.Convert_optional_String_To_string(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { return err diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go index 66fd5896bb..0cc60afb18 100644 --- a/api/v1alpha6/openstackcluster_conversion.go +++ b/api/v1alpha6/openstackcluster_conversion.go @@ -416,6 +416,7 @@ func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) { optional.RestoreString(&(*previous).FloatingIP, &(*dst).FloatingIP) optional.RestoreString(&(*previous).AvailabilityZone, &(*dst).AvailabilityZone) + optional.RestoreBool(&(*previous).Enabled, &(*dst).Enabled) } func Convert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Bastion, s apiconversion.Scope) error { diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go index 8e33e36df6..f1ad2538c2 100644 --- a/api/v1alpha6/zz_generated.conversion.go +++ b/api/v1alpha6/zz_generated.conversion.go @@ -510,7 +510,9 @@ func Convert_v1beta1_AddressPair_To_v1alpha6_AddressPair(in *v1beta1.AddressPair } func autoConvert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error { - out.Enabled = in.Enabled + if err := optional.Convert_bool_To_optional_Bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } // WARNING: in.Instance requires manual conversion: does not exist in peer-type if err := optional.Convert_string_To_optional_String(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { return err @@ -519,7 +521,9 @@ func autoConvert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.B } func autoConvert_v1beta1_Bastion_To_v1alpha6_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error { - out.Enabled = in.Enabled + if err := optional.Convert_optional_Bool_To_bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } // WARNING: in.Spec requires manual conversion: does not exist in peer-type if err := optional.Convert_optional_String_To_string(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { return err diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go index 4f06e21cc4..df703c5eb7 100644 --- a/api/v1alpha7/openstackcluster_conversion.go +++ b/api/v1alpha7/openstackcluster_conversion.go @@ -384,6 +384,7 @@ func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) { optional.RestoreString(&(*previous).FloatingIP, &(*dst).FloatingIP) optional.RestoreString(&(*previous).AvailabilityZone, &(*dst).AvailabilityZone) + optional.RestoreBool(&(*previous).Enabled, &(*dst).Enabled) } } diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go index c202a6787b..91d95656f4 100644 --- a/api/v1alpha7/zz_generated.conversion.go +++ b/api/v1alpha7/zz_generated.conversion.go @@ -573,7 +573,9 @@ func Convert_v1beta1_AddressPair_To_v1alpha7_AddressPair(in *v1beta1.AddressPair } func autoConvert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error { - out.Enabled = in.Enabled + if err := optional.Convert_bool_To_optional_Bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } // WARNING: in.Instance requires manual conversion: does not exist in peer-type if err := optional.Convert_string_To_optional_String(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { return err @@ -582,7 +584,9 @@ func autoConvert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.B } func autoConvert_v1beta1_Bastion_To_v1alpha7_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error { - out.Enabled = in.Enabled + if err := optional.Convert_optional_Bool_To_bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } // WARNING: in.Spec requires manual conversion: does not exist in peer-type if err := optional.Convert_optional_String_To_string(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { return err diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go index 492546e755..bfdef09c6b 100644 --- a/api/v1beta1/types.go +++ b/api/v1beta1/types.go @@ -719,12 +719,18 @@ var ( ) // Bastion represents basic information about the bastion node. If you enable bastion, the spec has to be specified. -// +kubebuilder:validation:XValidation:rule="!self.enabled || has(self.spec)",message="you need to specify the spec if bastion is enabled" +// +kubebuilder:validation:XValidation:rule="!self.enabled || has(self.spec)",message="spec is required if bastion is enabled" type Bastion struct { - // Enabled means that bastion is enabled. Defaults to false. - // +kubebuilder:validation:Required - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` + // Enabled means that bastion is enabled. The bastion is enabled by + // default if this field is not specified. Set this field to false to disable the + // bastion. + // + // It is not currently possible to remove the bastion from the cluster + // spec without first disabling it by setting this field to false and + // waiting until the bastion has been deleted. + // +kubebuilder:default:=true + // +optional + Enabled optional.Bool `json:"enabled,omitempty"` // Spec for the bastion itself Spec *OpenStackMachineSpec `json:"spec,omitempty"` @@ -741,6 +747,13 @@ type Bastion struct { FloatingIP optional.String `json:"floatingIP,omitempty"` } +func (b *Bastion) IsEnabled() bool { + if b == nil { + return false + } + return b.Enabled == nil || *b.Enabled +} + type APIServerLoadBalancer struct { // Enabled defines whether a load balancer should be created. This value // defaults to true if an APIServerLoadBalancer is given. diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 088e9c46f2..69d71929a1 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -116,6 +116,11 @@ func (in *AllocationPool) DeepCopy() *AllocationPool { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Bastion) DeepCopyInto(out *Bastion) { *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } if in.Spec != nil { in, out := &in.Spec, &out.Spec *out = new(OpenStackMachineSpec) diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml index 5056e60154..acdaa6eae7 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml @@ -4921,9 +4921,16 @@ spec: be used to create the Bastion Spec. type: string enabled: - default: false - description: Enabled means that bastion is enabled. Defaults to - false. + default: true + description: |- + Enabled means that bastion is enabled. The bastion is enabled by + default if this field is not specified. Set this field to false to disable the + bastion. + + + It is not currently possible to remove the bastion from the cluster + spec without first disabling it by setting this field to false and + waiting until the bastion has been deleted. type: boolean floatingIP: description: |- @@ -5639,11 +5646,9 @@ spec: - flavor - image type: object - required: - - enabled type: object x-kubernetes-validations: - - message: you need to specify the spec if bastion is enabled + - message: spec is required if bastion is enabled rule: '!self.enabled || has(self.spec)' controlPlaneAvailabilityZones: description: |- diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml index 5f25ff93c1..f01e35e574 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml @@ -2345,9 +2345,16 @@ spec: will be used to create the Bastion Spec. type: string enabled: - default: false - description: Enabled means that bastion is enabled. Defaults - to false. + default: true + description: |- + Enabled means that bastion is enabled. The bastion is enabled by + default if this field is not specified. Set this field to false to disable the + bastion. + + + It is not currently possible to remove the bastion from the cluster + spec without first disabling it by setting this field to false and + waiting until the bastion has been deleted. type: boolean floatingIP: description: |- @@ -3076,11 +3083,9 @@ spec: - flavor - image type: object - required: - - enabled type: object x-kubernetes-validations: - - message: you need to specify the spec if bastion is enabled + - message: spec is required if bastion is enabled rule: '!self.enabled || has(self.spec)' controlPlaneAvailabilityZones: description: |- diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go index c9283f11b7..3823b6ec3a 100644 --- a/controllers/openstackcluster_controller.go +++ b/controllers/openstackcluster_controller.go @@ -219,7 +219,7 @@ func contains(arr []string, target string) bool { func resolveBastionResources(scope *scope.WithLogger, clusterResourceName string, openStackCluster *infrav1.OpenStackCluster) (bool, error) { // Resolve and store resources for the bastion - if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled { + if openStackCluster.Spec.Bastion.IsEnabled() { if openStackCluster.Status.Bastion == nil { openStackCluster.Status.Bastion = &infrav1.BastionStatus{} } @@ -406,7 +406,7 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS } // No Bastion defined - if openStackCluster.Spec.Bastion == nil || !openStackCluster.Spec.Bastion.Enabled { + if !openStackCluster.Spec.Bastion.IsEnabled() { // Delete any existing bastion if openStackCluster.Status.Bastion != nil { if err := deleteBastion(scope, cluster, openStackCluster); err != nil { @@ -440,6 +440,8 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS return nil, fmt.Errorf("failed computing bastion hash from instance spec: %w", err) } if bastionHashHasChanged(bastionHash, openStackCluster.ObjectMeta.Annotations) { + scope.Logger().Info("Bastion instance spec has changed, deleting existing bastion") + if err := deleteBastion(scope, cluster, openStackCluster); err != nil { return nil, err } @@ -544,7 +546,7 @@ func bastionAddFloatingIP(openStackCluster *infrav1.OpenStackCluster, clusterRes func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *clusterv1.Cluster) (*compute.InstanceSpec, error) { bastion := openStackCluster.Spec.Bastion if bastion == nil { - return nil, fmt.Errorf("bastion spec is nil") + bastion = &infrav1.Bastion{} } if bastion.Spec == nil { // For the case when Bastion is deleted but we don't have spec, let's use an empty one. diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go index c2a602ec31..86fb45173d 100644 --- a/controllers/openstackcluster_controller_test.go +++ b/controllers/openstackcluster_controller_test.go @@ -196,10 +196,10 @@ var _ = Describe("OpenStackCluster controller", func() { Expect(err).To(MatchError(clientCreateErr)) Expect(result).To(Equal(reconcile.Result{})) }) - It("should be able to reconcile when bastion is disabled and does not exist", func() { - testCluster.SetName("no-bastion") + It("should be able to reconcile when bastion is explicitly disabled and does not exist", func() { + testCluster.SetName("no-bastion-explicit") testCluster.Spec = infrav1.OpenStackClusterSpec{ - Bastion: &infrav1.Bastion{}, + Bastion: &infrav1.Bastion{Enabled: pointer.Bool(false)}, } err := k8sClient.Create(ctx, testCluster) Expect(err).To(BeNil()) @@ -228,7 +228,7 @@ var _ = Describe("OpenStackCluster controller", func() { testCluster.SetName("adopt-existing-bastion") testCluster.Spec = infrav1.OpenStackClusterSpec{ Bastion: &infrav1.Bastion{ - Enabled: true, + Enabled: pointer.Bool(true), Spec: &bastionSpec, }, } @@ -311,7 +311,7 @@ var _ = Describe("OpenStackCluster controller", func() { testCluster.SetName("requeue-bastion") testCluster.Spec = infrav1.OpenStackClusterSpec{ Bastion: &infrav1.Bastion{ - Enabled: true, + Enabled: pointer.Bool(true), Spec: &bastionSpec, }, } @@ -393,7 +393,7 @@ var _ = Describe("OpenStackCluster controller", func() { testCluster.SetName("requeue-bastion") testCluster.Spec = infrav1.OpenStackClusterSpec{ Bastion: &infrav1.Bastion{ - Enabled: true, + Enabled: pointer.Bool(true), Spec: &bastionSpec, }, } @@ -467,9 +467,7 @@ var _ = Describe("OpenStackCluster controller", func() { }) It("should delete an existing bastion even if its uuid is not stored in status", func() { testCluster.SetName("delete-existing-bastion") - testCluster.Spec = infrav1.OpenStackClusterSpec{ - Bastion: &infrav1.Bastion{}, - } + testCluster.Spec = infrav1.OpenStackClusterSpec{} err := k8sClient.Create(ctx, testCluster) Expect(err).To(BeNil()) err = k8sClient.Create(ctx, capiCluster) @@ -516,7 +514,7 @@ var _ = Describe("OpenStackCluster controller", func() { testCluster.SetName("subnet-filtering") testCluster.Spec = infrav1.OpenStackClusterSpec{ Bastion: &infrav1.Bastion{ - Enabled: true, + Enabled: pointer.Bool(true), Spec: &bastionSpec, }, DisableAPIServerFloatingIP: pointer.Bool(true), @@ -586,7 +584,7 @@ var _ = Describe("OpenStackCluster controller", func() { testCluster.SetName("subnet-filtering") testCluster.Spec = infrav1.OpenStackClusterSpec{ Bastion: &infrav1.Bastion{ - Enabled: true, + Enabled: pointer.Bool(true), Spec: &bastionSpec, }, DisableAPIServerFloatingIP: pointer.Bool(true), diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md index 217373dd46..b97042eec6 100644 --- a/docs/book/src/api/v1beta1/api.md +++ b/docs/book/src/api/v1beta1/api.md @@ -1084,7 +1084,13 @@ bool -

Enabled means that bastion is enabled. Defaults to false.

+(Optional) +

Enabled means that bastion is enabled. The bastion is enabled by +default if this field is not specified. Set this field to false to disable the +bastion.

+

It is not currently possible to remove the bastion from the cluster +spec without first disabling it by setting this field to false and +waiting until the bastion has been deleted.

diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md index 36d68a5b19..7ad5cb3dab 100644 --- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md +++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md @@ -14,7 +14,7 @@ - [Change to image](#change-to-image) - [Removal of imageUUID](#removal-of-imageuuid) - [Changes to ports](#changes-to-ports) - - [Additon of floatingIPPoolRef](#additon-of-floatingippoolref) + - [Addition of floatingIPPoolRef](#addition-of-floatingippoolref) - [`OpenStackCluster`](#openstackcluster) - [Removal of cloudName](#removal-of-cloudname-1) - [identityRef is now required](#identityref-is-now-required) @@ -367,6 +367,8 @@ spec: #### Changes to bastion +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. + In v1beta1, `OpenStackCluster.spec.bastion.instance` becomes `OpenStackCluster.spec.bastion.spec`. ```yaml diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go index 5d159f52a5..cc41b9423b 100644 --- a/pkg/cloud/services/networking/securitygroups.go +++ b/pkg/cloud/services/networking/securitygroups.go @@ -47,7 +47,7 @@ func (s *Service) ReconcileSecurityGroups(openStackCluster *infrav1.OpenStackClu return nil } - bastionEnabled := openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled + bastionEnabled := openStackCluster.Spec.Bastion.IsEnabled() secControlPlaneGroupName := getSecControlPlaneGroupName(clusterResourceName) secWorkerGroupName := getSecWorkerGroupName(clusterResourceName) @@ -212,7 +212,7 @@ func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCl desiredSecGroupsBySuffix := make(map[string]securityGroupSpec) - if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled { + if openStackCluster.Spec.Bastion.IsEnabled() { controlPlaneRules = append(controlPlaneRules, getSGControlPlaneSSH(secBastionGroupID)...) workerRules = append(workerRules, getSGWorkerSSH(secBastionGroupID)...) @@ -357,7 +357,7 @@ func (s *Service) DeleteSecurityGroups(openStackCluster *infrav1.OpenStackCluste getSecWorkerGroupName(clusterResourceName), } - if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled { + if openStackCluster.Spec.Bastion.IsEnabled() { secGroupNames = append(secGroupNames, getSecBastionGroupName(clusterResourceName)) } diff --git a/pkg/cloud/services/networking/securitygroups_test.go b/pkg/cloud/services/networking/securitygroups_test.go index f40e4a5d75..487fa9bd87 100644 --- a/pkg/cloud/services/networking/securitygroups_test.go +++ b/pkg/cloud/services/networking/securitygroups_test.go @@ -533,7 +533,7 @@ func TestService_ReconcileSecurityGroups(t *testing.T) { name: "Default control plane, worker, and bastion security groups", openStackClusterSpec: infrav1.OpenStackClusterSpec{ Bastion: &infrav1.Bastion{ - Enabled: true, + Enabled: pointer.Bool(true), }, ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{}, }, diff --git a/pkg/webhooks/openstackcluster_webhook.go b/pkg/webhooks/openstackcluster_webhook.go index ece642481f..d5a68c6ae5 100644 --- a/pkg/webhooks/openstackcluster_webhook.go +++ b/pkg/webhooks/openstackcluster_webhook.go @@ -110,7 +110,7 @@ func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, new // Allow to remove the bastion spec only if it was disabled before. if newObj.Spec.Bastion == nil { - if oldObj.Spec.Bastion != nil && oldObj.Spec.Bastion.Enabled { + if oldObj.Spec.Bastion.IsEnabled() { allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "bastion"), "cannot be removed before disabling it")) } } diff --git a/pkg/webhooks/openstackcluster_webhook_test.go b/pkg/webhooks/openstackcluster_webhook_test.go index 09c18dcc70..d42b6eb1ce 100644 --- a/pkg/webhooks/openstackcluster_webhook_test.go +++ b/pkg/webhooks/openstackcluster_webhook_test.go @@ -92,7 +92,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) { }, Flavor: "minimal", }, - Enabled: true, + Enabled: pointer.Bool(true), }, }, Status: infrav1.OpenStackClusterStatus{ @@ -116,7 +116,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) { }, Flavor: "medium", }, - Enabled: true, + Enabled: pointer.Bool(true), }, }, }, @@ -459,7 +459,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) { CloudName: "foobar", }, Bastion: &infrav1.Bastion{ - Enabled: true, + Enabled: pointer.Bool(true), Spec: &infrav1.OpenStackMachineSpec{ Flavor: "m1.small", Image: infrav1.ImageParam{ @@ -490,7 +490,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) { CloudName: "foobar", }, Bastion: &infrav1.Bastion{ - Enabled: false, + Enabled: pointer.Bool(false), Spec: &infrav1.OpenStackMachineSpec{ Flavor: "m1.small", Image: infrav1.ImageParam{ diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go index 947f9b7b84..122269034b 100644 --- a/test/e2e/suites/apivalidations/openstackcluster_test.go +++ b/test/e2e/suites/apivalidations/openstackcluster_test.go @@ -90,7 +90,7 @@ var _ = Describe("OpenStackCluster API validations", func() { It("should allow bastion.enabled=true with a spec", func() { cluster.Spec.Bastion = &infrav1.Bastion{ - Enabled: true, + Enabled: pointer.Bool(true), Spec: &infrav1.OpenStackMachineSpec{ Image: infrav1.ImageParam{ Filter: &infrav1.ImageFilter{ @@ -104,25 +104,38 @@ var _ = Describe("OpenStackCluster API validations", func() { It("should not allow bastion.enabled=true without a spec", func() { cluster.Spec.Bastion = &infrav1.Bastion{ - Enabled: true, + Enabled: pointer.Bool(true), } Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed") }) - It("should default bastion.enabled=false", func() { + It("should not allow an empty Bastion", func() { cluster.Spec.Bastion = &infrav1.Bastion{} + Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed") + }) + + It("should default bastion.enabled=true", func() { + cluster.Spec.Bastion = &infrav1.Bastion{ + Spec: &infrav1.OpenStackMachineSpec{ + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("fake-image"), + }, + }, + }, + } Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should not succeed") // Fetch the cluster and check the defaulting fetchedCluster := &infrav1.OpenStackCluster{} Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cluster.Name, Namespace: cluster.Namespace}, fetchedCluster)).To(Succeed(), "OpenStackCluster fetch should succeed") - - Expect(fetchedCluster.Spec.Bastion.Enabled).To(BeFalse(), "Bastion.Enabled should default to false") + Expect(fetchedCluster.Spec.Bastion.Enabled).ToNot(BeNil(), "Bastion.Enabled should have been defaulted") + Expect(*fetchedCluster.Spec.Bastion.Enabled).To(BeTrueBecause("Bastion.Enabled should default to true")) }) It("should allow IPv4 as bastion floatingIP", func() { cluster.Spec.Bastion = &infrav1.Bastion{ - Enabled: true, + Enabled: pointer.Bool(true), Spec: &infrav1.OpenStackMachineSpec{ Image: infrav1.ImageParam{ Filter: &infrav1.ImageFilter{ @@ -137,7 +150,6 @@ var _ = Describe("OpenStackCluster API validations", func() { It("should not allow non-IPv4 as bastion floating IP", func() { cluster.Spec.Bastion = &infrav1.Bastion{ - Enabled: true, Spec: &infrav1.OpenStackMachineSpec{ Image: infrav1.ImageParam{ Filter: &infrav1.ImageFilter{ diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go index 37422eb33f..78ddf8b55a 100644 --- a/test/e2e/suites/e2e/e2e_test.go +++ b/test/e2e/suites/e2e/e2e_test.go @@ -176,7 +176,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() { openStackCluster, err = shared.ClusterForSpec(ctx, e2eCtx, namespace) Expect(err).NotTo(HaveOccurred()) openStackClusterDisabledBastion := openStackCluster.DeepCopy() - openStackClusterDisabledBastion.Spec.Bastion.Enabled = false + openStackClusterDisabledBastion.Spec.Bastion.Enabled = pointer.Bool(false) Expect(e2eCtx.Environment.BootstrapClusterProxy.GetClient().Update(ctx, openStackClusterDisabledBastion)).To(Succeed()) Eventually( func() (bool, error) {