Skip to content
This repository has been archived by the owner on Nov 8, 2022. It is now read-only.

Commit

Permalink
apiproduct: refactor api selectors
Browse files Browse the repository at this point in the history
  • Loading branch information
eguzki committed Oct 14, 2021
1 parent b4c1fcb commit 7bc3213
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 69 deletions.
34 changes: 21 additions & 13 deletions apis/networking/v1beta1/apiproduct_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,22 @@ type SecurityScheme struct {
OpenIDConnectAuth *OpenIDConnectAuth `json:"openIDConnectAuth,omitempty"`
}

type Mapping struct {
Prefix string `json:"prefix"`
}
type APIReference struct {
// Kuadrant API object name
Name string `json:"name"`

type APISelector struct {
Name string `json:"name"`
// Kuadrant API object namespace
Namespace string `json:"namespace"`

// +optional
Tag *string `json:"tag,omitempty"`

Mapping Mapping `json:"mapping,omitempty"`
// Public prefix path to be added to all paths exposed by the API
// +optional
Prefix *string `json:"prefix,omitempty"`
}

func (a *APISelector) APINamespacedName() types.NamespacedName {
func (a *APIReference) APINamespacedName() types.NamespacedName {
name := a.Name
if a.Tag != nil {
name = APIObjectName(a.Name, *a.Tag)
Expand Down Expand Up @@ -109,7 +110,10 @@ type APIProductSpec struct {
// derived based on the underlying platform.
Hosts []string `json:"hosts"`
SecurityScheme []*SecurityScheme `json:"securityScheme"`
APIs []*APISelector `json:"APIs"`

// The list of kuadrant API to be protected
// +kubebuilder:validation:MinItems=1
APIs []APIReference `json:"APIs"`

// RateLimit configures global rate limit parameters
// +optional
Expand Down Expand Up @@ -169,14 +173,18 @@ func (a *APIProduct) Validate() error {

// Look for duplicated mapping prefixes
mappingPrefix := map[string]interface{}{}
for idx, apiSel := range a.Spec.APIs {
apiField := apisFldPath.Index(idx)
for idx := range a.Spec.APIs {
apiRef := &a.Spec.APIs[idx]
if apiRef.Prefix == nil {
continue
}

if _, ok := mappingPrefix[apiSel.Mapping.Prefix]; ok {
fieldErrors = append(fieldErrors, field.Invalid(apiField, apiSel.APINamespacedName(), "duplicated prefix"))
apiField := apisFldPath.Index(idx)
if _, ok := mappingPrefix[*apiRef.Prefix]; ok {
fieldErrors = append(fieldErrors, field.Invalid(apiField, apiRef.APINamespacedName(), "duplicated prefix"))
}

mappingPrefix[apiSel.Mapping.Prefix] = nil
mappingPrefix[*apiRef.Prefix] = nil
}

if len(fieldErrors) > 0 {
Expand Down
37 changes: 11 additions & 26 deletions apis/networking/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 8 additions & 7 deletions config/crd/bases/networking.kuadrant.io_apiproducts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,26 @@ spec:
description: APIProductSpec defines the desired state of APIProduct
properties:
APIs:
description: The list of kuadrant API to be protected
items:
properties:
mapping:
properties:
prefix:
type: string
required:
- prefix
type: object
name:
description: Kuadrant API object name
type: string
namespace:
description: Kuadrant API object namespace
type: string
prefix:
description: Public prefix path to be added to all paths exposed
by the API
type: string
tag:
type: string
required:
- name
- namespace
type: object
minItems: 1
type: array
hosts:
description: The destination hosts to which traffic is being sent.
Expand Down
12 changes: 5 additions & 7 deletions controllers/apiproduct_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ var _ = Describe("APIPRoduct controller", func() {

func apiProduct(ns string) *networkingv1beta1.APIProduct {
tag := "production"
catsPrefix := "/cats"
dogsPrefix := "/dogs"
return &networkingv1beta1.APIProduct{
TypeMeta: metav1.TypeMeta{
Kind: networkingv1beta1.APIProductKind,
Expand All @@ -190,22 +192,18 @@ func apiProduct(ns string) *networkingv1beta1.APIProduct {
ObjectMeta: metav1.ObjectMeta{Name: "apiproduct01", Namespace: ns},
Spec: networkingv1beta1.APIProductSpec{
Hosts: []string{"petstore.127.0.0.1.nip.io"},
APIs: []*networkingv1beta1.APISelector{
APIs: []networkingv1beta1.APIReference{
{
Name: "cats",
Namespace: ns,
Tag: &tag,
Mapping: networkingv1beta1.Mapping{
Prefix: "/cats",
},
Prefix: &catsPrefix,
},
{
Name: "dogs",
Namespace: ns,
Tag: &tag,
Mapping: networkingv1beta1.Mapping{
Prefix: "/dogs",
},
Prefix: &dogsPrefix,
},
},
SecurityScheme: []*networkingv1beta1.SecurityScheme{
Expand Down
12 changes: 6 additions & 6 deletions pkg/ingressproviders/istioprovider/http_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func stringMatch(path string, matchType PathMatchType) *v1alpha3.StringMatch {
}
}

func HTTPRoutesFromOAS(oasContent string, pathPrefix string, destination networkingv1beta1.Destination) ([]*v1alpha3.HTTPRoute, error) {
func HTTPRoutesFromOAS(oasContent string, pathPrefix *string, destination networkingv1beta1.Destination) ([]*v1alpha3.HTTPRoute, error) {
doc, err := openapi3.NewLoader().LoadFromData([]byte(oasContent))
if err != nil {
return nil, err
Expand Down Expand Up @@ -146,12 +146,12 @@ func HTTPRoutesFromOAS(oasContent string, pathPrefix string, destination network
}

// Handle Prefix Override.
if pathPrefix != "" {
if pathPrefix != nil {
// We need to rewrite the path, to match what the service expects, basically,
// removing the prefixOverride
factory.RewriteURI = &path
// If there's an Override, lets append it to the actual Operation Path.
factory.URIMatchPath = pathPrefix + path
factory.URIMatchPath = *pathPrefix + path
}

httpRoutes = append(httpRoutes, factory.HTTPRoute())
Expand All @@ -161,7 +161,7 @@ func HTTPRoutesFromOAS(oasContent string, pathPrefix string, destination network
return httpRoutes, nil
}

func HTTPRoutesFromPath(pathMatch *gatewayapiv1alpha1.HTTPPathMatch, pathPrefix string, destination networkingv1beta1.Destination) ([]*v1alpha3.HTTPRoute, error) {
func HTTPRoutesFromPath(pathMatch *gatewayapiv1alpha1.HTTPPathMatch, pathPrefix *string, destination networkingv1beta1.Destination) ([]*v1alpha3.HTTPRoute, error) {
if pathMatch == nil {
return nil, nil
}
Expand All @@ -186,12 +186,12 @@ func HTTPRoutesFromPath(pathMatch *gatewayapiv1alpha1.HTTPPathMatch, pathPrefix
}

// Handle Prefix Override.
if pathPrefix != "" {
if pathPrefix != nil {
// We need to rewrite the path, to match what the service expects, basically,
// removing the prefixOverride
factory.RewriteURI = pathMatch.Value
// If there's an Override, lets append it to the actual Operation Path.
factory.URIMatchPath = pathPrefix + *pathMatch.Value
factory.URIMatchPath = *pathPrefix + *pathMatch.Value
}

httpRoutes = append(httpRoutes, factory.HTTPRoute())
Expand Down
12 changes: 6 additions & 6 deletions pkg/ingressproviders/istioprovider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ func (is *IstioProvider) getAuthorizationPolicy(virtualService *istio.VirtualSer

func (is *IstioProvider) virtualServiceFromAPIProduct(ctx context.Context, apip *networkingv1beta1.APIProduct) (*istio.VirtualService, error) {
httpRoutes := []*v1alpha3.HTTPRoute{}
for _, apiSel := range apip.Spec.APIs {
apiHTTPRoutes, err := is.apiHTTPRoutes(ctx, apiSel)
for idx := range apip.Spec.APIs {
apiHTTPRoutes, err := is.apiHTTPRoutes(ctx, &apip.Spec.APIs[idx])
if err != nil {
return nil, err
}
Expand All @@ -191,18 +191,18 @@ func (is *IstioProvider) virtualServiceFromAPIProduct(ctx context.Context, apip
return factory.VirtualService(), nil
}

func (is *IstioProvider) apiHTTPRoutes(ctx context.Context, apiSel *networkingv1beta1.APISelector) ([]*v1alpha3.HTTPRoute, error) {
func (is *IstioProvider) apiHTTPRoutes(ctx context.Context, apiRef *networkingv1beta1.APIReference) ([]*v1alpha3.HTTPRoute, error) {
api := &networkingv1beta1.API{}
err := is.Client().Get(ctx, apiSel.APINamespacedName(), api)
err := is.Client().Get(ctx, apiRef.APINamespacedName(), api)
if err != nil {
return nil, err
}

if api.Spec.Mappings.OAS != nil {
return HTTPRoutesFromOAS(*api.Spec.Mappings.OAS, apiSel.Mapping.Prefix, api.Spec.Destination)
return HTTPRoutesFromOAS(*api.Spec.Mappings.OAS, apiRef.Prefix, api.Spec.Destination)
}

return HTTPRoutesFromPath(api.Spec.Mappings.HTTPPathMatch, apiSel.Mapping.Prefix, api.Spec.Destination)
return HTTPRoutesFromPath(api.Spec.Mappings.HTTPPathMatch, apiRef.Prefix, api.Spec.Destination)
}

func (is *IstioProvider) Status(ctx context.Context, apip *networkingv1beta1.APIProduct) (bool, error) {
Expand Down
7 changes: 3 additions & 4 deletions samples/apiproduct.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
---
apiVersion: networking.kuadrant.io/v1beta1
kind: APIProduct
metadata:
Expand All @@ -9,13 +10,11 @@ spec:
- name: dogs
namespace: default
tag: production
mapping:
prefix: /dogs
prefix: /dogs
- name: cats
namespace: default
tag: production
mapping:
prefix: /cats
prefix: /cats
securityScheme:
- name: MyAPIKey
apiKeyAuth:
Expand Down

0 comments on commit 7bc3213

Please sign in to comment.