blob: 8077dde64ad0b495db2ed0ae619edb302e053b43 [file] [log] [blame]
//go:build integ
// +build integ
// Copyright Istio Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package policy
import (
"os"
"path/filepath"
"testing"
"time"
)
import (
"github.com/apache/dubbo-go-pixiu/pkg/config/protocol"
"github.com/apache/dubbo-go-pixiu/pkg/test/env"
"github.com/apache/dubbo-go-pixiu/pkg/test/framework"
"github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/echo"
"github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/echo/check"
"github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/echo/deployment"
"github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/istio"
"github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/istio/ingress"
"github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/namespace"
"github.com/apache/dubbo-go-pixiu/pkg/test/framework/label"
"github.com/apache/dubbo-go-pixiu/pkg/test/framework/resource"
"github.com/apache/dubbo-go-pixiu/pkg/test/kube"
"github.com/apache/dubbo-go-pixiu/pkg/test/util/retry"
"github.com/apache/dubbo-go-pixiu/pkg/test/util/tmpl"
)
var (
ist istio.Instance
echoNsInst namespace.Instance
ratelimitNs namespace.Instance
ing ingress.Instance
srv echo.Instance
clt echo.Instance
)
func TestRateLimiting(t *testing.T) {
framework.
NewTest(t).
Features("traffic.ratelimit.envoy").
Run(func(t framework.TestContext) {
cleanup := setupEnvoyFilter(t, "testdata/enable_envoy_ratelimit.yaml")
defer cleanup()
sendTrafficAndCheckIfRatelimited(t)
})
}
func TestLocalRateLimiting(t *testing.T) {
framework.
NewTest(t).
Features("traffic.ratelimit.envoy").
Run(func(t framework.TestContext) {
cleanup := setupEnvoyFilter(t, "testdata/enable_envoy_local_ratelimit.yaml")
defer cleanup()
sendTrafficAndCheckIfRatelimited(t)
})
}
func TestLocalRouteSpecificRateLimiting(t *testing.T) {
framework.
NewTest(t).
Features("traffic.ratelimit.envoy").
Run(func(t framework.TestContext) {
cleanup := setupEnvoyFilter(t, "testdata/enable_envoy_local_ratelimit_per_route.yaml")
defer cleanup()
sendTrafficAndCheckIfRatelimited(t)
})
}
func TestLocalRateLimitingServiceAccount(t *testing.T) {
framework.
NewTest(t).
Features("traffic.ratelimit.envoy").
Run(func(t framework.TestContext) {
cleanup := setupEnvoyFilter(t, "testdata/enable_envoy_local_ratelimit_sa.yaml")
defer cleanup()
sendTrafficAndCheckIfRatelimited(t)
})
}
func TestMain(m *testing.M) {
// nolint: staticcheck
framework.
NewSuite(m).
Label(label.CustomSetup).
Setup(istio.Setup(&ist, nil)).
Setup(testSetup).
Run()
}
func testSetup(ctx resource.Context) (err error) {
echoNsInst, err = namespace.New(ctx, namespace.Config{
Prefix: "istio-echo",
Inject: true,
})
if err != nil {
return
}
_, err = deployment.New(ctx).
With(&clt, echo.Config{
Service: "clt",
Namespace: echoNsInst,
ServiceAccount: true,
}).
With(&srv, echo.Config{
Service: "srv",
Namespace: echoNsInst,
Ports: []echo.Port{
{
Name: "http",
Protocol: protocol.HTTP,
// We use a port > 1024 to not require root
WorkloadPort: 8888,
},
},
ServiceAccount: true,
}).
Build()
if err != nil {
return
}
ing = ist.IngressFor(ctx.Clusters().Default())
ratelimitNs, err = namespace.New(ctx, namespace.Config{
Prefix: "istio-ratelimit",
})
if err != nil {
return
}
err = ctx.ConfigIstio().File(ratelimitNs.Name(), "testdata/rate-limit-configmap.yaml").Apply()
if err != nil {
return
}
err = ctx.ConfigIstio().File(ratelimitNs.Name(), filepath.Join(env.IstioSrc, "samples/ratelimit/rate-limit-service.yaml")).Apply()
if err != nil {
return
}
// Wait for redis and ratelimit service to be up.
fetchFn := kube.NewPodFetch(ctx.Clusters().Default(), ratelimitNs.Name(), "app=redis")
if _, err = kube.WaitUntilPodsAreReady(fetchFn); err != nil {
return
}
fetchFn = kube.NewPodFetch(ctx.Clusters().Default(), ratelimitNs.Name(), "app=ratelimit")
if _, err = kube.WaitUntilPodsAreReady(fetchFn); err != nil {
return
}
return nil
}
func setupEnvoyFilter(ctx framework.TestContext, file string) func() {
content, err := os.ReadFile(file)
if err != nil {
ctx.Fatal(err)
}
con, err := tmpl.Evaluate(string(content), map[string]interface{}{
"EchoNamespace": echoNsInst.Name(),
"RateLimitNamespace": ratelimitNs.Name(),
})
if err != nil {
ctx.Fatal(err)
}
err = ctx.ConfigIstio().YAML(ist.Settings().SystemNamespace, con).Apply()
if err != nil {
ctx.Fatal(err)
}
return func() {
ctx.ConfigIstio().YAML(ist.Settings().SystemNamespace, con).DeleteOrFail(ctx)
}
}
func sendTrafficAndCheckIfRatelimited(t framework.TestContext) {
t.Helper()
retry.UntilSuccessOrFail(t, func() error {
t.Logf("Sending 5 requests...")
httpOpts := echo.CallOptions{
To: srv,
Port: echo.Port{
Name: "http",
},
Count: 5,
Retry: echo.Retry{
NoRetry: true,
},
}
result, err := clt.Call(httpOpts)
return check.TooManyRequests().Check(result, err)
}, retry.Delay(10*time.Second), retry.Timeout(60*time.Second))
}