Skip to content

Commit 3b55e32

Browse files
Merge pull request openstack-k8s-operators#400 from abays/osprh_29980
[b/r] Add skip-webhook-validation annotation for OpenStackBaremetalSet
2 parents 96ee712 + 6af1d2f commit 3b55e32

6 files changed

Lines changed: 87 additions & 12 deletions

File tree

api/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ require (
77
github.com/go-playground/validator/v10 v10.30.1
88
github.com/metal3-io/baremetal-operator/apis v0.9.3
99
github.com/onsi/ginkgo/v2 v2.28.2
10-
github.com/onsi/gomega v1.40.0
11-
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260515134210-2e2a0d06648c
10+
github.com/onsi/gomega v1.41.0
11+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260610101308-d3778a549c89
1212
k8s.io/api v0.31.14
1313
k8s.io/apimachinery v0.31.14
1414
sigs.k8s.io/controller-runtime v0.19.7

api/go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
105105
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
106106
github.com/onsi/ginkgo/v2 v2.28.2 h1:DTrMfpqxiNUyQ3Y0zhn1n3cOO2euFgQPYIpkWwxVFps=
107107
github.com/onsi/ginkgo/v2 v2.28.2/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE=
108-
github.com/onsi/gomega v1.40.0 h1:Vtol0e1MghCD2ZVIilPDIg44XSL9l2QAn8ZNaljWcJc=
109-
github.com/onsi/gomega v1.40.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A=
110-
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260515134210-2e2a0d06648c h1:tTESojEnTyj5EZ1IlHiTncHqN6Az7iWLBd7sbMDSsEY=
111-
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260515134210-2e2a0d06648c/go.mod h1:aIuG6lx3aS0vnXweRNdR/Q0SlfOsLIo0OzrqKK7C6xs=
108+
github.com/onsi/gomega v1.41.0 h1:OwKp4pXNgVxf6sCplzYo794OFNuoL2q2SBMU5NSWOjA=
109+
github.com/onsi/gomega v1.41.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A=
110+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260610101308-d3778a549c89 h1:+tWqTXuBAKW4BLfegP0HvtMsE9KK8tX4lw76gaW+oeA=
111+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260610101308-d3778a549c89/go.mod h1:JC04T5G4E/he5ukonV1oCqa0QzFkLv761VbLruVghJM=
112112
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
113113
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
114114
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ require (
99
github.com/google/uuid v1.6.0
1010
github.com/metal3-io/baremetal-operator/apis v0.9.3
1111
github.com/onsi/ginkgo/v2 v2.28.2
12-
github.com/onsi/gomega v1.40.0
13-
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260515134210-2e2a0d06648c
12+
github.com/onsi/gomega v1.41.0
13+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260610101308-d3778a549c89
1414
github.com/openstack-k8s-operators/openstack-baremetal-operator/api v0.0.0-00010101000000-000000000000
1515
github.com/spf13/cobra v1.10.2
1616
k8s.io/api v0.31.14

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,12 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
131131
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
132132
github.com/onsi/ginkgo/v2 v2.28.2 h1:DTrMfpqxiNUyQ3Y0zhn1n3cOO2euFgQPYIpkWwxVFps=
133133
github.com/onsi/ginkgo/v2 v2.28.2/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE=
134-
github.com/onsi/gomega v1.40.0 h1:Vtol0e1MghCD2ZVIilPDIg44XSL9l2QAn8ZNaljWcJc=
135-
github.com/onsi/gomega v1.40.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A=
134+
github.com/onsi/gomega v1.41.0 h1:OwKp4pXNgVxf6sCplzYo794OFNuoL2q2SBMU5NSWOjA=
135+
github.com/onsi/gomega v1.41.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A=
136136
github.com/openshift/api v0.0.0-20250711200046-c86d80652a9e h1:E1OdwSpqWuDPCedyUt0GEdoAE+r5TXy7YS21yNEo+2U=
137137
github.com/openshift/api v0.0.0-20250711200046-c86d80652a9e/go.mod h1:Shkl4HanLwDiiBzakv+con/aMGnVE2MAGvoKp5oyYUo=
138-
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260515134210-2e2a0d06648c h1:tTESojEnTyj5EZ1IlHiTncHqN6Az7iWLBd7sbMDSsEY=
139-
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260515134210-2e2a0d06648c/go.mod h1:aIuG6lx3aS0vnXweRNdR/Q0SlfOsLIo0OzrqKK7C6xs=
138+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260610101308-d3778a549c89 h1:+tWqTXuBAKW4BLfegP0HvtMsE9KK8tX4lw76gaW+oeA=
139+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260610101308-d3778a549c89/go.mod h1:JC04T5G4E/he5ukonV1oCqa0QzFkLv761VbLruVghJM=
140140
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
141141
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
142142
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

internal/webhook/v1beta1/openstackbaremetalset_webhook.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"sigs.k8s.io/controller-runtime/pkg/webhook"
2929
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
3030

31+
"github.com/openstack-k8s-operators/lib-common/modules/common/annotations"
3132
baremetalv1beta1 "github.com/openstack-k8s-operators/openstack-baremetal-operator/api/v1beta1"
3233
)
3334

@@ -36,6 +37,9 @@ var (
3637
ErrInvalidOpenStackBaremetalSetType = errors.New("expected an OpenStackBaremetalSet object")
3738
)
3839

40+
const skipValidationWarning = "webhook validation is being skipped due to the " +
41+
annotations.SkipValidationAnnotation + " annotation; remove it when no longer needed"
42+
3943
// nolint:unused
4044
// log is for logging in this package.
4145
var openstackbaremetalsetlog = logf.Log.WithName("openstackbaremetalset-resource")
@@ -104,6 +108,11 @@ func (v *OpenStackBaremetalSetCustomValidator) ValidateCreate(_ context.Context,
104108
}
105109
openstackbaremetalsetlog.Info("Validation for OpenStackBaremetalSet upon creation", "name", openstackbaremetalset.GetName())
106110

111+
if annotations.SkipValidation(openstackbaremetalset) {
112+
openstackbaremetalsetlog.Info("Skipping webhook validation", "name", openstackbaremetalset.GetName())
113+
return admission.Warnings{skipValidationWarning}, nil
114+
}
115+
107116
// Call the validation function from api/v1beta1
108117
return openstackbaremetalset.ValidateCreate()
109118
}
@@ -116,6 +125,11 @@ func (v *OpenStackBaremetalSetCustomValidator) ValidateUpdate(_ context.Context,
116125
}
117126
openstackbaremetalsetlog.Info("Validation for OpenStackBaremetalSet upon update", "name", openstackbaremetalset.GetName())
118127

128+
if annotations.SkipValidation(openstackbaremetalset) {
129+
openstackbaremetalsetlog.Info("Skipping webhook validation", "name", openstackbaremetalset.GetName())
130+
return admission.Warnings{skipValidationWarning}, nil
131+
}
132+
119133
// Call the validation function from api/v1beta1
120134
return openstackbaremetalset.ValidateUpdate(oldObj)
121135
}
@@ -128,6 +142,11 @@ func (v *OpenStackBaremetalSetCustomValidator) ValidateDelete(_ context.Context,
128142
}
129143
openstackbaremetalsetlog.Info("Validation for OpenStackBaremetalSet upon deletion", "name", openstackbaremetalset.GetName())
130144

145+
if annotations.SkipValidation(openstackbaremetalset) {
146+
openstackbaremetalsetlog.Info("Skipping webhook validation", "name", openstackbaremetalset.GetName())
147+
return admission.Warnings{skipValidationWarning}, nil
148+
}
149+
131150
// Call the validation function from api/v1beta1
132151
return openstackbaremetalset.ValidateDelete()
133152
}

tests/functional/openstackbaremetalset_webhook_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ import (
1111
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1212
"k8s.io/apimachinery/pkg/types"
1313

14+
"github.com/openstack-k8s-operators/lib-common/modules/common/annotations"
15+
baremetalv1 "github.com/openstack-k8s-operators/openstack-baremetal-operator/api/v1beta1"
16+
webhookv1beta1 "github.com/openstack-k8s-operators/openstack-baremetal-operator/internal/webhook/v1beta1"
17+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1418
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
1519
)
1620

@@ -151,6 +155,58 @@ var _ = Describe("OpenStackBaremetalSet Webhook", func() {
151155
})
152156
})
153157

158+
When("When creating BaremetalSet with skip webhook validation annotation", func() {
159+
BeforeEach(func() {
160+
DeferCleanup(th.DeleteInstance, CreateBaremetalHost(bmhName))
161+
bmh := GetBaremetalHost(bmhName)
162+
Eventually(func(g Gomega) {
163+
bmh.Status.Provisioning.State = metal3v1.StateAvailable
164+
g.Expect(th.K8sClient.Status().Update(th.Ctx, bmh)).To(Succeed())
165+
}, th.Timeout, th.Interval).Should(Succeed())
166+
})
167+
168+
It("It should not fail even with insufficient BMHs when annotation is set", func() {
169+
spec := TwoNodeBaremetalSetSpec(baremetalSetName.Namespace)
170+
object := DefaultBaremetalSetTemplate(baremetalSetName, spec)
171+
metadata := object["metadata"].(map[string]any)
172+
metadata["annotations"] = map[string]any{
173+
annotations.SkipValidationAnnotation: "",
174+
}
175+
unstructuredObj := &unstructured.Unstructured{Object: object}
176+
_, err := controllerutil.CreateOrPatch(
177+
th.Ctx, th.K8sClient, unstructuredObj, func() error { return nil })
178+
Expect(err).ShouldNot(HaveOccurred())
179+
})
180+
181+
It("should return a warning when skip-validation annotation is set", func() {
182+
validator := &webhookv1beta1.OpenStackBaremetalSetCustomValidator{}
183+
obj := &baremetalv1.OpenStackBaremetalSet{
184+
ObjectMeta: metav1.ObjectMeta{
185+
Name: baremetalSetName.Name,
186+
Namespace: baremetalSetName.Namespace,
187+
Annotations: map[string]string{
188+
annotations.SkipValidationAnnotation: "",
189+
},
190+
},
191+
}
192+
193+
warnings, err := validator.ValidateCreate(th.Ctx, obj)
194+
Expect(err).ShouldNot(HaveOccurred())
195+
Expect(warnings).To(HaveLen(1))
196+
Expect(warnings[0]).To(ContainSubstring(annotations.SkipValidationAnnotation))
197+
198+
warnings, err = validator.ValidateUpdate(th.Ctx, obj, obj)
199+
Expect(err).ShouldNot(HaveOccurred())
200+
Expect(warnings).To(HaveLen(1))
201+
Expect(warnings[0]).To(ContainSubstring(annotations.SkipValidationAnnotation))
202+
203+
warnings, err = validator.ValidateDelete(th.Ctx, obj)
204+
Expect(err).ShouldNot(HaveOccurred())
205+
Expect(warnings).To(HaveLen(1))
206+
Expect(warnings[0]).To(ContainSubstring(annotations.SkipValidationAnnotation))
207+
})
208+
})
209+
154210
When("When creating BaremetalSet with node selectors", func() {
155211
BeforeEach(func() {
156212
DeferCleanup(th.DeleteInstance, CreateBaremetalHostWithNodeLabel(

0 commit comments

Comments
 (0)