Skip to content

Commit b33678b

Browse files
committed
Complete webhook validation for topology references
This patch is a follow up of [1] in the validation webhook area. It enhances the validation workflow and it aims to complete the pattern by distributing the ValidateTopology logic across the API instances. It is based on [2] and the key improvements include: - Distributed validation: it provides a ValidateTopology function across all API instances, ensuring consistent validation throughout the system - Optimized validation calls: it refines how validation is triggered and reduce code duplication; it still requires a basic struct refactor to fully de-duplicate the existing functions, but it can be done as part of a follow up This patch leverages the centralized topology validator introduced in infra-operator [3]. Jira: https://issues.redhat.com/browse/OSPRH-14626 [1] openstack-k8s-operators#924 [2] openstack-k8s-operators/nova-operator#936 [3] openstack-k8s-operators/infra-operator#356 Signed-off-by: Francesco Pantano <fpantano@redhat.com>
1 parent e89e0b8 commit b33678b

File tree

8 files changed

+155
-92
lines changed

8 files changed

+155
-92
lines changed

api/go.mod

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ go 1.21
55
require (
66
github.com/onsi/ginkgo/v2 v2.20.1
77
github.com/onsi/gomega v1.34.1
8-
github.com/openstack-k8s-operators/infra-operator/apis v0.6.0
9-
github.com/openstack-k8s-operators/lib-common/modules/common v0.5.1-0.20250228124213-cd63da392f97
10-
k8s.io/api v0.29.14
11-
k8s.io/apimachinery v0.29.14
12-
k8s.io/client-go v0.29.14
8+
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20250319162810-463dd75a4cc4
9+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20250315090821-34e570d2d5fb
10+
k8s.io/api v0.29.15
11+
k8s.io/apimachinery v0.29.15
12+
k8s.io/client-go v0.29.15
1313
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8
1414
sigs.k8s.io/controller-runtime v0.17.6
1515
)
@@ -65,8 +65,8 @@ require (
6565
gopkg.in/inf.v0 v0.9.1 // indirect
6666
gopkg.in/yaml.v2 v2.4.0 // indirect
6767
gopkg.in/yaml.v3 v3.0.1 // indirect
68-
k8s.io/apiextensions-apiserver v0.29.14 // indirect
69-
k8s.io/component-base v0.29.14 // indirect
68+
k8s.io/apiextensions-apiserver v0.29.15 // indirect
69+
k8s.io/component-base v0.29.15 // indirect
7070
k8s.io/klog/v2 v2.120.1 // indirect
7171
k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 // indirect
7272
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect

api/go.sum

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
7474
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
7575
github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094 h1:J1wuGhVxpsHykZBa6Beb1gQ96Ptej9AE/BvwCBiRj1E=
7676
github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4=
77-
github.com/openstack-k8s-operators/infra-operator/apis v0.6.0 h1:28i9Yc3UAdQK8VNzk0ubwq4n+qLuhD0nk6/7iHgD9us=
78-
github.com/openstack-k8s-operators/infra-operator/apis v0.6.0/go.mod h1:JgcmYJyyMKfArK8ulZnbls0L01qt8Dq6s5LH8TZH63A=
79-
github.com/openstack-k8s-operators/lib-common/modules/common v0.5.1-0.20250228124213-cd63da392f97 h1:3LC66vrXJzGMV/eCdvImosOEL2Cgc2KFJIm2YhfTG3w=
80-
github.com/openstack-k8s-operators/lib-common/modules/common v0.5.1-0.20250228124213-cd63da392f97/go.mod h1:rgpcv2tLD+/vudXx/gpIQSTuRpk4GOxHx84xwfvQalM=
77+
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20250319162810-463dd75a4cc4 h1:wb2zsr9x9LantNLN/9dmYM42c3yLq3QuzsoOlGpDUxM=
78+
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20250319162810-463dd75a4cc4/go.mod h1:n5DV/lGE9DHryAJ+JLJSgUXI2QHTj+aN4KoeSNC3PfU=
79+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20250315090821-34e570d2d5fb h1:UAFYEHnbyhO0+yymquFmIqxc9QGji9mzreuYrDS1Ev4=
80+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20250315090821-34e570d2d5fb/go.mod h1:1CtBP0MQffdjE6buOv5jP2rB3+h7WH0a11lcyrpmxOk=
8181
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
8282
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
8383
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -180,16 +180,16 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
180180
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
181181
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
182182
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
183-
k8s.io/api v0.29.14 h1:JWFh5ufowH3Y6tCgEzY3URVJHb27f0tEDEej0nCjWDw=
184-
k8s.io/api v0.29.14/go.mod h1:IV8YqKxMm8JGLBLlHM13Npn5lCITH10XYipWEW+YEOQ=
185-
k8s.io/apiextensions-apiserver v0.29.14 h1:gw9WXrZJPu5kpI1UC+Wf8BVe9PWwRUB/UZXU8VzBsq4=
186-
k8s.io/apiextensions-apiserver v0.29.14/go.mod h1:TJ51W+HKW2XqTtAsEFOz1/OohsMtekbKaTXh8ldioL4=
187-
k8s.io/apimachinery v0.29.14 h1:IDhwnGNCp836SLOwW1SoEfFNV77wxIklhxeAHX9vmSo=
188-
k8s.io/apimachinery v0.29.14/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
189-
k8s.io/client-go v0.29.14 h1:OSnzZ9DClaFRgl3zMAY2kGZhNjdGJkEb+RDz+MW2h6k=
190-
k8s.io/client-go v0.29.14/go.mod h1:XtZt5n5UxKfPJ+sCoTPcEavWgZbLFFxMnAFFRQGK1RY=
191-
k8s.io/component-base v0.29.14 h1:SF1DWN7bc2VloJ/ysegGoi/aHnopEo81aw9CslhqXIw=
192-
k8s.io/component-base v0.29.14/go.mod h1:FoK1PHhFTaEQVvQLw29/Uyfd8Ug0qUKHrUcXIXJ1VxI=
183+
k8s.io/api v0.29.15 h1:QxPcAheYujeBwkdiE0vMyKkAtqUq5YNyXVqimT+me44=
184+
k8s.io/api v0.29.15/go.mod h1:16duIp2ez6GiLPq1g8XtZNIkw6hJpIitpxZSvv0dZ6E=
185+
k8s.io/apiextensions-apiserver v0.29.15 h1:XI5axgsWqMlIIgpHbcz5vPjk06i3ibHv5FUdSfdtQLU=
186+
k8s.io/apiextensions-apiserver v0.29.15/go.mod h1:6ZU61z32I8WUwbBTPIANUesTj5G40sZek0ojmeoMJI8=
187+
k8s.io/apimachinery v0.29.15 h1:aLc0wghElkdnTO7TMVTxTrifoXah1lqRL8s6szDHGbg=
188+
k8s.io/apimachinery v0.29.15/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
189+
k8s.io/client-go v0.29.15 h1:zCBOXKCtz9Hl8boKUGs8zbtZEP6pc7O8Ov3ma+gnS6o=
190+
k8s.io/client-go v0.29.15/go.mod h1:xPy0D3p4sonPhZhI3QoYo4m7oLKoPjFf4vYF9oxoxNM=
191+
k8s.io/component-base v0.29.15 h1:CvmXXTDyk43FDaiJ/Rp+yWFjw6hkUI2t7mIJUrK5j00=
192+
k8s.io/component-base v0.29.15/go.mod h1:jH/sbuvmXew2Fz2iIKNMeNw8o/d1KR9tAg6uekQKnVk=
193193
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
194194
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
195195
k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 h1:qVoMaQV5t62UUvHe16Q3eb2c5HPzLHYzsi0Tu/xLndo=

api/v1beta1/common_types.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package v1beta1
1919
import (
2020
corev1 "k8s.io/api/core/v1"
2121
topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
22+
"k8s.io/apimachinery/pkg/util/validation/field"
2223
)
2324

2425
// IronicServiceTemplate defines the common input parameters for Ironic services
@@ -76,3 +77,15 @@ type KeystoneEndpoints struct {
7677
// Public endpoint URL
7778
Public string `json:"public"`
7879
}
80+
81+
// ValidateTopology -
82+
func (instance *IronicServiceTemplate) ValidateTopology(
83+
basePath *field.Path,
84+
namespace string,
85+
) field.ErrorList {
86+
var allErrs field.ErrorList
87+
allErrs = append(allErrs, topologyv1.ValidateTopologyRef(
88+
instance.TopologyRef,
89+
*basePath.Child("topologyRef"), namespace)...)
90+
return allErrs
91+
}

api/v1beta1/ironic_webhook.go

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -612,48 +612,38 @@ func (spec *IronicSpecCore) ValidateIronicTopology(basePath *field.Path, namespa
612612

613613
// When a TopologyRef CR is referenced, fail if a different Namespace is
614614
// referenced because is not supported
615-
if spec.TopologyRef != nil {
616-
if err := topologyv1.ValidateTopologyNamespace(spec.TopologyRef.Namespace, *basePath, namespace); err != nil {
617-
allErrs = append(allErrs, err)
618-
}
619-
}
615+
allErrs = append(allErrs, topologyv1.ValidateTopologyRef(
616+
spec.TopologyRef, *basePath.Child("topologyRef"), namespace)...)
620617

621618
// When a TopologyRef CR is referenced with an override to IronicAPI, fail
622619
// if a different Namespace is referenced because not supported
623-
if spec.IronicAPI.TopologyRef != nil {
624-
if err := topologyv1.ValidateTopologyNamespace(spec.IronicAPI.TopologyRef.Namespace, *basePath, namespace); err != nil {
625-
allErrs = append(allErrs, err)
626-
}
627-
}
620+
apiPath := basePath.Child("ironicAPI")
621+
allErrs = append(allErrs,
622+
spec.IronicAPI.ValidateTopology(apiPath, namespace)...)
628623

629624
// When a TopologyRef CR is referenced with an override to an instance of
630625
// IronicConductor(s), fail if a different Namespace is referenced because
631626
// not supported
632627
for _, cs := range spec.IronicConductors {
633-
if cs.TopologyRef != nil {
634-
if err := topologyv1.ValidateTopologyNamespace(cs.TopologyRef.Namespace, *basePath, namespace); err != nil {
635-
allErrs = append(allErrs, err)
636-
}
637-
}
628+
path := basePath.Child("ironicConductors")
629+
allErrs = append(allErrs,
630+
cs.ValidateTopology(path, namespace)...)
638631
}
639632

640633
// When a TopologyRef CR is referenced with an override to an instance of
641634
// IronicInspector, fail if a different Namespace is referenced because not
642635
// supported
643-
if spec.IronicInspector.TopologyRef != nil {
644-
if err := topologyv1.ValidateTopologyNamespace(spec.IronicInspector.TopologyRef.Namespace, *basePath, namespace); err != nil {
645-
allErrs = append(allErrs, err)
646-
}
647-
}
636+
insPath := basePath.Child("ironicInspector")
637+
allErrs = append(allErrs,
638+
spec.IronicInspector.ValidateTopology(insPath, namespace)...)
648639

649640
// When a TopologyRef CR is referenced with an override to an instance of
650641
// IronicNeutronAgent, fail if a different Namespace is referenced because
651642
// not supported
652-
if spec.IronicNeutronAgent.TopologyRef != nil {
653-
if err := topologyv1.ValidateTopologyNamespace(spec.IronicNeutronAgent.TopologyRef.Namespace, *basePath, namespace); err != nil {
654-
allErrs = append(allErrs, err)
655-
}
656-
}
643+
nagentPath := basePath.Child("ironicNeutronAgent")
644+
allErrs = append(allErrs,
645+
spec.IronicNeutronAgent.ValidateTopology(nagentPath, namespace)...)
646+
657647
return allErrs
658648
}
659649

api/v1beta1/ironicinspector_types.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/openstack-k8s-operators/lib-common/modules/common/tls"
2424
corev1 "k8s.io/api/core/v1"
2525
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
"k8s.io/apimachinery/pkg/util/validation/field"
2627
)
2728

2829
// IronicInspectorPasswordSelector to identify the AdminUser password from the Secret
@@ -279,3 +280,15 @@ func (instance *IronicInspector) GetLastAppliedTopology() *topologyv1.TopoRef {
279280
func (instance *IronicInspector) SetLastAppliedTopology(topologyRef *topologyv1.TopoRef) {
280281
instance.Status.LastAppliedTopology = topologyRef
281282
}
283+
284+
// ValidateTopology -
285+
func (instance *IronicInspectorTemplate) ValidateTopology(
286+
basePath *field.Path,
287+
namespace string,
288+
) field.ErrorList {
289+
var allErrs field.ErrorList
290+
allErrs = append(allErrs, topologyv1.ValidateTopologyRef(
291+
instance.TopologyRef,
292+
*basePath.Child("topologyRef"), namespace)...)
293+
return allErrs
294+
}

go.mod

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ require (
88
github.com/onsi/ginkgo/v2 v2.20.1
99
github.com/onsi/gomega v1.34.1
1010
github.com/openshift/api v3.9.0+incompatible
11-
github.com/openstack-k8s-operators/infra-operator/apis v0.6.0
11+
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20250319162810-463dd75a4cc4
1212
github.com/openstack-k8s-operators/ironic-operator/api v0.0.0-00010101000000-000000000000
1313
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20250309111939-0605fce19482
14-
github.com/openstack-k8s-operators/lib-common/modules/common v0.5.1-0.20250228124213-cd63da392f97
14+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20250315090821-34e570d2d5fb
1515
github.com/openstack-k8s-operators/lib-common/modules/test v0.5.1-0.20250228124213-cd63da392f97
1616
github.com/openstack-k8s-operators/mariadb-operator/api v0.6.0
17-
k8s.io/api v0.29.14
18-
k8s.io/apimachinery v0.29.14
19-
k8s.io/client-go v0.29.14
17+
k8s.io/api v0.29.15
18+
k8s.io/apimachinery v0.29.15
19+
k8s.io/client-go v0.29.15
2020
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8
2121
sigs.k8s.io/controller-runtime v0.17.6
2222
)
@@ -77,8 +77,8 @@ require (
7777
google.golang.org/protobuf v1.34.1 // indirect
7878
gopkg.in/inf.v0 v0.9.1 // indirect
7979
gopkg.in/yaml.v2 v2.4.0 // indirect
80-
k8s.io/apiextensions-apiserver v0.29.14 // indirect
81-
k8s.io/component-base v0.29.14 // indirect
80+
k8s.io/apiextensions-apiserver v0.29.15 // indirect
81+
k8s.io/component-base v0.29.15 // indirect
8282
k8s.io/klog/v2 v2.120.1 // indirect
8383
k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 // indirect
8484
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect

go.sum

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,12 @@ github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
7878
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
7979
github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094 h1:J1wuGhVxpsHykZBa6Beb1gQ96Ptej9AE/BvwCBiRj1E=
8080
github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4=
81-
github.com/openstack-k8s-operators/infra-operator/apis v0.6.0 h1:28i9Yc3UAdQK8VNzk0ubwq4n+qLuhD0nk6/7iHgD9us=
82-
github.com/openstack-k8s-operators/infra-operator/apis v0.6.0/go.mod h1:JgcmYJyyMKfArK8ulZnbls0L01qt8Dq6s5LH8TZH63A=
81+
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20250319162810-463dd75a4cc4 h1:wb2zsr9x9LantNLN/9dmYM42c3yLq3QuzsoOlGpDUxM=
82+
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20250319162810-463dd75a4cc4/go.mod h1:n5DV/lGE9DHryAJ+JLJSgUXI2QHTj+aN4KoeSNC3PfU=
8383
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20250309111939-0605fce19482 h1:W8PhAs+lX7Scgkr1zUGR9kK+ASTUv7DEFn3Aym1zfEg=
8484
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20250309111939-0605fce19482/go.mod h1:yzzegC4K5/iSWD24stJXfj46WjvPG9LTjLb03XvdZ4I=
85-
github.com/openstack-k8s-operators/lib-common/modules/common v0.5.1-0.20250228124213-cd63da392f97 h1:3LC66vrXJzGMV/eCdvImosOEL2Cgc2KFJIm2YhfTG3w=
86-
github.com/openstack-k8s-operators/lib-common/modules/common v0.5.1-0.20250228124213-cd63da392f97/go.mod h1:rgpcv2tLD+/vudXx/gpIQSTuRpk4GOxHx84xwfvQalM=
85+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20250315090821-34e570d2d5fb h1:UAFYEHnbyhO0+yymquFmIqxc9QGji9mzreuYrDS1Ev4=
86+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20250315090821-34e570d2d5fb/go.mod h1:1CtBP0MQffdjE6buOv5jP2rB3+h7WH0a11lcyrpmxOk=
8787
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.5.1-0.20250228124213-cd63da392f97 h1:2m8xt9k3FWcnzmq5SxplT0t6v8vvH7LZq3UWK17ygak=
8888
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.5.1-0.20250228124213-cd63da392f97/go.mod h1:tfMa+ochq7Dyilq9hQr2CEPfPtsj6IUgMmMqi4CWDmo=
8989
github.com/openstack-k8s-operators/lib-common/modules/test v0.5.1-0.20250228124213-cd63da392f97 h1:2f6Fl2chkacLkElCtEtCFygtuVhEq3YuUvZbfiEBDZ8=
@@ -200,16 +200,16 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
200200
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
201201
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
202202
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
203-
k8s.io/api v0.29.14 h1:JWFh5ufowH3Y6tCgEzY3URVJHb27f0tEDEej0nCjWDw=
204-
k8s.io/api v0.29.14/go.mod h1:IV8YqKxMm8JGLBLlHM13Npn5lCITH10XYipWEW+YEOQ=
205-
k8s.io/apiextensions-apiserver v0.29.14 h1:gw9WXrZJPu5kpI1UC+Wf8BVe9PWwRUB/UZXU8VzBsq4=
206-
k8s.io/apiextensions-apiserver v0.29.14/go.mod h1:TJ51W+HKW2XqTtAsEFOz1/OohsMtekbKaTXh8ldioL4=
207-
k8s.io/apimachinery v0.29.14 h1:IDhwnGNCp836SLOwW1SoEfFNV77wxIklhxeAHX9vmSo=
208-
k8s.io/apimachinery v0.29.14/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
209-
k8s.io/client-go v0.29.14 h1:OSnzZ9DClaFRgl3zMAY2kGZhNjdGJkEb+RDz+MW2h6k=
210-
k8s.io/client-go v0.29.14/go.mod h1:XtZt5n5UxKfPJ+sCoTPcEavWgZbLFFxMnAFFRQGK1RY=
211-
k8s.io/component-base v0.29.14 h1:SF1DWN7bc2VloJ/ysegGoi/aHnopEo81aw9CslhqXIw=
212-
k8s.io/component-base v0.29.14/go.mod h1:FoK1PHhFTaEQVvQLw29/Uyfd8Ug0qUKHrUcXIXJ1VxI=
203+
k8s.io/api v0.29.15 h1:QxPcAheYujeBwkdiE0vMyKkAtqUq5YNyXVqimT+me44=
204+
k8s.io/api v0.29.15/go.mod h1:16duIp2ez6GiLPq1g8XtZNIkw6hJpIitpxZSvv0dZ6E=
205+
k8s.io/apiextensions-apiserver v0.29.15 h1:XI5axgsWqMlIIgpHbcz5vPjk06i3ibHv5FUdSfdtQLU=
206+
k8s.io/apiextensions-apiserver v0.29.15/go.mod h1:6ZU61z32I8WUwbBTPIANUesTj5G40sZek0ojmeoMJI8=
207+
k8s.io/apimachinery v0.29.15 h1:aLc0wghElkdnTO7TMVTxTrifoXah1lqRL8s6szDHGbg=
208+
k8s.io/apimachinery v0.29.15/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
209+
k8s.io/client-go v0.29.15 h1:zCBOXKCtz9Hl8boKUGs8zbtZEP6pc7O8Ov3ma+gnS6o=
210+
k8s.io/client-go v0.29.15/go.mod h1:xPy0D3p4sonPhZhI3QoYo4m7oLKoPjFf4vYF9oxoxNM=
211+
k8s.io/component-base v0.29.15 h1:CvmXXTDyk43FDaiJ/Rp+yWFjw6hkUI2t7mIJUrK5j00=
212+
k8s.io/component-base v0.29.15/go.mod h1:jH/sbuvmXew2Fz2iIKNMeNw8o/d1KR9tAg6uekQKnVk=
213213
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
214214
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
215215
k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 h1:qVoMaQV5t62UUvHe16Q3eb2c5HPzLHYzsi0Tu/xLndo=

tests/functional/ironic_controller_test.go

Lines changed: 72 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -791,29 +791,76 @@ var _ = Describe("Ironic Webhook", func() {
791791
)
792792
})
793793

794-
It("rejects a wrong TopologyRef on a different namespace", func() {
795-
spec := GetDefaultIronicSpec()
796-
// Reference a top-level topology
797-
spec["topologyRef"] = map[string]interface{}{
798-
"name": ironicNames.IronicTopologies[0].Name,
799-
"namespace": "foo",
800-
}
801-
raw := map[string]interface{}{
802-
"apiVersion": "ironic.openstack.org/v1beta1",
803-
"kind": "Ironic",
804-
"metadata": map[string]interface{}{
805-
"name": ironicNames.IronicName.Name,
806-
"namespace": ironicNames.IronicName.Namespace,
807-
},
808-
"spec": spec,
809-
}
810-
unstructuredObj := &unstructured.Unstructured{Object: raw}
811-
_, err := controllerutil.CreateOrPatch(
812-
th.Ctx, th.K8sClient, unstructuredObj, func() error { return nil })
813-
Expect(err).To(HaveOccurred())
814-
Expect(err.Error()).To(
815-
ContainSubstring(
816-
"Invalid value: \"namespace\": Customizing namespace field is not supported"),
817-
)
818-
})
794+
DescribeTable("rejects wrong topology for",
795+
func(serviceNameFunc func() (string, string)) {
796+
797+
component, errorPath := serviceNameFunc()
798+
expectedErrorMessage := fmt.Sprintf("spec.%s.namespace: Invalid value: \"namespace\": Customizing namespace field is not supported", errorPath)
799+
800+
spec := GetDefaultIronicSpec()
801+
802+
// API, Inspector, NeutronAgent
803+
if component != "top-level" && component != "ironicConductors" {
804+
spec[component] = map[string]interface{}{
805+
"topologyRef": map[string]interface{}{
806+
"name": "bar",
807+
"namespace": "foo",
808+
},
809+
}
810+
}
811+
// Conductors
812+
if component == "ironicConductors" {
813+
condList := []map[string]interface{}{
814+
{
815+
"topologyRef": map[string]interface{}{
816+
"name": "foo",
817+
"namespace": "bar",
818+
},
819+
},
820+
}
821+
spec["ironicConductors"] = condList
822+
// top-level topologyRef
823+
} else {
824+
spec["topologyRef"] = map[string]interface{}{
825+
"name": "bar",
826+
"namespace": "foo",
827+
}
828+
}
829+
// Build the ironic CR
830+
raw := map[string]interface{}{
831+
"apiVersion": "ironic.openstack.org/v1beta1",
832+
"kind": "Ironic",
833+
"metadata": map[string]interface{}{
834+
"name": ironicNames.IronicName.Name,
835+
"namespace": ironicNames.IronicName.Namespace,
836+
},
837+
"spec": spec,
838+
}
839+
unstructuredObj := &unstructured.Unstructured{Object: raw}
840+
_, err := controllerutil.CreateOrPatch(
841+
th.Ctx, th.K8sClient, unstructuredObj, func() error { return nil })
842+
Expect(err).To(HaveOccurred())
843+
Expect(err.Error()).To(
844+
ContainSubstring(expectedErrorMessage))
845+
},
846+
Entry("top-level topologyRef", func() (string, string) {
847+
return "top-level", "topologyRef"
848+
}),
849+
Entry("ironicAPI topologyRef", func() (string, string) {
850+
component := "ironicAPI"
851+
return component, fmt.Sprintf("%s.topologyRef", component)
852+
}),
853+
Entry("ironicInspector topologyRef", func() (string, string) {
854+
component := "ironicInspector"
855+
return component, fmt.Sprintf("%s.topologyRef", component)
856+
}),
857+
Entry("ironicNeutronAgent topologyRef", func() (string, string) {
858+
component := "ironicNeutronAgent"
859+
return component, fmt.Sprintf("%s.topologyRef", component)
860+
}),
861+
Entry("ironicConductor topologyRef", func() (string, string) {
862+
component := "ironicConductors"
863+
return component, fmt.Sprintf("%s.topologyRef", component)
864+
}),
865+
)
819866
})

0 commit comments

Comments
 (0)