Skip to content

Commit dc6dc35

Browse files
committed
Allow webhook changes to OpenStackCluster.Spec.Bastion
Signed-off-by: Tobias Giese <[email protected]>
1 parent 8e3bbaf commit dc6dc35

File tree

3 files changed

+175
-0
lines changed

3 files changed

+175
-0
lines changed

api/v1alpha4/openstackcluster_webhook.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,18 @@ func (r *OpenStackCluster) ValidateUpdate(oldRaw runtime.Object) error {
105105
r.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{}
106106
}
107107

108+
// Allow changes to the bastion spec only if no bastion host is deployed (i.e. Spec.Bastion.Enabled=false).
109+
if old.Status.Bastion == nil {
110+
old.Spec.Bastion = &Bastion{}
111+
r.Spec.Bastion = &Bastion{}
112+
}
113+
114+
// Allow toggling the bastion enabled flag.
115+
if old.Spec.Bastion != nil && r.Spec.Bastion != nil {
116+
old.Spec.Bastion.Enabled = true
117+
r.Spec.Bastion.Enabled = true
118+
}
119+
108120
if !reflect.DeepEqual(old.Spec, r.Spec) {
109121
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "cannot be modified"))
110122
}

api/v1alpha4/openstackcluster_webhook_test.go

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,164 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
111111
},
112112
wantErr: true,
113113
},
114+
{
115+
name: "Toggle OpenStackCluster.Spec.Bastion.Enabled flag is allowed",
116+
oldTemplate: &OpenStackCluster{
117+
Spec: OpenStackClusterSpec{
118+
CloudName: "foobar",
119+
Bastion: &Bastion{
120+
Instance: OpenStackMachineSpec{
121+
CloudName: "foobar",
122+
Image: "foobar",
123+
Flavor: "minimal",
124+
},
125+
Enabled: false,
126+
},
127+
},
128+
},
129+
newTemplate: &OpenStackCluster{
130+
Spec: OpenStackClusterSpec{
131+
CloudName: "foobar",
132+
Bastion: &Bastion{
133+
Instance: OpenStackMachineSpec{
134+
CloudName: "foobarbaz",
135+
Image: "foobarbaz",
136+
Flavor: "medium",
137+
},
138+
Enabled: true,
139+
},
140+
},
141+
},
142+
wantErr: false,
143+
},
144+
{
145+
name: "Changing empty OpenStackCluster.Spec.Bastion is allowed",
146+
oldTemplate: &OpenStackCluster{
147+
Spec: OpenStackClusterSpec{
148+
CloudName: "foobar",
149+
},
150+
},
151+
newTemplate: &OpenStackCluster{
152+
Spec: OpenStackClusterSpec{
153+
CloudName: "foobar",
154+
Bastion: &Bastion{
155+
Instance: OpenStackMachineSpec{
156+
CloudName: "foobar",
157+
Image: "foobar",
158+
Flavor: "medium",
159+
},
160+
Enabled: true,
161+
},
162+
},
163+
},
164+
wantErr: false,
165+
},
166+
{
167+
name: "Changing OpenStackCluster.Spec.Bastion with no deployed bastion host is allowed",
168+
oldTemplate: &OpenStackCluster{
169+
Spec: OpenStackClusterSpec{
170+
CloudName: "foobar",
171+
Bastion: &Bastion{
172+
Instance: OpenStackMachineSpec{
173+
CloudName: "foobar",
174+
Image: "foobar",
175+
Flavor: "minimal",
176+
},
177+
Enabled: false,
178+
},
179+
},
180+
Status: OpenStackClusterStatus{},
181+
},
182+
newTemplate: &OpenStackCluster{
183+
Spec: OpenStackClusterSpec{
184+
CloudName: "foobar",
185+
Bastion: &Bastion{
186+
Instance: OpenStackMachineSpec{
187+
CloudName: "foobarbaz",
188+
Image: "foobarbaz",
189+
Flavor: "medium",
190+
},
191+
Enabled: true,
192+
},
193+
},
194+
},
195+
wantErr: false,
196+
},
197+
{
198+
name: "Changing OpenStackCluster.Spec.Bastion with deployed bastion host is not allowed",
199+
oldTemplate: &OpenStackCluster{
200+
Spec: OpenStackClusterSpec{
201+
CloudName: "foobar",
202+
Bastion: &Bastion{
203+
Instance: OpenStackMachineSpec{
204+
CloudName: "foobar",
205+
Image: "foobar",
206+
Flavor: "minimal",
207+
},
208+
Enabled: true,
209+
},
210+
},
211+
Status: OpenStackClusterStatus{
212+
Bastion: &Instance{
213+
Name: "foobar",
214+
},
215+
},
216+
},
217+
newTemplate: &OpenStackCluster{
218+
Spec: OpenStackClusterSpec{
219+
CloudName: "foobar",
220+
Bastion: &Bastion{
221+
Instance: OpenStackMachineSpec{
222+
CloudName: "foobarbaz",
223+
Image: "foobarbaz",
224+
Flavor: "medium",
225+
},
226+
Enabled: true,
227+
},
228+
},
229+
},
230+
wantErr: true,
231+
},
232+
{
233+
name: "Disabling the OpenStackCluster.Spec.Bastion while it's running is allowed",
234+
oldTemplate: &OpenStackCluster{
235+
Spec: OpenStackClusterSpec{
236+
CloudName: "foobar",
237+
Bastion: &Bastion{
238+
Instance: OpenStackMachineSpec{
239+
CloudName: "foobar",
240+
Image: "foobar",
241+
Flavor: "minimal",
242+
},
243+
Enabled: true,
244+
},
245+
},
246+
Status: OpenStackClusterStatus{
247+
Bastion: &Instance{
248+
Name: "foobar",
249+
},
250+
},
251+
},
252+
newTemplate: &OpenStackCluster{
253+
Spec: OpenStackClusterSpec{
254+
CloudName: "foobar",
255+
Bastion: &Bastion{
256+
Instance: OpenStackMachineSpec{
257+
CloudName: "foobar",
258+
Image: "foobar",
259+
Flavor: "minimal",
260+
},
261+
Enabled: false,
262+
},
263+
},
264+
Status: OpenStackClusterStatus{
265+
Bastion: &Instance{
266+
Name: "foobar",
267+
},
268+
},
269+
},
270+
wantErr: false,
271+
},
114272
}
115273
for _, tt := range tests {
116274
t.Run(tt.name, func(t *testing.T) {

docs/book/src/clusteropenstack/configuration.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,11 @@ To configure the Cluster API Provider for OpenStack to create a SSH bastion host
402402
sshKeyName: <Key pair name>
403403
```
404404

405+
The `enabled` flag is toggleable. Thus, you're able to save resources while the bastion host is not needed.
406+
All other parameters can be changed via an `OpenStackCluster` update while the bastion host is not running.
407+
408+
> Note: as a rolling update is not ideal during a bastion host session, we prevent changes to a running bastion configuration.
409+
405410
A floating IP is created and associated to the bastion host automatically, but you can add the IP address explicitly:
406411

407412
```yaml

0 commit comments

Comments
 (0)