diff --git a/api/go.mod b/api/go.mod index dea2fc2ec..a2043cd04 100644 --- a/api/go.mod +++ b/api/go.mod @@ -70,3 +70,5 @@ require ( // mschuppert: map to latest commit from release-4.13 tag // must consistent within modules and service operators replace github.com/openshift/api => github.com/openshift/api v0.0.0-20230414143018-3367bc7e6ac7 //allow-merging + +replace github.com/openstack-k8s-operators/lib-common/modules/common => github.com/stuggi/lib-common/modules/common v0.0.0-20240508083919-01ef8c1d28c5 diff --git a/api/go.sum b/api/go.sum index 150c7c8b6..405af986f 100644 --- a/api/go.sum +++ b/api/go.sum @@ -65,8 +65,6 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= github.com/onsi/gomega v1.33.0 h1:snPCflnZrpMsy94p4lXVEkHo12lmPnc3vY5XBbreexE= -github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240429052447-09a614506ca6 h1:WLsG3Ko+phW5xZJjncypLWGASoLqKrt05qN9Zxsad6g= -github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240429052447-09a614506ca6/go.mod h1:lYhFzul37AR/6gAhTAA1KKWbOlzB3F/7014lejn883c= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -87,6 +85,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stuggi/lib-common/modules/common v0.0.0-20240508083919-01ef8c1d28c5 h1:RwBWawOf7fLsojvTdCeCZ+O5k3VqOqoX5f7PRQfa9lY= +github.com/stuggi/lib-common/modules/common v0.0.0-20240508083919-01ef8c1d28c5/go.mod h1:lYhFzul37AR/6gAhTAA1KKWbOlzB3F/7014lejn883c= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= diff --git a/api/v1beta1/nova_webhook.go b/api/v1beta1/nova_webhook.go index 1404d32cc..7fefc284f 100644 --- a/api/v1beta1/nova_webhook.go +++ b/api/v1beta1/nova_webhook.go @@ -26,6 +26,7 @@ import ( "fmt" "github.com/google/go-cmp/cmp" + service "github.com/openstack-k8s-operators/lib-common/modules/common/service" "github.com/robfig/cron/v3" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -210,9 +211,19 @@ func (r *NovaSpecCore) ValidateCellTemplates(basePath *field.Path) field.ErrorLi } func (r *NovaSpecCore) ValidateAPIServiceTemplate(basePath *field.Path) field.ErrorList { - errors := ValidateAPIDefaultConfigOverwrite( - basePath.Child("apiServiceTemplate").Child("defaultConfigOverwrite"), - r.APIServiceTemplate.DefaultConfigOverwrite) + errors := field.ErrorList{} + + // validate the service override key is valid + errors = append(errors, + service.ValidateRoutedOverrides( + basePath.Child("apiServiceTemplate").Child("override").Child("service"), + r.APIServiceTemplate.Override.Service)...) + + errors = append(errors, + ValidateAPIDefaultConfigOverwrite( + basePath.Child("apiServiceTemplate").Child("defaultConfigOverwrite"), + r.APIServiceTemplate.DefaultConfigOverwrite)...) + return errors } diff --git a/api/v1beta1/novaapi_webhook.go b/api/v1beta1/novaapi_webhook.go index fb055563d..718677d7d 100644 --- a/api/v1beta1/novaapi_webhook.go +++ b/api/v1beta1/novaapi_webhook.go @@ -34,6 +34,8 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + "github.com/openstack-k8s-operators/lib-common/modules/common/service" ) // NovaAPIDefaults - @@ -86,9 +88,16 @@ var _ webhook.Validator = &NovaAPI{} func (r *NovaAPI) ValidateCreate() (admission.Warnings, error) { novaapilog.Info("validate create", "name", r.Name) - errors := ValidateAPIDefaultConfigOverwrite( - field.NewPath("spec").Child("defaultConfigOverwrite"), - r.Spec.DefaultConfigOverwrite) + errors := field.ErrorList{} + basePath := field.NewPath("spec") + + // validate the service override key is valid + errors = append(errors, service.ValidateRoutedOverrides(basePath.Child("override").Child("service"), r.Spec.Override.Service)...) + + errors = append(errors, + ValidateAPIDefaultConfigOverwrite( + basePath.Child("defaultConfigOverwrite"), + r.Spec.DefaultConfigOverwrite)...) if len(errors) != 0 { novaapilog.Info("validation failed", "name", r.Name) @@ -109,9 +118,16 @@ func (r *NovaAPI) ValidateUpdate(old runtime.Object) (admission.Warnings, error) novaapilog.Info("validate update", "diff", cmp.Diff(oldNovaAPI, r)) - errors := ValidateAPIDefaultConfigOverwrite( - field.NewPath("spec").Child("defaultConfigOverwrite"), - r.Spec.DefaultConfigOverwrite) + errors := field.ErrorList{} + basePath := field.NewPath("spec") + + // validate the service override key is valid + errors = append(errors, service.ValidateRoutedOverrides(basePath.Child("override").Child("service"), r.Spec.Override.Service)...) + + errors = append(errors, + ValidateAPIDefaultConfigOverwrite( + basePath.Child("defaultConfigOverwrite"), + r.Spec.DefaultConfigOverwrite)...) if len(errors) != 0 { novaapilog.Info("validation failed", "name", r.Name) diff --git a/go.mod b/go.mod index 7521023f4..4c51ff8f5 100644 --- a/go.mod +++ b/go.mod @@ -88,3 +88,5 @@ replace github.com/openstack-k8s-operators/nova-operator/api => ./api // mschuppert: map to latest commit from release-4.13 tag // must consistent within modules and service operators replace github.com/openshift/api => github.com/openshift/api v0.0.0-20230414143018-3367bc7e6ac7 //allow-merging + +replace github.com/openstack-k8s-operators/lib-common/modules/common => github.com/stuggi/lib-common/modules/common v0.0.0-20240508083919-01ef8c1d28c5 diff --git a/go.sum b/go.sum index 5d7936190..7478e64dc 100644 --- a/go.sum +++ b/go.sum @@ -78,8 +78,6 @@ github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240429104248-2 github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240429104248-25176c735750/go.mod h1:QN2DJpfEc+mbvvfhoCuJ/UhQzvw12Mf+8nS0QX1HGIg= github.com/openstack-k8s-operators/keystone-operator/api v0.3.1-0.20240429164853-7e1e3b111ee9 h1:aS7xUxC/uOXfw0T4ARTu0G1qb6eJ0WnB2JRv9donPOE= github.com/openstack-k8s-operators/keystone-operator/api v0.3.1-0.20240429164853-7e1e3b111ee9/go.mod h1:Y/ge/l24phVaJb9S8mYRjtnDkohFkX/KEOUXLArcyvQ= -github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240429052447-09a614506ca6 h1:WLsG3Ko+phW5xZJjncypLWGASoLqKrt05qN9Zxsad6g= -github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240429052447-09a614506ca6/go.mod h1:lYhFzul37AR/6gAhTAA1KKWbOlzB3F/7014lejn883c= github.com/openstack-k8s-operators/lib-common/modules/openstack v0.3.1-0.20240429052447-09a614506ca6 h1:/mhzQQ9FF70z00zZD7dpgOoNXvEu9q68oob3oAiJW08= github.com/openstack-k8s-operators/lib-common/modules/openstack v0.3.1-0.20240429052447-09a614506ca6/go.mod h1:mrRNYeg8jb1zgGsufpN1/IB3sdbaST8btTBLwQ+taaA= github.com/openstack-k8s-operators/lib-common/modules/test v0.3.1-0.20240429052447-09a614506ca6 h1:Xx8uGcklRNHgBKTftNcK/Ob3qxiKwxUf5fVjtWCvOHI= @@ -106,6 +104,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stuggi/lib-common/modules/common v0.0.0-20240508083919-01ef8c1d28c5 h1:RwBWawOf7fLsojvTdCeCZ+O5k3VqOqoX5f7PRQfa9lY= +github.com/stuggi/lib-common/modules/common v0.0.0-20240508083919-01ef8c1d28c5/go.mod h1:lYhFzul37AR/6gAhTAA1KKWbOlzB3F/7014lejn883c= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= diff --git a/test/functional/validation_webhook_test.go b/test/functional/validation_webhook_test.go index 2f2b1a829..679664e56 100644 --- a/test/functional/validation_webhook_test.go +++ b/test/functional/validation_webhook_test.go @@ -1025,4 +1025,74 @@ var _ = Describe("Nova validation", func() { ), ) }) + + It("rejects NovaAPI wrong service override endpoint type", func() { + spec := GetDefaultNovaAPISpec(novaNames) + spec["override"] = map[string]interface{}{ + "service": map[string]interface{}{ + "internal": map[string]interface{}{}, + "wrooong": map[string]interface{}{}, + }, + } + raw := map[string]interface{}{ + "apiVersion": "nova.openstack.org/v1beta1", + "kind": "NovaAPI", + "metadata": map[string]interface{}{ + "name": novaNames.APIName.Name, + "namespace": novaNames.Namespace, + }, + "spec": spec, + } + + unstructuredObj := &unstructured.Unstructured{Object: raw} + _, err := controllerutil.CreateOrPatch( + ctx, k8sClient, unstructuredObj, func() error { return nil }) + + Expect(err).To(HaveOccurred()) + var statusError *k8s_errors.StatusError + Expect(errors.As(err, &statusError)).To(BeTrue()) + Expect(statusError.ErrStatus.Details.Kind).To(Equal("NovaAPI")) + Expect(statusError.ErrStatus.Message).To( + ContainSubstring( + "invalid: spec.override.service[wrooong]: " + + "Invalid value: \"wrooong\": invalid endpoint type: wrooong"), + ) + }) + It("rejects Nova with wrong service override endpoint type in NovaAPI", func() { + spec := GetDefaultNovaSpec() + spec["cellTemplates"] = map[string]interface{}{ + "cell0": GetDefaultNovaCellTemplate(), + } + spec["apiServiceTemplate"] = map[string]interface{}{ + "override": map[string]interface{}{ + "service": map[string]interface{}{ + "internal": map[string]interface{}{}, + "wrooong": map[string]interface{}{}, + }, + }, + } + raw := map[string]interface{}{ + "apiVersion": "nova.openstack.org/v1beta1", + "kind": "Nova", + "metadata": map[string]interface{}{ + "name": novaNames.NovaName.Name, + "namespace": novaNames.Namespace, + }, + "spec": spec, + } + + unstructuredObj := &unstructured.Unstructured{Object: raw} + _, err := controllerutil.CreateOrPatch( + ctx, k8sClient, unstructuredObj, func() error { return nil }) + + Expect(err).To(HaveOccurred()) + var statusError *k8s_errors.StatusError + Expect(errors.As(err, &statusError)).To(BeTrue()) + Expect(statusError.ErrStatus.Details.Kind).To(Equal("Nova")) + Expect(statusError.ErrStatus.Message).To( + ContainSubstring( + "invalid: spec.apiServiceTemplate.override.service[wrooong]: " + + "Invalid value: \"wrooong\": invalid endpoint type: wrooong"), + ) + }) })