Skip to content
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,5 @@ charts/gateway-addons-helm/dashboards/vendor/
*.tar.gz

*.yaml-e

*.out
86 changes: 54 additions & 32 deletions test/e2e/tests/local_ratelimit.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,35 @@ func init() {
const (
RatelimitLimitHeaderName = "x-ratelimit-limit"
RatelimitRemainingHeaderName = "x-ratelimit-remaining"
RatelimitResetHeaderName = "x-ratelimit-reset"
)

var allRateLimitHeaders = []string{
RatelimitLimitHeaderName,
RatelimitRemainingHeaderName,
RatelimitResetHeaderName,
}

var LocalRateLimitTest = suite.ConformanceTest{
ShortName: "LocalRateLimit",
Description: "Make sure local rate limit work",
Manifests: []string{"testdata/local-ratelimit.yaml"},
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
for _, disableHeader := range []bool{true, false} {
runNoRateLimitTest(t, suite, disableHeader)

t.Run(fmt.Sprintf("SpecificUser-%t", disableHeader), func(t *testing.T) {
caseSuffix := "disableHeader"
if !disableHeader {
caseSuffix = "withHeader"
}
t.Run(fmt.Sprintf("SpecificUser-%s", caseSuffix), func(t *testing.T) {
runSpecificUserRateLimitTest(t, suite, disableHeader)
})

t.Run(fmt.Sprintf("AllTraffic-%t", disableHeader), func(t *testing.T) {
t.Run(fmt.Sprintf("AllTraffic-%s", caseSuffix), func(t *testing.T) {
runAllTrafficRateLimitTest(t, suite, disableHeader)
})

t.Run(fmt.Sprintf("HeaderInvertMatch-%t", disableHeader), func(t *testing.T) {
t.Run(fmt.Sprintf("HeaderInvertMatch-%s", caseSuffix), func(t *testing.T) {
runHeaderInvertMatchRateLimitTest(t, suite, disableHeader)
})
}
Expand Down Expand Up @@ -87,19 +97,19 @@ func runNoRateLimitTest(t *testing.T, suite *suite.ConformanceTestSuite, disable
},
Response: http.Response{
StatusCode: 200,
AbsentHeaders: []string{RatelimitLimitHeaderName, RatelimitRemainingHeaderName},
AbsentHeaders: allRateLimitHeaders,
},
Namespace: ns,
}

// keep sending requests till get 200 first, that will cost one 200
utils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite, gwAddr, expectOkResp)
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectOkResp)

// send 10+ more
total := 10
for total > 0 {
// keep sending requests till get 200 first, that will cost one 200
utils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite, gwAddr, expectOkResp)
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectOkResp)
total--
}
}
Expand Down Expand Up @@ -134,10 +144,13 @@ func runSpecificUserRateLimitTest(t *testing.T, suite *suite.ConformanceTestSuit
if !disableHeader {
okResponse.Response.Headers = map[string]string{
RatelimitLimitHeaderName: "3",
RatelimitRemainingHeaderName: "", // empty string means we don't care about the value
RatelimitRemainingHeaderName: "1",
RatelimitResetHeaderName: "0",
}
} else {
okResponse.Response.AbsentHeaders = allRateLimitHeaders
}
utils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite, gwAddr, okResponse)
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, okResponse)

// this request should be limited because the user is john
limitResponse := http.ExpectedResponse{
Expand All @@ -154,11 +167,13 @@ func runSpecificUserRateLimitTest(t *testing.T, suite *suite.ConformanceTestSuit
}
if !disableHeader {
limitResponse.Response.Headers = map[string]string{
RatelimitLimitHeaderName: "4",
RatelimitRemainingHeaderName: "0", // at the end the remaining should be 0
RatelimitLimitHeaderName: "3",
RatelimitRemainingHeaderName: "0",
}
} else {
limitResponse.Response.AbsentHeaders = allRateLimitHeaders
}
utils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite, gwAddr, limitResponse)
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, limitResponse)

// this request should not be limited because the user is not john hit default bucket
notJohnResponse := http.ExpectedResponse{
Expand All @@ -177,9 +192,12 @@ func runSpecificUserRateLimitTest(t *testing.T, suite *suite.ConformanceTestSuit
notJohnResponse.Response.Headers = map[string]string{
RatelimitLimitHeaderName: "10",
RatelimitRemainingHeaderName: "2", // there almost 8 requests before reach this
RatelimitResetHeaderName: "0",
}
} else {
notJohnResponse.Response.AbsentHeaders = allRateLimitHeaders
}
utils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite, gwAddr, notJohnResponse)
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, notJohnResponse)

// In the end it will hit the limit
notJohnLimitResponse := http.ExpectedResponse{
Expand All @@ -190,10 +208,6 @@ func runSpecificUserRateLimitTest(t *testing.T, suite *suite.ConformanceTestSuit
},
},
Response: http.Response{
Headers: map[string]string{
RatelimitLimitHeaderName: "10",
RatelimitRemainingHeaderName: "0", // it will be limited at the end
},
StatusCode: 429,
},
Namespace: ns,
Expand All @@ -203,8 +217,10 @@ func runSpecificUserRateLimitTest(t *testing.T, suite *suite.ConformanceTestSuit
RatelimitLimitHeaderName: "10",
RatelimitRemainingHeaderName: "0", // it will be limited at the end
}
} else {
notJohnLimitResponse.Response.AbsentHeaders = allRateLimitHeaders
}
utils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite, gwAddr, notJohnLimitResponse)
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, notJohnLimitResponse)
}

func runAllTrafficRateLimitTest(t *testing.T, suite *suite.ConformanceTestSuite, disableHeader bool) {
Expand Down Expand Up @@ -232,11 +248,14 @@ func runAllTrafficRateLimitTest(t *testing.T, suite *suite.ConformanceTestSuite,
if !disableHeader {
okResponse.Response.Headers = map[string]string{
RatelimitLimitHeaderName: "3",
RatelimitRemainingHeaderName: "", // empty string means we don't care about the value
RatelimitRemainingHeaderName: "1",
RatelimitResetHeaderName: "0",
}
} else {
okResponse.Response.AbsentHeaders = allRateLimitHeaders
}
// keep sending requests till get 200 first, that will cost one 200
utils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite, gwAddr, okResponse)
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, okResponse)

limitResponse := http.ExpectedResponse{
Request: http.Request{
Expand All @@ -252,9 +271,11 @@ func runAllTrafficRateLimitTest(t *testing.T, suite *suite.ConformanceTestSuite,
RatelimitLimitHeaderName: "3",
RatelimitRemainingHeaderName: "0", // at the end the remaining should be 0
}
} else {
limitResponse.Response.AbsentHeaders = allRateLimitHeaders
}
// this request should be limited at the end
utils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite, gwAddr, limitResponse)
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, limitResponse)
}

func runHeaderInvertMatchRateLimitTest(t *testing.T, suite *suite.ConformanceTestSuite, disableHeader bool) {
Expand Down Expand Up @@ -287,10 +308,11 @@ func runHeaderInvertMatchRateLimitTest(t *testing.T, suite *suite.ConformanceTes
if !disableHeader {
okResponse.Response.Headers = map[string]string{
RatelimitLimitHeaderName: "3",
RatelimitRemainingHeaderName: "", // empty string means we don't care about the value
RatelimitRemainingHeaderName: "1",
RatelimitResetHeaderName: "0",
}
}
utils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite, gwAddr, okResponse)
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, okResponse)

// this request should be limited because the user is one and org is not test and the limit is 3
limitResponse := http.ExpectedResponse{
Expand All @@ -302,21 +324,19 @@ func runHeaderInvertMatchRateLimitTest(t *testing.T, suite *suite.ConformanceTes
},
},
Response: http.Response{
Headers: map[string]string{
RatelimitLimitHeaderName: "3",
RatelimitRemainingHeaderName: "0", // at the end the remaining should be 0
},
StatusCode: 429,
},
Namespace: ns,
}
if !disableHeader {
limitResponse.Response.Headers = map[string]string{
RatelimitLimitHeaderName: "3",
RatelimitRemainingHeaderName: "0", // empty string means we don't care about the value
RatelimitRemainingHeaderName: "0",
}
} else {
limitResponse.Response.AbsentHeaders = allRateLimitHeaders
}
utils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite, gwAddr, limitResponse)
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, limitResponse)

// with test org
testOrgResponse := http.ExpectedResponse{
Expand All @@ -334,9 +354,11 @@ func runHeaderInvertMatchRateLimitTest(t *testing.T, suite *suite.ConformanceTes
}
if !disableHeader {
testOrgResponse.Response.Headers = map[string]string{
RatelimitLimitHeaderName: "", // we don't care the real number
RatelimitRemainingHeaderName: "",
RatelimitLimitHeaderName: "4294967295",
RatelimitResetHeaderName: "0",
}
} else {
testOrgResponse.Response.AbsentHeaders = allRateLimitHeaders
}
utils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite, gwAddr, testOrgResponse)
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, testOrgResponse)
}
5 changes: 2 additions & 3 deletions test/e2e/tests/local_ratelimit_distinct_cidr.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (

"github.com/envoyproxy/gateway/internal/gatewayapi"
"github.com/envoyproxy/gateway/internal/gatewayapi/resource"
"github.com/envoyproxy/gateway/test/e2e/utils"
)

func init() {
Expand Down Expand Up @@ -100,7 +99,7 @@ var LocalRateLimitDistinctCIDRTest = suite.ConformanceTest{
}

func testRatelimit(t *testing.T, suite *suite.ConformanceTestSuite, headers map[string]string, ns, gwAddr, path string) {
utils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite, gwAddr, http.ExpectedResponse{
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, http.ExpectedResponse{
Request: http.Request{
Path: path,
Headers: headers,
Expand All @@ -115,7 +114,7 @@ func testRatelimit(t *testing.T, suite *suite.ConformanceTestSuite, headers map[
StatusCode: 200,
Headers: map[string]string{
RatelimitLimitHeaderName: "3",
RatelimitRemainingHeaderName: "", // empty string means we don't care about the value
RatelimitRemainingHeaderName: "1",
},
},
Namespace: ns,
Expand Down
Loading