Skip to content

Commit d76e19e

Browse files
authored
Merge pull request #1076 from Daimler/tobiasgiese/cherry-pick-bastion-1070
✨ [v0.5.0] Allow webhook changes to OpenStackCluster.Spec.Bastion
2 parents 616df5b + dc6dc35 commit d76e19e

File tree

5 files changed

+392
-28
lines changed

5 files changed

+392
-28
lines changed

api/v1alpha4/openstackcluster_webhook.go

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ limitations under the License.
1717
package v1alpha4
1818

1919
import (
20+
"fmt"
2021
"reflect"
2122

22-
"github.com/pkg/errors"
2323
apierrors "k8s.io/apimachinery/pkg/api/errors"
2424
"k8s.io/apimachinery/pkg/runtime"
2525
"k8s.io/apimachinery/pkg/util/validation/field"
26+
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
2627
"sigs.k8s.io/controller-runtime/pkg/builder"
2728
logf "sigs.k8s.io/controller-runtime/pkg/log"
2829
"sigs.k8s.io/controller-runtime/pkg/manager"
@@ -65,40 +66,58 @@ func (r *OpenStackCluster) ValidateCreate() error {
6566
}
6667

6768
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
68-
func (r *OpenStackCluster) ValidateUpdate(old runtime.Object) error {
69+
func (r *OpenStackCluster) ValidateUpdate(oldRaw runtime.Object) error {
6970
var allErrs field.ErrorList
71+
old, ok := oldRaw.(*OpenStackCluster)
72+
if !ok {
73+
return apierrors.NewBadRequest(fmt.Sprintf("expected an OpenStackCluster but got a %T", oldRaw))
74+
}
7075

71-
newOpenStackCluster, err := runtime.DefaultUnstructuredConverter.ToUnstructured(r)
72-
if err != nil {
73-
return apierrors.NewInvalid(GroupVersion.WithKind("OpenStackCluster").GroupKind(), r.Name, field.ErrorList{
74-
field.InternalError(nil, errors.Wrap(err, "failed to convert new OpenStackCluster to unstructured object")),
75-
})
76+
if r.Spec.IdentityRef != nil && r.Spec.IdentityRef.Kind != defaultIdentityRefKind {
77+
allErrs = append(allErrs,
78+
field.Invalid(field.NewPath("spec", "identityRef", "kind"),
79+
r.Spec.IdentityRef, "must be a Secret"),
80+
)
7681
}
77-
oldOpenStackCluster, err := runtime.DefaultUnstructuredConverter.ToUnstructured(old)
78-
if err != nil {
79-
return apierrors.NewInvalid(GroupVersion.WithKind("OpenStackCluster").GroupKind(), r.Name, field.ErrorList{
80-
field.InternalError(nil, errors.Wrap(err, "failed to convert old OpenStackCluster to unstructured object")),
81-
})
82+
83+
// Allow changes to Spec.IdentityRef.Name.
84+
if old.Spec.IdentityRef != nil && r.Spec.IdentityRef != nil {
85+
old.Spec.IdentityRef.Name = ""
86+
r.Spec.IdentityRef.Name = ""
8287
}
8388

84-
if r.Spec.IdentityRef != nil && r.Spec.IdentityRef.Kind != defaultIdentityRefKind {
85-
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "identityRef", "kind"), "must be a Secret"))
89+
// Allow changes to Spec.IdentityRef if it was unset.
90+
if old.Spec.IdentityRef == nil && r.Spec.IdentityRef != nil {
91+
old.Spec.IdentityRef = &OpenStackIdentityReference{}
92+
r.Spec.IdentityRef = &OpenStackIdentityReference{}
8693
}
8794

88-
newOpenStackClusterSpec := newOpenStackCluster["spec"].(map[string]interface{})
89-
oldOpenStackClusterSpec := oldOpenStackCluster["spec"].(map[string]interface{})
95+
if old.Spec.IdentityRef != nil && r.Spec.IdentityRef == nil {
96+
allErrs = append(allErrs,
97+
field.Invalid(field.NewPath("spec", "identityRef"),
98+
r.Spec.IdentityRef, "field cannot be set to nil"),
99+
)
100+
}
101+
102+
// Allow change only for the first time.
103+
if old.Spec.ControlPlaneEndpoint.Host == "" {
104+
old.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{}
105+
r.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{}
106+
}
90107

91-
// get controlPlaneEndpoint, something like {"host":"", "port":""}
92-
cpe := oldOpenStackClusterSpec["controlPlaneEndpoint"].(map[string]interface{})
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+
}
93113

94-
// allow change only for the first time
95-
host, ok := cpe["host"].(string)
96-
if ok && len(host) == 0 {
97-
delete(oldOpenStackClusterSpec, "controlPlaneEndpoint")
98-
delete(newOpenStackClusterSpec, "controlPlaneEndpoint")
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
99118
}
100119

101-
if !reflect.DeepEqual(oldOpenStackClusterSpec, newOpenStackClusterSpec) {
120+
if !reflect.DeepEqual(old.Spec, r.Spec) {
102121
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "cannot be modified"))
103122
}
104123

0 commit comments

Comments
 (0)