Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kuadrant extension enhancements #47

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions cmd/generate_gatewayapi_httproute.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func runGenerateGatewayApiHttpRoute(cmd *cobra.Command, args []string) error {
}

func buildHTTPRoute(doc *openapi3.T) *gatewayapiv1beta1.HTTPRoute {
httpRoute := &gatewayapiv1beta1.HTTPRoute{
return &gatewayapiv1beta1.HTTPRoute{
TypeMeta: v1.TypeMeta{
APIVersion: "gateway.networking.k8s.io/v1beta1",
Kind: "HTTPRoute",
Expand All @@ -79,12 +79,4 @@ func buildHTTPRoute(doc *openapi3.T) *gatewayapiv1beta1.HTTPRoute {
Rules: gatewayapi.HTTPRouteRulesFromOAS(doc),
},
}

// Extract and set labels
labels, ok := gatewayapi.ExtractLabelsFromOAS(doc)
if ok {
httpRoute.ObjectMeta.Labels = labels
}

return httpRoute
}
8 changes: 6 additions & 2 deletions doc/openapi-kuadrant-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ info:
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
Expand All @@ -27,7 +29,8 @@ is the default when there is no operation level configuration.
paths:
/cat:
x-kuadrant: ## Path level Kuadrant Extension
enable: true ## Add to the HTTPRoute. Optional. Default: false
disable: true ## Remove from the HTTPRoute. Optional. Default: false
pathMatchType: Exact ## Specifies how to match against the path Value. Valid values: [Exact;PathPrefix]. Optional. Default: Exact
backendRefs: ## Backend references to be included in the HTTPRoute. []gateway.networking.k8s.io/v1beta1.HTTPBackendRef. Optional.
- name: petstore
port: 80
Expand Down Expand Up @@ -55,7 +58,8 @@ paths:
/cat:
get:
x-kuadrant: ## Path level Kuadrant Extension
enable: true ## Add to the HTTPRoute. Optional. Default: false
disable: true ## Remove from the HTTPRoute. Optional. Default: path level "disable" value
pathMatchType: Exact ## Specifies how to match against the path Value. Valid values: [Exact;PathPrefix]. Optional. Default: Exact
backendRefs: ## Backend references to be included in the HTTPRoute. Optional.
- name: petstore
port: 80
Expand Down
45 changes: 14 additions & 31 deletions pkg/gatewayapi/http_route.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package gatewayapi

import (
"fmt"

"github.com/getkin/kin-openapi/openapi3"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
Expand All @@ -29,7 +27,10 @@ func HTTPRouteObjectMetaFromOAS(doc *openapi3.T) metav1.ObjectMeta {
panic("info kuadrant extension route name not found")
}

om := metav1.ObjectMeta{Name: *kuadrantInfoExtension.Route.Name}
om := metav1.ObjectMeta{
Name: *kuadrantInfoExtension.Route.Name,
Labels: kuadrantInfoExtension.Route.Labels,
}

if kuadrantInfoExtension.Route.Namespace != nil {
om.Namespace = *kuadrantInfoExtension.Route.Namespace
Expand Down Expand Up @@ -89,16 +90,14 @@ func HTTPRouteRulesFromOAS(doc *openapi3.T) []gatewayapiv1beta1.HTTPRouteRule {
panic(err)
}

pathEnabled := kuadrantPathExtension.IsEnabled()

// Operations
for verb, operation := range pathItem.Operations() {
kuadrantOperationExtension, err := utils.NewKuadrantOASOperationExtension(operation)
if err != nil {
panic(err)
}

if !ptr.Deref(kuadrantOperationExtension.Enable, pathEnabled) {
if ptr.Deref(kuadrantOperationExtension.Disable, kuadrantPathExtension.IsDisabled()) {
// not enabled for the operation
continue
}
Expand All @@ -109,7 +108,13 @@ func HTTPRouteRulesFromOAS(doc *openapi3.T) []gatewayapiv1beta1.HTTPRouteRule {
backendRefs = kuadrantOperationExtension.BackendRefs
}

rules = append(rules, buildHTTPRouteRule(basePath, path, pathItem, verb, operation, backendRefs))
// default pathMatchType at the path level
pathMatchType := ptr.Deref(
kuadrantOperationExtension.PathMatchType,
kuadrantPathExtension.GetPathMatchType(),
)

rules = append(rules, buildHTTPRouteRule(basePath, path, pathItem, verb, operation, backendRefs, pathMatchType))
}
}

Expand All @@ -120,30 +125,8 @@ func HTTPRouteRulesFromOAS(doc *openapi3.T) []gatewayapiv1beta1.HTTPRouteRule {
return rules
}

func ExtractLabelsFromOAS(doc *openapi3.T) (map[string]string, bool) {
if doc.Info == nil || doc.Info.Extensions == nil {
return nil, false
}

if extension, ok := doc.Info.Extensions["x-kuadrant"]; ok {
if extensionMap, ok := extension.(map[string]interface{}); ok {
if route, ok := extensionMap["route"].(map[string]interface{}); ok {
if labelsInterface, ok := route["labels"]; ok {
labels := make(map[string]string)
for key, value := range labelsInterface.(map[string]interface{}) {
labels[key] = fmt.Sprint(value)
}
return labels, true
}
}
}
}

return nil, false
}

func buildHTTPRouteRule(basePath, path string, pathItem *openapi3.PathItem, verb string, op *openapi3.Operation, backendRefs []gatewayapiv1beta1.HTTPBackendRef) gatewayapiv1beta1.HTTPRouteRule {
match := utils.OpenAPIMatcherFromOASOperations(basePath, path, pathItem, verb, op)
func buildHTTPRouteRule(basePath, path string, pathItem *openapi3.PathItem, verb string, op *openapi3.Operation, backendRefs []gatewayapiv1beta1.HTTPBackendRef, pathMatchType gatewayapiv1beta1.PathMatchType) gatewayapiv1beta1.HTTPRouteRule {
match := utils.OpenAPIMatcherFromOASOperations(basePath, path, pathItem, verb, op, pathMatchType)

return gatewayapiv1beta1.HTTPRouteRule{
BackendRefs: backendRefs,
Expand Down
16 changes: 10 additions & 6 deletions pkg/kuadrantapi/rate_limit_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,14 @@ func RateLimitPolicyLimitsFromOAS(doc *openapi3.T) map[string]kuadrantapiv1beta2
panic(err)
}

pathEnabled := kuadrantPathExtension.IsEnabled()

// Operations
for verb, operation := range pathItem.Operations() {
kuadrantOperationExtension, err := utils.NewKuadrantOASOperationExtension(operation)
if err != nil {
panic(err)
}

if !ptr.Deref(kuadrantOperationExtension.Enable, pathEnabled) {
if ptr.Deref(kuadrantOperationExtension.Disable, kuadrantPathExtension.IsDisabled()) {
// not enabled for the operation
//fmt.Printf("OUT not enabled: path: %s, method: %s\n", path, verb)
continue
Expand All @@ -60,10 +58,16 @@ func RateLimitPolicyLimitsFromOAS(doc *openapi3.T) map[string]kuadrantapiv1beta2
continue
}

// default pathMatchType at the path level
pathMatchType := ptr.Deref(
kuadrantOperationExtension.PathMatchType,
kuadrantPathExtension.GetPathMatchType(),
)

limitName := utils.OpenAPIOperationName(path, verb, operation)

limits[limitName] = kuadrantapiv1beta2.Limit{
RouteSelectors: buildLimitRouteSelectors(basePath, path, pathItem, verb, operation),
RouteSelectors: buildLimitRouteSelectors(basePath, path, pathItem, verb, operation, pathMatchType),
When: rateLimit.When,
Counters: rateLimit.Counters,
Rates: rateLimit.Rates,
Expand All @@ -78,8 +82,8 @@ func RateLimitPolicyLimitsFromOAS(doc *openapi3.T) map[string]kuadrantapiv1beta2
return limits
}

func buildLimitRouteSelectors(basePath, path string, pathItem *openapi3.PathItem, verb string, op *openapi3.Operation) []kuadrantapiv1beta2.RouteSelector {
match := utils.OpenAPIMatcherFromOASOperations(basePath, path, pathItem, verb, op)
func buildLimitRouteSelectors(basePath, path string, pathItem *openapi3.PathItem, verb string, op *openapi3.Operation, pathMatchType gatewayapiv1beta1.PathMatchType) []kuadrantapiv1beta2.RouteSelector {
match := utils.OpenAPIMatcherFromOASOperations(basePath, path, pathItem, verb, op, pathMatchType)

return []kuadrantapiv1beta2.RouteSelector{
{
Expand Down
17 changes: 12 additions & 5 deletions pkg/utils/kuadrant_oas_extension_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type RouteObject struct {
Namespace *string `json:"namespace,omitempty"`
Hostnames []gatewayapiv1beta1.Hostname `json:"hostnames,omitempty"`
ParentRefs []gatewayapiv1beta1.ParentReference `json:"parentRefs,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
}

type KuadrantOASInfoExtension struct {
Expand Down Expand Up @@ -48,14 +49,20 @@ type KuadrantRateLimitExtension struct {
}

type KuadrantOASPathExtension struct {
Enable *bool `json:"enable,omitempty"`
BackendRefs []gatewayapiv1beta1.HTTPBackendRef `json:"backendRefs,omitempty"`
RateLimit *KuadrantRateLimitExtension `json:"rate_limit,omitempty"`
Disable *bool `json:"disable,omitempty"`
PathMatchType *gatewayapiv1beta1.PathMatchType `json:"pathMatchType,omitempty"`
BackendRefs []gatewayapiv1beta1.HTTPBackendRef `json:"backendRefs,omitempty"`
RateLimit *KuadrantRateLimitExtension `json:"rate_limit,omitempty"`
}

func (k *KuadrantOASPathExtension) IsEnabled() bool {
func (k *KuadrantOASPathExtension) IsDisabled() bool {
// Set default
return ptr.Deref(k.Enable, false)
return ptr.Deref(k.Disable, false)
}

func (k *KuadrantOASPathExtension) GetPathMatchType() gatewayapiv1beta1.PathMatchType {
// Set default
return ptr.Deref(k.PathMatchType, gatewayapiv1beta1.PathMatchExact)
}

func NewKuadrantOASPathExtension(pathItem *openapi3.PathItem) (*KuadrantOASPathExtension, error) {
Expand Down
6 changes: 2 additions & 4 deletions pkg/utils/oas_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ func BasePathFromOpenAPI(obj *openapi3.T) (string, error) {
return serverURL.Path, nil
}

func OpenAPIMatcherFromOASOperations(basePath, path string, pathItem *openapi3.PathItem, verb string, op *openapi3.Operation) gatewayapiv1beta1.HTTPRouteMatch {

func OpenAPIMatcherFromOASOperations(basePath, path string, pathItem *openapi3.PathItem, verb string, op *openapi3.Operation, pathMatchType gatewayapiv1beta1.PathMatchType) gatewayapiv1beta1.HTTPRouteMatch {
// remove the last slash of the Base Path
sanitizedBasePath := LastSlashRegexp.ReplaceAllString(basePath, "")

Expand Down Expand Up @@ -126,8 +125,7 @@ func OpenAPIMatcherFromOASOperations(basePath, path string, pathItem *openapi3.P
return gatewayapiv1beta1.HTTPRouteMatch{
Method: &[]gatewayapiv1beta1.HTTPMethod{gatewayapiv1beta1.HTTPMethod(verb)}[0],
Path: &gatewayapiv1beta1.HTTPPathMatch{
// TODO(eguzki): consider other path match types like PathPrefix
Type: &[]gatewayapiv1beta1.PathMatchType{gatewayapiv1beta1.PathMatchExact}[0],
Type: &pathMatchType,
Value: &[]string{matchPath}[0],
},
Headers: headersMatch,
Expand Down
Loading