istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tests/integration/telemetry/policy/envoy_ratelimit_test.go (about) 1 //go:build integ 2 // +build integ 3 4 // Copyright Istio Authors. All Rights Reserved. 5 // 6 // Licensed under the Apache License, Version 2.0 (the "License"); 7 // you may not use this file except in compliance with the License. 8 // You may obtain a copy of the License at 9 // 10 // http://www.apache.org/licenses/LICENSE-2.0 11 // 12 // Unless required by applicable law or agreed to in writing, software 13 // distributed under the License is distributed on an "AS IS" BASIS, 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 18 package policy 19 20 import ( 21 "os" 22 "path/filepath" 23 "testing" 24 25 "istio.io/istio/pkg/config/protocol" 26 "istio.io/istio/pkg/test/env" 27 "istio.io/istio/pkg/test/framework" 28 "istio.io/istio/pkg/test/framework/components/echo" 29 "istio.io/istio/pkg/test/framework/components/echo/check" 30 "istio.io/istio/pkg/test/framework/components/echo/deployment" 31 "istio.io/istio/pkg/test/framework/components/istio" 32 "istio.io/istio/pkg/test/framework/components/istio/ingress" 33 "istio.io/istio/pkg/test/framework/components/namespace" 34 "istio.io/istio/pkg/test/framework/components/prometheus" 35 "istio.io/istio/pkg/test/framework/label" 36 "istio.io/istio/pkg/test/framework/resource" 37 "istio.io/istio/pkg/test/kube" 38 "istio.io/istio/pkg/test/util/tmpl" 39 ) 40 41 var ( 42 ist istio.Instance 43 echoNsInst namespace.Instance 44 ratelimitNs namespace.Instance 45 ing ingress.Instance 46 srv echo.Instance 47 clt echo.Instance 48 prom prometheus.Instance 49 ) 50 51 func TestRateLimiting(t *testing.T) { 52 framework. 53 NewTest(t). 54 Run(func(t framework.TestContext) { 55 cleanup := setupEnvoyFilter(t, "testdata/enable_envoy_ratelimit.yaml") 56 defer cleanup() 57 sendTrafficAndCheckIfRatelimited(t) 58 }) 59 } 60 61 func TestLocalRateLimiting(t *testing.T) { 62 framework. 63 NewTest(t). 64 Run(func(t framework.TestContext) { 65 cleanup := setupEnvoyFilter(t, "testdata/enable_envoy_local_ratelimit.yaml") 66 defer cleanup() 67 sendTrafficAndCheckIfRatelimited(t) 68 }) 69 } 70 71 func TestLocalRouteSpecificRateLimiting(t *testing.T) { 72 framework. 73 NewTest(t). 74 Run(func(t framework.TestContext) { 75 cleanup := setupEnvoyFilter(t, "testdata/enable_envoy_local_ratelimit_per_route.yaml") 76 defer cleanup() 77 sendTrafficAndCheckIfRatelimited(t) 78 }) 79 } 80 81 func TestLocalRateLimitingServiceAccount(t *testing.T) { 82 framework. 83 NewTest(t). 84 Run(func(t framework.TestContext) { 85 cleanup := setupEnvoyFilter(t, "testdata/enable_envoy_local_ratelimit_sa.yaml") 86 defer cleanup() 87 sendTrafficAndCheckIfRatelimited(t) 88 }) 89 } 90 91 func TestMain(m *testing.M) { 92 // nolint: staticcheck 93 framework. 94 NewSuite(m). 95 Label(label.CustomSetup). 96 Setup(istio.Setup(&ist, nil)). 97 Setup(testSetup). 98 Setup(setupPrometheus). 99 Run() 100 } 101 102 func setupPrometheus(ctx resource.Context) (err error) { 103 prom, err = prometheus.New(ctx, prometheus.Config{}) 104 return err 105 } 106 107 func testSetup(ctx resource.Context) (err error) { 108 echoNsInst, err = namespace.New(ctx, namespace.Config{ 109 Prefix: "istio-echo", 110 Inject: true, 111 }) 112 if err != nil { 113 return 114 } 115 116 _, err = deployment.New(ctx). 117 With(&clt, echo.Config{ 118 Service: "clt", 119 Namespace: echoNsInst, 120 ServiceAccount: true, 121 }). 122 With(&srv, echo.Config{ 123 Service: "srv", 124 Namespace: echoNsInst, 125 Ports: []echo.Port{ 126 { 127 Name: "http", 128 Protocol: protocol.HTTP, 129 // We use a port > 1024 to not require root 130 WorkloadPort: 8888, 131 }, 132 }, 133 ServiceAccount: true, 134 }). 135 Build() 136 if err != nil { 137 return 138 } 139 140 ing = ist.IngressFor(ctx.Clusters().Default()) 141 142 ratelimitNs, err = namespace.New(ctx, namespace.Config{ 143 Prefix: "istio-ratelimit", 144 }) 145 if err != nil { 146 return 147 } 148 149 err = ctx.ConfigIstio().File(ratelimitNs.Name(), "testdata/rate-limit-configmap.yaml").Apply() 150 if err != nil { 151 return 152 } 153 154 err = ctx.ConfigIstio().File(ratelimitNs.Name(), filepath.Join(env.IstioSrc, "samples/ratelimit/rate-limit-service.yaml")). 155 Apply() 156 if err != nil { 157 return 158 } 159 160 // Wait for redis and ratelimit service to be up. 161 fetchFn := kube.NewPodFetch(ctx.Clusters().Default(), ratelimitNs.Name(), "app=redis") 162 if _, err = kube.WaitUntilPodsAreReady(fetchFn); err != nil { 163 return 164 } 165 fetchFn = kube.NewPodFetch(ctx.Clusters().Default(), ratelimitNs.Name(), "app=ratelimit") 166 if _, err = kube.WaitUntilPodsAreReady(fetchFn); err != nil { 167 return 168 } 169 170 return nil 171 } 172 173 func setupEnvoyFilter(ctx framework.TestContext, file string) func() { 174 content, err := os.ReadFile(file) 175 if err != nil { 176 ctx.Fatal(err) 177 } 178 179 con, err := tmpl.Evaluate(string(content), map[string]any{ 180 "EchoNamespace": echoNsInst.Name(), 181 "RateLimitNamespace": ratelimitNs.Name(), 182 }) 183 if err != nil { 184 ctx.Fatal(err) 185 } 186 187 err = ctx.ConfigIstio().YAML(ist.Settings().SystemNamespace, con).Apply() 188 if err != nil { 189 ctx.Fatal(err) 190 } 191 return func() { 192 ctx.ConfigIstio().YAML(ist.Settings().SystemNamespace, con).DeleteOrFail(ctx) 193 } 194 } 195 196 func sendTrafficAndCheckIfRatelimited(t framework.TestContext) { 197 t.Helper() 198 clt.CallOrFail(t, echo.CallOptions{ 199 To: srv, 200 Port: echo.Port{ 201 Name: "http", 202 }, 203 Count: 5, 204 Check: check.TooManyRequests(), 205 }) 206 }