diff --git a/cmd/generate_gatewayapi_httproute_test.go b/cmd/generate_gatewayapi_httproute_test.go new file mode 100644 index 0000000..49666de --- /dev/null +++ b/cmd/generate_gatewayapi_httproute_test.go @@ -0,0 +1,141 @@ +package cmd + +import ( + "bytes" + "io" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" + "sigs.k8s.io/yaml" +) + +var _ = Describe("Generate HTTPRoute", func() { + var ( + cmd *cobra.Command + cmdStdoutBuffer *bytes.Buffer + cmdStderrBuffer *bytes.Buffer + ) + + BeforeEach(func() { + cmd = generateGatewayApiHttpRouteCommand() + cmdStdoutBuffer = bytes.NewBufferString("") + cmdStderrBuffer = bytes.NewBufferString("") + cmd.SetOut(cmdStdoutBuffer) + cmd.SetErr(cmdStderrBuffer) + }) + + Context("with invalid OAS", func() { + It("happy path", func() { + cmd.SetArgs([]string{"--oas", "testdata/invalid_oas.yaml"}) + Expect(cmd.Execute()).Should(MatchError(ContainSubstring("OpenAPI validation error"))) + + }) + }) + + Context("with root level kuadrant extensions", func() { + It("HTTPRoute is generated", func() { + cmd.SetArgs([]string{"--oas", "testdata/petstore_openapi.yaml"}) + Expect(cmd.Execute()).ShouldNot(HaveOccurred()) + out, err := io.ReadAll(cmdStdoutBuffer) + Expect(err).ShouldNot(HaveOccurred()) + + var httpRoute gatewayapiv1.HTTPRoute + Expect(yaml.Unmarshal(out, &httpRoute)).ShouldNot(HaveOccurred()) + Expect(httpRoute.TypeMeta).To(Equal(metav1.TypeMeta{ + APIVersion: gatewayapiv1.GroupVersion.String(), + Kind: "HTTPRoute", + })) + Expect(httpRoute.ObjectMeta).To(Equal(metav1.ObjectMeta{ + Name: "petstore", + Namespace: "petstore-ns", + })) + Expect(httpRoute.Spec.CommonRouteSpec).To(Equal(gatewayapiv1.CommonRouteSpec{ + ParentRefs: []gatewayapiv1.ParentReference{ + { + Name: "gw", Namespace: ptr.To(gatewayapiv1.Namespace("gw-ns")), + }, + }, + })) + Expect(httpRoute.Spec.Hostnames).To(Equal([]gatewayapiv1.Hostname{ + gatewayapiv1.Hostname("example.com"), + })) + Expect(httpRoute.Spec.Rules).To(HaveLen(3)) + Expect(httpRoute.Spec.Rules).To(ContainElement( + gatewayapiv1.HTTPRouteRule{ + Matches: []gatewayapiv1.HTTPRouteMatch{ + { + Path: &gatewayapiv1.HTTPPathMatch{ + Type: ptr.To(gatewayapiv1.PathMatchExact), + Value: ptr.To("/v1/cat"), + }, + Method: ptr.To(gatewayapiv1.HTTPMethodGet), + }, + }, + BackendRefs: []gatewayapiv1.HTTPBackendRef{ + { + BackendRef: gatewayapiv1.BackendRef{ + BackendObjectReference: gatewayapiv1.BackendObjectReference{ + Name: "petstore", + Namespace: ptr.To(gatewayapiv1.Namespace("petstore")), + Port: ptr.To(gatewayapiv1.PortNumber(80)), + }, + }, + }, + }, + }, + )) + Expect(httpRoute.Spec.Rules).To(ContainElement( + gatewayapiv1.HTTPRouteRule{ + Matches: []gatewayapiv1.HTTPRouteMatch{ + { + Path: &gatewayapiv1.HTTPPathMatch{ + Type: ptr.To(gatewayapiv1.PathMatchExact), + Value: ptr.To("/v1/dog"), + }, + Method: ptr.To(gatewayapiv1.HTTPMethodGet), + }, + }, + BackendRefs: []gatewayapiv1.HTTPBackendRef{ + { + BackendRef: gatewayapiv1.BackendRef{ + BackendObjectReference: gatewayapiv1.BackendObjectReference{ + Name: "petstore", + Namespace: ptr.To(gatewayapiv1.Namespace("petstore")), + Port: ptr.To(gatewayapiv1.PortNumber(80)), + }, + }, + }, + }, + }, + )) + Expect(httpRoute.Spec.Rules).To(ContainElement( + gatewayapiv1.HTTPRouteRule{ + Matches: []gatewayapiv1.HTTPRouteMatch{ + { + Path: &gatewayapiv1.HTTPPathMatch{ + Type: ptr.To(gatewayapiv1.PathMatchExact), + Value: ptr.To("/v1/dog"), + }, + Method: ptr.To(gatewayapiv1.HTTPMethodPost), + }, + }, + BackendRefs: []gatewayapiv1.HTTPBackendRef{ + { + BackendRef: gatewayapiv1.BackendRef{ + BackendObjectReference: gatewayapiv1.BackendObjectReference{ + Name: "petstore", + Namespace: ptr.To(gatewayapiv1.Namespace("petstore")), + Port: ptr.To(gatewayapiv1.PortNumber(80)), + }, + }, + }, + }, + }, + )) + }) + }) +}) diff --git a/cmd/generate_kuadrant_authpolicy_test.go b/cmd/generate_kuadrant_authpolicy_test.go new file mode 100644 index 0000000..8bde5de --- /dev/null +++ b/cmd/generate_kuadrant_authpolicy_test.go @@ -0,0 +1,111 @@ +package cmd + +import ( + "bytes" + "io" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" + gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/yaml" + + authorinoapi "github.com/kuadrant/authorino/api/v1beta2" + kuadrantapiv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" +) + +var _ = Describe("Generate AuthPolicy", func() { + var ( + cmd *cobra.Command + cmdStdoutBuffer *bytes.Buffer + cmdStderrBuffer *bytes.Buffer + ) + + BeforeEach(func() { + cmd = generateKuadrantAuthPolicyCommand() + cmdStdoutBuffer = bytes.NewBufferString("") + cmdStderrBuffer = bytes.NewBufferString("") + cmd.SetOut(cmdStdoutBuffer) + cmd.SetErr(cmdStderrBuffer) + }) + + Context("with invalid OAS", func() { + It("happy path", func() { + cmd.SetArgs([]string{"--oas", "testdata/invalid_oas.yaml"}) + Expect(cmd.Execute()).Should(MatchError(ContainSubstring("OpenAPI validation error"))) + + }) + }) + + Context("with operation including security", func() { + It("authorization policy generated", func() { + cmd.SetArgs([]string{"--oas", "testdata/petstore_openapi.yaml"}) + Expect(cmd.Execute()).ShouldNot(HaveOccurred()) + out, err := io.ReadAll(cmdStdoutBuffer) + Expect(err).ShouldNot(HaveOccurred()) + + var kap kuadrantapiv1beta2.AuthPolicy + Expect(yaml.Unmarshal(out, &kap)).ShouldNot(HaveOccurred()) + Expect(kap.TypeMeta).To(Equal(metav1.TypeMeta{ + APIVersion: kuadrantapiv1beta2.GroupVersion.String(), Kind: "AuthPolicy", + })) + Expect(kap.ObjectMeta).To(Equal(metav1.ObjectMeta{ + Name: "petstore", + Namespace: "petstore-ns", + })) + Expect(kap.Spec.TargetRef).To(Equal(gatewayapiv1alpha2.PolicyTargetReference{ + Group: gatewayapiv1.GroupName, + Kind: gatewayapiv1.Kind("HTTPRoute"), + Name: gatewayapiv1.ObjectName("petstore"), + Namespace: ptr.To(gatewayapiv1.Namespace("petstore-ns")), + })) + Expect(kap.Spec.AuthPolicyCommonSpec.RouteSelectors).To(HaveExactElements( + kuadrantapiv1beta2.RouteSelector{ + Matches: []gatewayapiv1.HTTPRouteMatch{ + { + Path: &gatewayapiv1.HTTPPathMatch{ + Type: ptr.To(gatewayapiv1.PathMatchExact), + Value: ptr.To("/v1/dog"), + }, + Method: ptr.To(gatewayapiv1.HTTPMethodPost), + }, + }, + }, + )) + Expect(kap.Spec.AuthPolicyCommonSpec.AuthScheme).To(Equal( + &kuadrantapiv1beta2.AuthSchemeSpec{ + Authentication: map[string]kuadrantapiv1beta2.AuthenticationSpec{ + "postDog_securedDog": kuadrantapiv1beta2.AuthenticationSpec{ + AuthenticationSpec: authorinoapi.AuthenticationSpec{ + Credentials: authorinoapi.Credentials{}, + AuthenticationMethodSpec: authorinoapi.AuthenticationMethodSpec{ + Jwt: &authorinoapi.JwtAuthenticationSpec{ + IssuerUrl: "https://example.com/.well-known/openid-configuration", + }, + }, + }, + CommonAuthRuleSpec: kuadrantapiv1beta2.CommonAuthRuleSpec{ + RouteSelectors: []kuadrantapiv1beta2.RouteSelector{ + { + Matches: []gatewayapiv1.HTTPRouteMatch{ + { + Path: &gatewayapiv1.HTTPPathMatch{ + Type: ptr.To(gatewayapiv1.PathMatchExact), + Value: ptr.To("/v1/dog"), + }, + Method: ptr.To(gatewayapiv1.HTTPMethodPost), + }, + }, + }, + }, + }, + }, + }, + }, + )) + }) + }) +}) diff --git a/cmd/generate_kuadrant_ratelimitpolicy_test.go b/cmd/generate_kuadrant_ratelimitpolicy_test.go new file mode 100644 index 0000000..ae71f55 --- /dev/null +++ b/cmd/generate_kuadrant_ratelimitpolicy_test.go @@ -0,0 +1,117 @@ +package cmd + +import ( + "bytes" + "io" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" + gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/yaml" + + kuadrantapiv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" +) + +var _ = Describe("Generate Ratelimitpolicy", func() { + var ( + cmd *cobra.Command + cmdStdoutBuffer *bytes.Buffer + cmdStderrBuffer *bytes.Buffer + ) + + BeforeEach(func() { + cmd = generateKuadrantRateLimitPolicyCommand() + cmdStdoutBuffer = bytes.NewBufferString("") + cmdStderrBuffer = bytes.NewBufferString("") + cmd.SetOut(cmdStdoutBuffer) + cmd.SetErr(cmdStderrBuffer) + }) + + Context("with invalid OAS", func() { + It("happy path", func() { + cmd.SetArgs([]string{"--oas", "testdata/invalid_oas.yaml"}) + Expect(cmd.Execute()).Should(MatchError(ContainSubstring("OpenAPI validation error"))) + + }) + }) + + Context("with rate limiting kuadrant extensions", func() { + It("rate limit policy generated", func() { + cmd.SetArgs([]string{"--oas", "testdata/petstore_openapi.yaml"}) + Expect(cmd.Execute()).ShouldNot(HaveOccurred()) + out, err := io.ReadAll(cmdStdoutBuffer) + Expect(err).ShouldNot(HaveOccurred()) + + var rlp kuadrantapiv1beta2.RateLimitPolicy + Expect(yaml.Unmarshal(out, &rlp)).ShouldNot(HaveOccurred()) + Expect(rlp.TypeMeta).To(Equal(metav1.TypeMeta{ + APIVersion: kuadrantapiv1beta2.GroupVersion.String(), Kind: "RateLimitPolicy", + })) + Expect(rlp.ObjectMeta).To(Equal(metav1.ObjectMeta{ + Name: "petstore", + Namespace: "petstore-ns", + })) + Expect(rlp.Spec.TargetRef).To(Equal(gatewayapiv1alpha2.PolicyTargetReference{ + Group: gatewayapiv1.GroupName, + Kind: gatewayapiv1.Kind("HTTPRoute"), + Name: gatewayapiv1.ObjectName("petstore"), + Namespace: ptr.To(gatewayapiv1.Namespace("petstore-ns")), + })) + Expect(rlp.Spec.RateLimitPolicyCommonSpec.Limits).To(HaveLen(2)) + Expect(rlp.Spec.RateLimitPolicyCommonSpec.Limits).To(HaveKeyWithValue("getCat", kuadrantapiv1beta2.Limit{ + Counters: []kuadrantapiv1beta2.ContextSelector{ + "request.headers.x-forwarded-for", + }, + RouteSelectors: []kuadrantapiv1beta2.RouteSelector{ + { + Matches: []gatewayapiv1.HTTPRouteMatch{ + { + Path: &gatewayapiv1.HTTPPathMatch{ + Type: ptr.To(gatewayapiv1.PathMatchExact), + Value: ptr.To("/v1/cat"), + }, + Method: ptr.To(gatewayapiv1.HTTPMethodGet), + }, + }, + }, + }, + Rates: []kuadrantapiv1beta2.Rate{ + { + Limit: 1, + Duration: 10, + Unit: kuadrantapiv1beta2.TimeUnit("second"), + }, + }, + })) + Expect(rlp.Spec.RateLimitPolicyCommonSpec.Limits).To(HaveKeyWithValue("getDog", kuadrantapiv1beta2.Limit{ + Counters: []kuadrantapiv1beta2.ContextSelector{ + "request.headers.x-forwarded-for", + }, + RouteSelectors: []kuadrantapiv1beta2.RouteSelector{ + { + Matches: []gatewayapiv1.HTTPRouteMatch{ + { + Path: &gatewayapiv1.HTTPPathMatch{ + Type: ptr.To(gatewayapiv1.PathMatchExact), + Value: ptr.To("/v1/dog"), + }, + Method: ptr.To(gatewayapiv1.HTTPMethodGet), + }, + }, + }, + }, + Rates: []kuadrantapiv1beta2.Rate{ + { + Limit: 3, + Duration: 10, + Unit: kuadrantapiv1beta2.TimeUnit("second"), + }, + }, + })) + }) + }) +}) diff --git a/cmd/testdata/petstore_openapi.yaml b/cmd/testdata/petstore_openapi.yaml new file mode 100644 index 0000000..232966b --- /dev/null +++ b/cmd/testdata/petstore_openapi.yaml @@ -0,0 +1,77 @@ +--- +openapi: "3.0.3" +info: + title: "Pet Store API" + version: "1.0.0" +x-kuadrant: + route: + name: "petstore" + namespace: "petstore-ns" + hostnames: + - example.com + parentRefs: + - name: gw + namespace: gw-ns +servers: + - url: https://example.io/v1 +paths: + /cat: + x-kuadrant: ## Path level Kuadrant Extension + backendRefs: + - name: petstore + port: 80 + namespace: petstore + rate_limit: + rates: + - limit: 1 + duration: 10 + unit: second + counters: + - request.headers.x-forwarded-for + get: # Added to the route and rate limited + operationId: "getCat" + responses: + 405: + description: "invalid input" + post: # NOT added to the route + x-kuadrant: + disable: true + operationId: "postCat" + responses: + 405: + description: "invalid input" + /dog: + get: # Added to the route and rate limited + x-kuadrant: ## Operation level Kuadrant Extension + backendRefs: + - name: petstore + port: 80 + namespace: petstore + rate_limit: + rates: + - limit: 3 + duration: 10 + unit: second + counters: + - request.headers.x-forwarded-for + operationId: "getDog" + responses: + 405: + description: "invalid input" + post: # Added to the route, NOT rate limited, secured + x-kuadrant: ## Operation level Kuadrant Extension + backendRefs: + - name: petstore + port: 80 + namespace: petstore + operationId: "postDog" + security: + - securedDog: [] + responses: + 405: + description: "invalid input" +components: + securitySchemes: + securedDog: + type: openIdConnect + openIdConnectUrl: https://example.com/.well-known/openid-configuration diff --git a/doc/generate-kuadrant-auth-policy.md b/doc/generate-kuadrant-auth-policy.md index 587aa14..6cfeac0 100644 --- a/doc/generate-kuadrant-auth-policy.md +++ b/doc/generate-kuadrant-auth-policy.md @@ -239,15 +239,15 @@ openapi: "3.1.0" info: title: "Pet Store API" version: "1.0.0" - x-kuadrant: - route: - name: "petstore" - namespace: "petstore" - hostnames: - - example.com - parentRefs: - - name: istio-ingressgateway - namespace: istio-system +x-kuadrant: + route: + name: "petstore" + namespace: "petstore" + hostnames: + - example.com + parentRefs: + - name: istio-ingressgateway + namespace: istio-system servers: - url: https://example.io/api/v1 paths: diff --git a/doc/generate-kuadrant-rate-limit-policy.md b/doc/generate-kuadrant-rate-limit-policy.md index 0d732bd..05b0377 100644 --- a/doc/generate-kuadrant-rate-limit-policy.md +++ b/doc/generate-kuadrant-rate-limit-policy.md @@ -62,15 +62,15 @@ openapi: "3.0.3" info: title: "Pet Store API" version: "1.0.0" - x-kuadrant: - route: - name: "petstore" - namespace: "petstore" - hostnames: - - example.com - parentRefs: - - name: istio-ingressgateway - namespace: istio-system +x-kuadrant: + route: + name: "petstore" + namespace: "petstore" + hostnames: + - example.com + parentRefs: + - name: istio-ingressgateway + namespace: istio-system servers: - url: https://example.io/v1 paths: diff --git a/doc/openapi-apicurio.md b/doc/openapi-apicurio.md index 5558ad7..b2aa3fd 100644 --- a/doc/openapi-apicurio.md +++ b/doc/openapi-apicurio.md @@ -23,17 +23,16 @@ The following configuration and extension points are supported by Apicurio Studi To generate an [HTTPRoute](https://gateway-api.sigs.k8s.io/api-types/httproute/) for the API, add the following `x-kuadrant` block to your API definition in Apicurio Studio, replacing values to match your API details and the location of your Gateway: ```yaml -info: - x-kuadrant: - route: - name: petstore - namespace: petstore - hostnames: - - 'petstore.example.com' - parentRefs: - - name: prod-web - namespace: kuadrant-multi-cluster-gateways - kind: Gateway +x-kuadrant: + route: + name: petstore + namespace: petstore + hostnames: + - 'petstore.example.com' + parentRefs: + - name: prod-web + namespace: kuadrant-multi-cluster-gateways + kind: Gateway ``` For more details, see [Generate Gateway API HTTPRoute object from OpenAPI 3](./generate-gateway-api-httproute.md). diff --git a/doc/openapi-kuadrant-extensions.md b/doc/openapi-kuadrant-extensions.md index cc8b763..cd15a81 100644 --- a/doc/openapi-kuadrant-extensions.md +++ b/doc/openapi-kuadrant-extensions.md @@ -7,18 +7,17 @@ This reference information shows examples of how to add Kuadrant extensions at t You can add a Kuadrant extension at the `info` level of an OpenAPI definition. The following example shows an extension added for a `petstore` app: ```yaml -info: - x-kuadrant: ## Info-level Kuadrant extension - route: ## HTTPRoute metadata - name: "petstore" - namespace: "petstore" - labels: ## map[string]string - deployment: petstore - hostnames: ## []gateway.networking.k8s.io/v1beta1.Hostname - - example.com - parentRefs: ## []gateway.networking.k8s.io/v1beta1.ParentReference - - name: apiGateway - namespace: gateways +x-kuadrant: + route: ## HTTPRoute metadata + name: "petstore" + namespace: "petstore" + labels: ## map[string]string + deployment: petstore + hostnames: ## []gateway.networking.k8s.io/v1beta1.Hostname + - example.com + parentRefs: ## []gateway.networking.k8s.io/v1beta1.ParentReference + - name: apiGateway + namespace: gateways ``` ## Path-level Kuadrant extension diff --git a/doc/openapi-openshift-dev-spaces.md b/doc/openapi-openshift-dev-spaces.md index 8f48dd5..cf51fc8 100644 --- a/doc/openapi-openshift-dev-spaces.md +++ b/doc/openapi-openshift-dev-spaces.md @@ -69,21 +69,20 @@ In this tutorial, you will add Kuadrant policies to your API definition as follo #### Defining a Gateway -Use the `x-kuadrant` extension in the `info` block to specify a `Gateway`. This information will be used to generate `HTTPRoute`s at the path level. For example: +Use the `x-kuadrant` extension in the root level to specify a `Gateway`. This information will be used to generate `HTTPRoute`s at the path level. For example: ```yaml -info: - x-kuadrant: - route: ## HTTPRoute metadata - name: "petstore" - namespace: "petstore" - labels: ## map[string]string - deployment: petstore - hostnames: ## []gateway.networking.k8s.io/v1beta1.Hostname - - example.com - parentRefs: ## []gateway.networking.k8s.io/v1beta1.ParentReference - - name: apiGateway - namespace: gateways +x-kuadrant: + route: ## HTTPRoute metadata + name: "petstore" + namespace: "petstore" + labels: ## map[string]string + deployment: petstore + hostnames: ## []gateway.networking.k8s.io/v1beta1.Hostname + - example.com + parentRefs: ## []gateway.networking.k8s.io/v1beta1.ParentReference + - name: apiGateway + namespace: gateways ``` #### Specifying HTTPRoutes for each path diff --git a/examples/oas3/petstore-multiple-sec-requirements.yaml b/examples/oas3/petstore-multiple-sec-requirements.yaml index 91b2184..a7b6c0c 100644 --- a/examples/oas3/petstore-multiple-sec-requirements.yaml +++ b/examples/oas3/petstore-multiple-sec-requirements.yaml @@ -3,15 +3,15 @@ openapi: "3.1.0" info: title: "Pet Store API" version: "1.0.0" - x-kuadrant: - route: - name: "petstore" - namespace: "petstore" - hostnames: - - example.com - parentRefs: - - name: istio-ingressgateway - namespace: istio-system +x-kuadrant: + route: + name: "petstore" + namespace: "petstore" + hostnames: + - example.com + parentRefs: + - name: istio-ingressgateway + namespace: istio-system servers: - url: https://toplevel.example.io/v1 paths: diff --git a/examples/oas3/petstore-with-oidc-kuadrant-extensions.yaml b/examples/oas3/petstore-with-oidc-kuadrant-extensions.yaml index cdcc0b8..b81d8bc 100644 --- a/examples/oas3/petstore-with-oidc-kuadrant-extensions.yaml +++ b/examples/oas3/petstore-with-oidc-kuadrant-extensions.yaml @@ -3,15 +3,15 @@ openapi: "3.0.3" info: title: "Pet Store API" version: "1.0.0" - x-kuadrant: - route: - name: "petstore" - namespace: "petstore" - hostnames: - - example.com - parentRefs: - - name: istio-ingressgateway - namespace: istio-system +x-kuadrant: + route: + name: "petstore" + namespace: "petstore" + hostnames: + - example.com + parentRefs: + - name: istio-ingressgateway + namespace: istio-system servers: - url: https://example.io/api/v1 paths: diff --git a/examples/oas3/petstore-with-rate-limit-kuadrant-extensions.yaml b/examples/oas3/petstore-with-rate-limit-kuadrant-extensions.yaml index f6e5548..0c1d6b5 100644 --- a/examples/oas3/petstore-with-rate-limit-kuadrant-extensions.yaml +++ b/examples/oas3/petstore-with-rate-limit-kuadrant-extensions.yaml @@ -3,15 +3,15 @@ openapi: "3.0.3" info: title: "Pet Store API" version: "1.0.0" - x-kuadrant: - route: - name: "petstore" - namespace: "petstore" - hostnames: - - example.com - parentRefs: - - name: istio-ingressgateway - namespace: istio-system +x-kuadrant: + route: + name: "petstore" + namespace: "petstore" + hostnames: + - example.com + parentRefs: + - name: istio-ingressgateway + namespace: istio-system servers: - url: https://example.io/api/v1 paths: diff --git a/pkg/gatewayapi/http_route.go b/pkg/gatewayapi/http_route.go index 4217bbd..2868e0a 100644 --- a/pkg/gatewayapi/http_route.go +++ b/pkg/gatewayapi/http_route.go @@ -10,80 +10,67 @@ import ( ) func HTTPRouteObjectMetaFromOAS(doc *openapi3.T) metav1.ObjectMeta { - if doc.Info == nil { - return metav1.ObjectMeta{} - } - - kuadrantInfoExtension, err := utils.NewKuadrantOASInfoExtension(doc.Info) + kuadrantRootExtension, err := utils.NewKuadrantOASRootExtension(doc) if err != nil { panic(err) } - if kuadrantInfoExtension == nil { + if kuadrantRootExtension == nil { return metav1.ObjectMeta{} } - if kuadrantInfoExtension.Route == nil { - panic("info kuadrant extension route not found") + if kuadrantRootExtension.Route == nil { + panic("openapi root kuadrant extension route not found") } - if kuadrantInfoExtension.Route.Name == nil { - panic("info kuadrant extension route name not found") + if kuadrantRootExtension.Route.Name == nil { + panic("openapi root kuadrant extension route name not found") } om := metav1.ObjectMeta{ - Name: *kuadrantInfoExtension.Route.Name, - Labels: kuadrantInfoExtension.Route.Labels, + Name: *kuadrantRootExtension.Route.Name, + Labels: kuadrantRootExtension.Route.Labels, } - if kuadrantInfoExtension.Route.Namespace != nil { - om.Namespace = *kuadrantInfoExtension.Route.Namespace + if kuadrantRootExtension.Route.Namespace != nil { + om.Namespace = *kuadrantRootExtension.Route.Namespace } return om } func HTTPRouteGatewayParentRefsFromOAS(doc *openapi3.T) []gatewayapiv1.ParentReference { - if doc.Info == nil { - return nil - } - - kuadrantInfoExtension, err := utils.NewKuadrantOASInfoExtension(doc.Info) - + kuadrantRootExtension, err := utils.NewKuadrantOASRootExtension(doc) if err != nil { panic(err) } - if kuadrantInfoExtension == nil { + if kuadrantRootExtension == nil { return nil } - if kuadrantInfoExtension.Route == nil { - panic("info kuadrant extension route not found") + if kuadrantRootExtension.Route == nil { + panic("openapi root kuadrant extension route not found") } - return kuadrantInfoExtension.Route.ParentRefs + return kuadrantRootExtension.Route.ParentRefs } func HTTPRouteHostnamesFromOAS(doc *openapi3.T) []gatewayapiv1.Hostname { - if doc.Info == nil { - return nil - } - - kuadrantInfoExtension, err := utils.NewKuadrantOASInfoExtension(doc.Info) + kuadrantRootExtension, err := utils.NewKuadrantOASRootExtension(doc) if err != nil { panic(err) } - if kuadrantInfoExtension == nil { + if kuadrantRootExtension == nil { return nil } - if kuadrantInfoExtension.Route == nil { - panic("info kuadrant extension route not found") + if kuadrantRootExtension.Route == nil { + panic("openapi root kuadrant extension route not found") } - return kuadrantInfoExtension.Route.Hostnames + return kuadrantRootExtension.Route.Hostnames } func HTTPRouteRulesFromOAS(doc *openapi3.T) []gatewayapiv1.HTTPRouteRule { diff --git a/pkg/utils/kuadrant_oas_extension_types.go b/pkg/utils/kuadrant_oas_extension_types.go index 1816313..8d99028 100644 --- a/pkg/utils/kuadrant_oas_extension_types.go +++ b/pkg/utils/kuadrant_oas_extension_types.go @@ -4,9 +4,10 @@ import ( "encoding/json" "github.com/getkin/kin-openapi/openapi3" - kuadrantapiv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" "k8s.io/utils/ptr" gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" + + kuadrantapiv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" ) type RouteObject struct { @@ -17,22 +18,22 @@ type RouteObject struct { Labels map[string]string `json:"labels,omitempty"` } -type KuadrantOASInfoExtension struct { +type KuadrantOASRootExtension struct { Route *RouteObject `json:"route,omitempty"` } -func NewKuadrantOASInfoExtension(info *openapi3.Info) (*KuadrantOASInfoExtension, error) { - type KuadrantOASInfoObject struct { +func NewKuadrantOASRootExtension(doc *openapi3.T) (*KuadrantOASRootExtension, error) { + type KuadrantOASRootObject struct { // Kuadrant extension - Kuadrant *KuadrantOASInfoExtension `json:"x-kuadrant,omitempty"` + Kuadrant *KuadrantOASRootExtension `json:"x-kuadrant,omitempty"` } - data, err := info.MarshalJSON() + data, err := doc.MarshalJSON() if err != nil { return nil, err } - var x KuadrantOASInfoObject + var x KuadrantOASRootObject if err := json.Unmarshal(data, &x); err != nil { return nil, err }