Skip to content

Commit

Permalink
envoygateway: tests
Browse files Browse the repository at this point in the history
Signed-off-by: Eguzki Astiz Lezaun <eastizle@redhat.com>
  • Loading branch information
eguzki committed Sep 9, 2024
1 parent 300b48b commit 6fd4a90
Show file tree
Hide file tree
Showing 3 changed files with 366 additions and 0 deletions.
15 changes: 15 additions & 0 deletions tests/commons.go
Original file line number Diff line number Diff line change
Expand Up @@ -663,3 +663,18 @@ func BuildBasicAuthScheme() *kuadrantv1beta2.AuthSchemeSpec {
},
}
}

func IsRLPAcceptedAndEnforced(g Gomega, ctx context.Context, cl client.Client, policyKey client.ObjectKey) {
existingPolicy := &kuadrantv1beta2.RateLimitPolicy{}
g.Expect(cl.Get(ctx, policyKey, existingPolicy)).To(Succeed())

acceptedCond := meta.FindStatusCondition(existingPolicy.Status.Conditions, string(gatewayapiv1alpha2.PolicyConditionAccepted))
g.Expect(acceptedCond).ToNot(BeNil())
acceptedCondMatch := acceptedCond.Status == metav1.ConditionTrue && acceptedCond.Reason == string(gatewayapiv1alpha2.PolicyReasonAccepted)

enforcedCond := meta.FindStatusCondition(existingPolicy.Status.Conditions, string(kuadrant.PolicyReasonEnforced))
g.Expect(enforcedCond).ToNot(BeNil())
enforcedCondMatch := enforcedCond.Status == metav1.ConditionTrue && enforcedCond.Reason == string(gatewayapiv1alpha2.PolicyReasonAccepted)

g.Expect(acceptedCondMatch && enforcedCondMatch).To(BeTrue())
}
23 changes: 23 additions & 0 deletions tests/envoygateway/utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//go:build integration

package envoygateway_test

import (
"context"

egv1alpha1 "github.com/envoyproxy/gateway/api/v1alpha1"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/api/meta"
"sigs.k8s.io/controller-runtime/pkg/client"
gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
)

func IsEnvoyExtenstionPolicyAccepted(g Gomega, ctx context.Context, cl client.Client, key client.ObjectKey) {
policy := &egv1alpha1.EnvoyExtensionPolicy{}
g.Expect(cl.Get(ctx, key, policy)).To(Succeed())

acceptedCond := meta.FindStatusCondition(policy.Status.Conditions, string(gatewayapiv1alpha2.PolicyConditionAccepted))
g.Expect(acceptedCond).ToNot(BeNil())
g.Expect(acceptedCond.Status == metav1.ConditionTrue && acceptedCond.Reason == string(gatewayapiv1alpha2.PolicyReasonAccepted)).To(BeTrue())
}
328 changes: 328 additions & 0 deletions tests/envoygateway/wasm_controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
//go:build integration

package envoygateway_test

import (
"fmt"
"strings"
"time"

egv1alpha1 "github.com/envoyproxy/gateway/api/v1alpha1"
kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gstruct"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/rand"
"sigs.k8s.io/controller-runtime/pkg/client"
logf "sigs.k8s.io/controller-runtime/pkg/log"
gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1"

"github.com/kuadrant/kuadrant-operator/controllers"
"github.com/kuadrant/kuadrant-operator/pkg/common"
"github.com/kuadrant/kuadrant-operator/pkg/rlptools"
"github.com/kuadrant/kuadrant-operator/pkg/rlptools/wasm"
"github.com/kuadrant/kuadrant-operator/tests"
)

var _ = Describe("wasm controller", func() {
const (
testTimeOut = SpecTimeout(2 * time.Minute)
afterEachTimeOut = NodeTimeout(3 * time.Minute)
)
var (
testNamespace string
gwHost = fmt.Sprintf("*.toystore-%s.com", rand.String(4))
gateway *gatewayapiv1.Gateway
)

BeforeEach(func(ctx SpecContext) {
testNamespace = tests.CreateNamespace(ctx, testClient())
gateway = tests.NewGatewayBuilder(TestGatewayName, tests.GatewayClassName, testNamespace).
WithHTTPListener("test-listener", gwHost).
Gateway
err := testClient().Create(ctx, gateway)
Expect(err).ToNot(HaveOccurred())

Eventually(tests.GatewayIsReady(ctx, testClient(), gateway)).WithContext(ctx).Should(BeTrue())
})

AfterEach(func(ctx SpecContext) {
tests.DeleteNamespace(ctx, testClient(), testNamespace)
}, afterEachTimeOut)

policyFactory := func(mutateFns ...func(policy *kuadrantv1beta2.RateLimitPolicy)) *kuadrantv1beta2.RateLimitPolicy {
policy := &kuadrantv1beta2.RateLimitPolicy{
TypeMeta: metav1.TypeMeta{
Kind: "RateLimitPolicy",
APIVersion: kuadrantv1beta2.GroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: "rlp",
Namespace: testNamespace,
},
Spec: kuadrantv1beta2.RateLimitPolicySpec{},
}

for _, mutateFn := range mutateFns {
mutateFn(policy)
}

return policy
}

randomHostFromGWHost := func() string {
return strings.Replace(gwHost, "*", rand.String(4), 1)
}

Context("RateLimitPolicy attached to the gateway", func() {

var (
gwPolicy *kuadrantv1beta2.RateLimitPolicy
gwRoute *gatewayapiv1.HTTPRoute
)

BeforeEach(func(ctx SpecContext) {
gwRoute = tests.BuildBasicHttpRoute(TestHTTPRouteName, TestGatewayName, testNamespace, []string{randomHostFromGWHost()})
err := testClient().Create(ctx, gwRoute)
Expect(err).ToNot(HaveOccurred())
Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(gwRoute))).WithContext(ctx).Should(BeTrue())

gwPolicy = policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) {
policy.Name = "gw"
policy.Spec.TargetRef.Group = gatewayapiv1.GroupName
policy.Spec.TargetRef.Kind = "Gateway"
policy.Spec.TargetRef.Name = TestGatewayName
policy.Spec.Default = &kuadrantv1beta2.RateLimitPolicyCommonSpec{
Limits: map[string]kuadrantv1beta2.Limit{
"l1": {
Rates: []kuadrantv1beta2.Rate{
{
Limit: 1, Duration: 3, Unit: "minute",
},
},
},
},
}
})

err = testClient().Create(ctx, gwPolicy)
logf.Log.V(1).Info("Creating RateLimitPolicy", "key", client.ObjectKeyFromObject(gwPolicy).String(), "error", err)
Expect(err).ToNot(HaveOccurred())

// check policy status
Eventually(tests.IsRLPAcceptedAndEnforced).
WithContext(ctx).
WithArguments(testClient(), client.ObjectKeyFromObject(gwPolicy)).Should(Succeed())
})

It("Creates envoyextensionpolicy", func(ctx SpecContext) {
extKey := client.ObjectKey{
Name: controllers.EnvoyExtensionPolicyName(TestGatewayName),
Namespace: testNamespace,
}

Eventually(tests.IsEnvoyExtenstionPolicyAccepted).
WithContext(ctx).WithArguments(testClient(), extKey).Should(Succeed())

ext := &egv1alpha1.EnvoyExtensionPolicy{}
err := testClient().Get(ctx, extKey, ext)
// must exist
Expect(err).ToNot(HaveOccurred())

Expect(ext.Spec.PolicyTargetReferences.TargetRefs).To(HaveLen(1))
Expect(ext.Spec.PolicyTargetReferences.TargetRefs[0].LocalPolicyTargetReference.Group).To(Equal("gateway.networking.k8s.io"))
Expect(ext.Spec.PolicyTargetReferences.TargetRefs[0].LocalPolicyTargetReference.Kind).To(Equal("Gateway"))
Expect(ext.Spec.PolicyTargetReferences.TargetRefs[0].LocalPolicyTargetReference.Name).To(Equal(gateway.Name))
Expect(ext.Spec.Wasm).To(HaveLen(1))
Expect(ext.Spec.Wasm[0].Code.Type).To(Equal(egv1alpha1.ImageWasmCodeSourceType))
Expect(ext.Spec.Wasm[0].Code.Image).To(Not(BeNil()))
Expect(ext.Spec.Wasm[0].Code.Image.URL).To(Equal(WASMFilterImageURL))
existingWASMConfig, err := wasm.ConfigFromJSON(ext.Spec.Wasm[0].Config)
Expect(err).ToNot(HaveOccurred())
Expect(existingWASMConfig).To(Equal(&wasm.Config{
FailureMode: wasm.FailureModeDeny,
RateLimitPolicies: []wasm.RateLimitPolicy{
{
Name: gwPolicy.String(),
Domain: rlptools.LimitsNamespaceFromRLP(gwPolicy),
Rules: []wasm.Rule{
{
Data: []wasm.DataItem{
{
Static: &wasm.StaticSpec{
Key: wasm.LimitNameToLimitadorIdentifier(client.ObjectKeyFromObject(gwPolicy), "l1"),
Value: "1",
},
},
},
},
},
Hostnames: []string{gwRoute.Spec.Hostnames[0]},
Service: common.KuadrantRateLimitClusterName,
},
},
}))
}, testTimeOut)

It("Deletes envoyextensionpolicy when rate limit policy is deleted", func(ctx SpecContext) {
err := testClient().Delete(ctx, gwPolicy)
logf.Log.V(1).Info("Deleting RateLimitPolicy", "key", client.ObjectKeyFromObject(gwPolicy).String(), "error", err)
Expect(err).ToNot(HaveOccurred())

extKey := client.ObjectKey{
Name: controllers.EnvoyExtensionPolicyName(TestGatewayName),
Namespace: testNamespace,
}

Eventually(func() bool {
err := testClient().Get(ctx, extKey, &egv1alpha1.EnvoyExtensionPolicy{})
logf.Log.V(1).Info("Fetching EnvoyExtensionPolicy", "key", extKey.String(), "error", err)
return apierrors.IsNotFound(err)
}).WithContext(ctx).Should(BeTrue())
}, testTimeOut)

It("Deletes envoyextensionpolicy if gateway is deleted", func(ctx SpecContext) {
err := testClient().Delete(ctx, gateway)
logf.Log.V(1).Info("Deleting Gateway", "key", client.ObjectKeyFromObject(gateway).String(), "error", err)
Expect(err).ToNot(HaveOccurred())

extKey := client.ObjectKey{
Name: controllers.EnvoyExtensionPolicyName(TestGatewayName),
Namespace: testNamespace,
}

Eventually(func() bool {
err := testClient().Get(ctx, extKey, &egv1alpha1.EnvoyExtensionPolicy{})
logf.Log.V(1).Info("Fetching EnvoyExtensionPolicy", "key", extKey.String(), "error", err)
return apierrors.IsNotFound(err)
}).WithContext(ctx).Should(BeTrue())
}, testTimeOut)
})

Context("RateLimitPolicy attached to the route", func() {

var (
routePolicy *kuadrantv1beta2.RateLimitPolicy
gwRoute *gatewayapiv1.HTTPRoute
)

BeforeEach(func(ctx SpecContext) {
gwRoute = tests.BuildBasicHttpRoute(TestHTTPRouteName, TestGatewayName, testNamespace, []string{randomHostFromGWHost()})
err := testClient().Create(ctx, gwRoute)
Expect(err).ToNot(HaveOccurred())
Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(gwRoute))).WithContext(ctx).Should(BeTrue())

routePolicy = policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) {
policy.Name = "route"
policy.Spec.TargetRef.Group = gatewayapiv1.GroupName
policy.Spec.TargetRef.Kind = "HTTPRoute"
policy.Spec.TargetRef.Name = TestHTTPRouteName
policy.Spec.Default = &kuadrantv1beta2.RateLimitPolicyCommonSpec{
Limits: map[string]kuadrantv1beta2.Limit{
"l1": {
Rates: []kuadrantv1beta2.Rate{
{
Limit: 1, Duration: 3, Unit: "minute",
},
},
},
},
}
})

err = testClient().Create(ctx, routePolicy)
logf.Log.V(1).Info("Creating RateLimitPolicy", "key", client.ObjectKeyFromObject(routePolicy).String(), "error", err)
Expect(err).ToNot(HaveOccurred())

// check policy status
Eventually(tests.IsRLPAcceptedAndEnforced).
WithContext(ctx).
WithArguments(testClient(), client.ObjectKeyFromObject(routePolicy)).Should(Succeed())
})

It("Creates envoyextensionpolicy", func(ctx SpecContext) {
extKey := client.ObjectKey{
Name: controllers.EnvoyExtensionPolicyName(TestGatewayName),
Namespace: testNamespace,
}

Eventually(tests.IsEnvoyExtenstionPolicyAccepted).
WithContext(ctx).WithArguments(testClient(), extKey).Should(Succeed())

ext := &egv1alpha1.EnvoyExtensionPolicy{}
err := testClient().Get(ctx, extKey, ext)
// must exist
Expect(err).ToNot(HaveOccurred())

Expect(ext.Spec.PolicyTargetReferences.TargetRefs).To(HaveLen(1))
Expect(ext.Spec.PolicyTargetReferences.TargetRefs[0].LocalPolicyTargetReference.Group).To(Equal("gateway.networking.k8s.io"))
Expect(ext.Spec.PolicyTargetReferences.TargetRefs[0].LocalPolicyTargetReference.Kind).To(Equal("Gateway"))
Expect(ext.Spec.PolicyTargetReferences.TargetRefs[0].LocalPolicyTargetReference.Name).To(Equal(gateway.Name))
Expect(ext.Spec.Wasm).To(HaveLen(1))
Expect(ext.Spec.Wasm[0].Code.Type).To(Equal(egv1alpha1.ImageWasmCodeSourceType))
Expect(ext.Spec.Wasm[0].Code.Image).To(Not(BeNil()))
Expect(ext.Spec.Wasm[0].Code.Image.URL).To(Equal(WASMFilterImageURL))
existingWASMConfig, err := wasm.ConfigFromJSON(ext.Spec.Wasm[0].Config)
Expect(err).ToNot(HaveOccurred())
Expect(existingWASMConfig).To(Equal(&wasm.Config{
FailureMode: wasm.FailureModeDeny,
RateLimitPolicies: []wasm.RateLimitPolicy{
{
Name: gwPolicy.String(),
Domain: rlptools.LimitsNamespaceFromRLP(gwPolicy),
Rules: []wasm.Rule{
{
Data: []wasm.DataItem{
{
Static: &wasm.StaticSpec{
Key: wasm.LimitNameToLimitadorIdentifier(client.ObjectKeyFromObject(gwPolicy), "l1"),
Value: "1",
},
},
},
},
},
Hostnames: []string{gwRoute.Spec.Hostnames[0]},
Service: common.KuadrantRateLimitClusterName,
},
},
}))
}, testTimeOut)

It("Deletes envoyextensionpolicy when rate limit policy is deleted", func(ctx SpecContext) {
err := testClient().Delete(ctx, routePolicy)
logf.Log.V(1).Info("Deleting RateLimitPolicy", "key", client.ObjectKeyFromObject(routePolicy).String(), "error", err)
Expect(err).ToNot(HaveOccurred())

extKey := client.ObjectKey{
Name: controllers.EnvoyExtensionPolicyName(TestGatewayName),
Namespace: testNamespace,
}

Eventually(func() bool {
err := testClient().Get(ctx, extKey, &egv1alpha1.EnvoyExtensionPolicy{})
logf.Log.V(1).Info("Fetching EnvoyExtensionPolicy", "key", extKey.String(), "error", err)
return apierrors.IsNotFound(err)
}).WithContext(ctx).Should(BeTrue())
}, testTimeOut)

It("Deletes envoyextensionpolicy if route is deleted", func(ctx SpecContext) {
err := testClient().Delete(ctx, gwRoute)
logf.Log.V(1).Info("Deleting RateLimitPolicy", "key", client.ObjectKeyFromObject(routePolicy).String(), "error", err)
Expect(err).ToNot(HaveOccurred())

extKey := client.ObjectKey{
Name: controllers.EnvoyExtensionPolicyName(TestGatewayName),
Namespace: testNamespace,
}

Eventually(func() bool {
err := testClient().Get(ctx, extKey, &egv1alpha1.EnvoyExtensionPolicy{})
logf.Log.V(1).Info("Fetching EnvoyExtensionPolicy", "key", extKey.String(), "error", err)
return apierrors.IsNotFound(err)
}).WithContext(ctx).Should(BeTrue())
}, testTimeOut)
})
})

0 comments on commit 6fd4a90

Please sign in to comment.