Skip to content

Commit

Permalink
wasm types moved to a common package
Browse files Browse the repository at this point in the history
  • Loading branch information
eguzki authored and KevFan committed Aug 16, 2023
1 parent 773dddd commit 807e754
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 178 deletions.
33 changes: 17 additions & 16 deletions controllers/ratelimitpolicy_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2"
"github.com/kuadrant/kuadrant-operator/pkg/common"
"github.com/kuadrant/kuadrant-operator/pkg/rlptools"
"github.com/kuadrant/kuadrant-operator/pkg/rlptools/wasm"
limitadorv1alpha1 "github.com/kuadrant/limitador-operator/api/v1alpha1"
)

Expand Down Expand Up @@ -272,35 +273,35 @@ var _ = Describe("RateLimitPolicy controller", func() {
Expect(err).ToNot(HaveOccurred())
existingWASMConfig, err := rlptools.WASMPluginFromStruct(existingWasmPlugin.Spec.PluginConfig)
Expect(err).ToNot(HaveOccurred())
Expect(existingWASMConfig).To(Equal(&rlptools.WASMPlugin{
FailureMode: rlptools.FailureModeDeny,
RateLimitPolicies: []rlptools.RateLimitPolicy{
Expect(existingWASMConfig).To(Equal(&wasm.WASMPlugin{
FailureMode: wasm.FailureModeDeny,
RateLimitPolicies: []wasm.RateLimitPolicy{
{
Name: "*.example.com",
Domain: common.MarshallNamespace(client.ObjectKeyFromObject(gateway), "*.example.com"),
Service: common.KuadrantRateLimitClusterName,
Hostnames: []string{"*.example.com"},
Rules: []rlptools.Rule{
Rules: []wasm.Rule{
{
Conditions: []rlptools.Condition{
Conditions: []wasm.Condition{
{
AllOf: []rlptools.PatternExpression{
AllOf: []wasm.PatternExpression{
{
Selector: "request.url_path",
Operator: rlptools.PatternOperator(kuadrantv1beta2.StartsWithOperator),
Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator),
Value: "/toy",
},
{
Selector: "request.method",
Operator: rlptools.PatternOperator(kuadrantv1beta2.EqualOperator),
Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator),
Value: "GET",
},
},
},
},
Data: []rlptools.DataItem{
Data: []wasm.DataItem{
{
Static: &rlptools.StaticSpec{
Static: &wasm.StaticSpec{
Key: fmt.Sprintf("%s/%s/l1", testNamespace, rlpName),
Value: "1",
},
Expand Down Expand Up @@ -400,20 +401,20 @@ var _ = Describe("RateLimitPolicy controller", func() {
Expect(err).ToNot(HaveOccurred())
existingWASMConfig, err := rlptools.WASMPluginFromStruct(existingWasmPlugin.Spec.PluginConfig)
Expect(err).ToNot(HaveOccurred())
Expect(existingWASMConfig).To(Equal(&rlptools.WASMPlugin{
FailureMode: rlptools.FailureModeDeny,
RateLimitPolicies: []rlptools.RateLimitPolicy{
Expect(existingWASMConfig).To(Equal(&wasm.WASMPlugin{
FailureMode: wasm.FailureModeDeny,
RateLimitPolicies: []wasm.RateLimitPolicy{
{
Name: "*",
Domain: common.MarshallNamespace(client.ObjectKeyFromObject(gateway), "*"),
Service: common.KuadrantRateLimitClusterName,
Hostnames: []string{"*"},
Rules: []rlptools.Rule{
Rules: []wasm.Rule{
{
Conditions: nil,
Data: []rlptools.DataItem{
Data: []wasm.DataItem{
{
Static: &rlptools.StaticSpec{
Static: &wasm.StaticSpec{
Key: fmt.Sprintf("%s/%s/l1", testNamespace, rlpName),
Value: "1",
},
Expand Down
13 changes: 7 additions & 6 deletions controllers/ratelimitpolicy_wasm_plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/kuadrant/kuadrant-operator/pkg/common"
"github.com/kuadrant/kuadrant-operator/pkg/reconcilers"
"github.com/kuadrant/kuadrant-operator/pkg/rlptools"
"github.com/kuadrant/kuadrant-operator/pkg/rlptools/wasm"
)

func (r *RateLimitPolicyReconciler) reconcileWASMPluginConf(ctx context.Context, rlp *kuadrantv1beta2.RateLimitPolicy, gwDiffObj *reconcilers.GatewayDiff) error {
Expand Down Expand Up @@ -120,7 +121,7 @@ func (r *RateLimitPolicyReconciler) gatewayWASMPlugin(ctx context.Context, gw co

// returns nil when there is no rate limit policy to apply
func (r *RateLimitPolicyReconciler) wasmPluginConfig(ctx context.Context,
gw common.GatewayWrapper, rlpRefs []client.ObjectKey) (*rlptools.WASMPlugin, error) {
gw common.GatewayWrapper, rlpRefs []client.ObjectKey) (*wasm.WASMPlugin, error) {
logger, _ := logr.FromContext(ctx)

routeRLPList := make([]*kuadrantv1beta2.RateLimitPolicy, 0)
Expand Down Expand Up @@ -171,14 +172,14 @@ func (r *RateLimitPolicyReconciler) wasmPluginConfig(ctx context.Context,
}
}

wasmPlugin := &rlptools.WASMPlugin{
FailureMode: rlptools.FailureModeDeny,
RateLimitPolicies: make([]rlptools.RateLimitPolicy, 0),
wasmPlugin := &wasm.WASMPlugin{
FailureMode: wasm.FailureModeDeny,
RateLimitPolicies: make([]wasm.RateLimitPolicy, 0),
}

// One RateLimitPolicy per domain
for domain, rules := range wasmRulesByDomain {
rateLimitPolicy := rlptools.RateLimitPolicy{
rateLimitPolicy := wasm.RateLimitPolicy{
Name: domain,
Domain: common.MarshallNamespace(gw.Key(), domain),
Service: common.KuadrantRateLimitClusterName,
Expand All @@ -192,7 +193,7 @@ func (r *RateLimitPolicyReconciler) wasmPluginConfig(ctx context.Context,
}

// merge operations currently implemented with list append operation
func mergeRules(routeRLP *kuadrantv1beta2.RateLimitPolicy, gwRLP *kuadrantv1beta2.RateLimitPolicy, route *gatewayapiv1beta1.HTTPRoute) []rlptools.Rule {
func mergeRules(routeRLP *kuadrantv1beta2.RateLimitPolicy, gwRLP *kuadrantv1beta2.RateLimitPolicy, route *gatewayapiv1beta1.HTTPRoute) []wasm.Rule {
routeRules := rlptools.WasmRules(routeRLP, route)

if gwRLP == nil {
Expand Down
124 changes: 124 additions & 0 deletions pkg/rlptools/wasm/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package wasm

import (
"encoding/json"

_struct "github.com/golang/protobuf/ptypes/struct"
gatewayapiv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"

kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2"
)

var (
PathMatchTypeMap = map[gatewayapiv1beta1.PathMatchType]PatternOperator{
gatewayapiv1beta1.PathMatchExact: PatternOperator(kuadrantv1beta2.EqualOperator),
gatewayapiv1beta1.PathMatchPathPrefix: PatternOperator(kuadrantv1beta2.StartsWithOperator),
gatewayapiv1beta1.PathMatchRegularExpression: PatternOperator(kuadrantv1beta2.MatchesOperator),
}
)

type SelectorSpec struct {
// Selector of an attribute from the contextual properties provided by Envoy
// during request and connection processing
// https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes
// They are named by a dot-separated path (e.g. request.path)
// Examples:
// "request.path" -> The path portion of the URL
Selector string `json:"selector"`

// If not set it defaults to `selector` field value as the descriptor key.
// +optional
Key *string `json:"key,omitempty"`

// An optional value to use if the selector is not found in the context.
// If not set and the selector is not found in the context, then no descriptor is generated.
// +optional
Default *string `json:"default,omitempty"`
}

type StaticSpec struct {
Value string `json:"value"`
Key string `json:"key"`
}

// TODO implement one of constraint
// Precisely one of "static", "selector" must be set.
type DataItem struct {
// +optional
Static *StaticSpec `json:"static,omitempty"`

// +optional
Selector *SelectorSpec `json:"selector,omitempty"`
}

type PatternOperator kuadrantv1beta2.WhenConditionOperator

type PatternExpression struct {
// Selector of an attribute from the contextual properties provided by Envoy
// during request and connection processing
// https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes
// They are named by a dot-separated path (e.g. request.path)
// Examples:
// "request.path" -> The path portion of the URL
Selector string `json:"selector"`

// The binary operator to be applied to the content fetched from context, for comparison with "value".
// Possible values are: "eq" (equal to), "neq" (not equal to), "incl" (includes; for arrays), "excl" (excludes; for arrays), "matches" (regex)
// TODO build comprehensive list of operators
Operator PatternOperator `json:"operator"`

// The value of reference for the comparison with the content fetched from the context.
Value string `json:"value"`
}

// Condition defines traffic matching rules
type Condition struct {
// All of the expressions defined must match to match this condition
// +optional
AllOf []PatternExpression `json:"allOf,omitempty"`
}

// Rule defines one rate limit configuration. When conditions are met,
// it uses `data` section to generate one RLS descriptor.
type Rule struct {
// +optional
Conditions []Condition `json:"conditions,omitempty"`
// +optional
Data []DataItem `json:"data,omitempty"`
}

type RateLimitPolicy struct {
Name string `json:"name"`
Domain string `json:"domain"`
Service string `json:"service"`
Hostnames []string `json:"hostnames"`

// +optional
Rules []Rule `json:"rules,omitempty"`
}

// +kubebuilder:validation:Enum:=deny;allow
type FailureModeType string

const (
FailureModeDeny FailureModeType = "deny"
FailureModeAllow FailureModeType = "allow"
)

type WASMPlugin struct {
FailureMode FailureModeType `json:"failureMode"`
RateLimitPolicies []RateLimitPolicy `json:"rateLimitPolicies"`
}

func (w *WASMPlugin) ToStruct() (*_struct.Struct, error) {
wasmPluginJSON, err := json.Marshal(w)
if err != nil {
return nil, err
}

pluginConfigStruct := &_struct.Struct{}
if err := pluginConfigStruct.UnmarshalJSON(wasmPluginJSON); err != nil {
return nil, err
}
return pluginConfigStruct, nil
}
Loading

0 comments on commit 807e754

Please sign in to comment.