supabase-postgres.git / summary / log / commit / refs
commit ccab863ddd2279e5ae49d027328d423bb20ebfe4
Author: Beng Eu <beng@bengeu.com>
Date: Thu Sep 05 06:52:22 2024 +0000
fix: update Envoy config to have circuit breaker settings, retries, increased timeouts and remove empty key query params
ansible/files/envoy_config/cds.yaml | 40 ++++++++++++++++
ansible/files/envoy_config/lds.yaml | 43 +++++++++++++++---
.../envoy_config/remove_apikey_query_parameter.lua | 8 ----
testinfra/test_ami.py | 51 ++++++++++++++++++++-
testinfra/test_ami_nix.py | 53 +++++++++++++++++++++-
5 files changed, 177 insertions(+), 18 deletions(-)
diff --git a/ansible/files/envoy_config/cds.yaml b/ansible/files/envoy_config/cds.yaml
index 8f921396..48fd1b9a 100644
--- a/ansible/files/envoy_config/cds.yaml
+++ b/ansible/files/envoy_config/cds.yaml
@@ -10,6 +10,16 @@ resources:
socket_address:
address: 127.0.0.1
port_value: 8085
+ circuit_breakers:
+ thresholds:
+ - priority: DEFAULT
+ max_connections: 10000
+ max_pending_requests: 10000
+ max_requests: 10000
+ retry_budget:
+ budget_percent:
+ value: 100
+ min_retry_concurrency: 100
- '@type': type.googleapis.com/envoy.config.cluster.v3.Cluster
name: gotrue
load_assignment:
@@ -21,6 +31,16 @@ resources:
socket_address:
address: 127.0.0.1
port_value: 9999
+ circuit_breakers:
+ thresholds:
+ - priority: DEFAULT
+ max_connections: 10000
+ max_pending_requests: 10000
+ max_requests: 10000
+ retry_budget:
+ budget_percent:
+ value: 100
+ min_retry_concurrency: 100
- '@type': type.googleapis.com/envoy.config.cluster.v3.Cluster
name: postgrest
load_assignment:
@@ -32,6 +52,16 @@ resources:
socket_address:
address: 127.0.0.1
port_value: 3000
+ circuit_breakers:
+ thresholds:
+ - priority: DEFAULT
+ max_connections: 10000
+ max_pending_requests: 10000
+ max_requests: 10000
+ retry_budget:
+ budget_percent:
+ value: 100
+ min_retry_concurrency: 100
- '@type': type.googleapis.com/envoy.config.cluster.v3.Cluster
name: postgrest_admin
load_assignment:
@@ -43,4 +73,14 @@ resources:
socket_address:
address: 127.0.0.1
port_value: 3001
+ circuit_breakers:
+ thresholds:
+ - priority: DEFAULT
+ max_connections: 10000
+ max_pending_requests: 10000
+ max_requests: 10000
+ retry_budget:
+ budget_percent:
+ value: 100
+ min_retry_concurrency: 100
diff --git a/ansible/files/envoy_config/lds.yaml b/ansible/files/envoy_config/lds.yaml
index dba85e9d..b7495778 100644
--- a/ansible/files/envoy_config/lds.yaml
+++ b/ansible/files/envoy_config/lds.yaml
@@ -87,8 +87,23 @@ resources:
'@type': >-
type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
source_codes:
- remove_apikey_query_parameter:
- filename: /etc/envoy/remove_apikey_query_parameter.lua
+ remove_apikey_and_empty_key_query_parameters:
+ inline_string: |-
+ function envoy_on_request(request_handle)
+ local path = request_handle:headers():get(":path")
+ request_handle
+ :headers()
+ :replace(":path", path:gsub("&=[^&]*", ""):gsub("?=[^&]*$", ""):gsub("?=[^&]*&", "?"))
+ :replace(":path", path:gsub("&apikey=[^&]*", ""):gsub("?apikey=[^&]*$", ""):gsub("?apikey=[^&]*&", "?"))
+ end
+ remove_empty_key_query_parameters:
+ inline_string: |-
+ function envoy_on_request(request_handle)
+ local path = request_handle:headers():get(":path")
+ request_handle
+ :headers()
+ :replace(":path", path:gsub("&=[^&]*", ""):gsub("?=[^&]*$", ""):gsub("?=[^&]*&", "?"))
+ end
- name: envoy.filters.http.router
typed_config:
'@type': >-
@@ -181,12 +196,14 @@ resources:
retry_policy:
num_retries: 3
retry_on: 5xx
+ timeout: 35s
typed_per_filter_config: *ref_0
- match:
prefix: /auth/v1/
route:
cluster: gotrue
prefix_rewrite: /
+ timeout: 35s
- match:
prefix: /rest/v1/
query_parameters:
@@ -197,12 +214,12 @@ resources:
route:
cluster: postgrest
prefix_rewrite: /
- timeout: 120s
+ timeout: 125s
typed_per_filter_config:
envoy.filters.http.lua:
'@type': >-
type.googleapis.com/envoy.extensions.filters.http.lua.v3.LuaPerRoute
- name: remove_apikey_query_parameter
+ name: remove_apikey_and_empty_key_query_parameter
- match:
prefix: /rest/v1/
request_headers_to_remove:
@@ -210,7 +227,12 @@ resources:
route:
cluster: postgrest
prefix_rewrite: /
- timeout: 120s
+ timeout: 125s
+ typed_per_filter_config:
+ envoy.filters.http.lua:
+ '@type': >-
+ type.googleapis.com/envoy.extensions.filters.http.lua.v3.LuaPerRoute
+ name: remove_empty_key_query_parameter
- match:
prefix: /rest-admin/v1/
query_parameters:
@@ -225,7 +247,7 @@ resources:
envoy.filters.http.lua:
'@type': >-
type.googleapis.com/envoy.extensions.filters.http.lua.v3.LuaPerRoute
- name: remove_apikey_query_parameter
+ name: remove_apikey_and_empty_key_query_parameters
- match:
prefix: /rest-admin/v1/
request_headers_to_remove:
@@ -242,7 +264,7 @@ resources:
route:
cluster: postgrest
prefix_rewrite: /rpc/graphql
- timeout: 120s
+ timeout: 125s
- match:
prefix: /admin/v1/
route:
@@ -293,6 +315,13 @@ resources:
direct_remote_ip:
address_prefix: 10.0.0.0
prefix_len: 8
+ include_attempt_count_in_response: true
+ retry_policy:
+ num_retries: 5
+ retry_back_off:
+ base_interval: 0.1s
+ max_interval: 1s
+ retry_on: gateway-error
stat_prefix: ingress_http
- '@type': type.googleapis.com/envoy.config.listener.v3.Listener
name: https_listener
diff --git a/ansible/files/envoy_config/remove_apikey_query_parameter.lua b/ansible/files/envoy_config/remove_apikey_query_parameter.lua
deleted file mode 100644
index 0aeabaeb..00000000
--- a/ansible/files/envoy_config/remove_apikey_query_parameter.lua
+++ /dev/null
@@ -1,8 +0,0 @@
-function envoy_on_request(request_handle)
- local path = request_handle:headers():get(":path")
-
- -- Remove `apikey` query parameter since PostgREST treats query parameters as conditions.
- request_handle
- :headers()
- :replace(":path", path:gsub("([&?])apikey=[^&]+&?", "%1"):gsub("&$", ""))
-end
diff --git a/testinfra/test_ami.py b/testinfra/test_ami.py
index 715da96f..05ec773b 100644
--- a/testinfra/test_ami.py
+++ b/testinfra/test_ami.py
@@ -343,7 +343,7 @@ def test_postgrest_can_connect_to_db(host):
# There would be an error if the `apikey` query parameter isn't removed,
# since PostgREST treats query parameters as conditions.
#
-# Worth testing since remove_apikey_query_parameter.lua uses regexp instead
+# Worth testing since remove_apikey_query_parameters uses regexp instead
# of parsed query parameters.
def test_postgrest_starting_apikey_query_parameter_is_removed(host):
res = requests.get(
@@ -388,3 +388,52 @@ def test_postgrest_ending_apikey_query_parameter_is_removed(host):
},
)
assert res.ok
+
+# There would be an error if the empty key query parameter isn't removed,
+# since PostgREST treats empty key query parameters as malformed input.
+#
+# Worth testing since remove_apikey_and_empty_key_query_parameters uses regexp instead
+# of parsed query parameters.
+def test_postgrest_starting_empty_key_query_parameter_is_removed(host):
+ res = requests.get(
+ f"http://{host.backend.get_hostname()}/rest/v1/buckets",
+ headers={
+ "accept-profile": "storage",
+ },
+ params={
+ "": "empty_key",
+ "id": "eq.absent",
+ "apikey": service_role_key,
+ },
+ )
+ assert res.ok
+
+
+def test_postgrest_middle_empty_key_query_parameter_is_removed(host):
+ res = requests.get(
+ f"http://{host.backend.get_hostname()}/rest/v1/buckets",
+ headers={
+ "accept-profile": "storage",
+ },
+ params={
+ "apikey": service_role_key,
+ "": "empty_key",
+ "id": "eq.absent",
+ },
+ )
+ assert res.ok
+
+
+def test_postgrest_ending_empty_key_query_parameter_is_removed(host):
+ res = requests.get(
+ f"http://{host.backend.get_hostname()}/rest/v1/buckets",
+ headers={
+ "accept-profile": "storage",
+ },
+ params={
+ "id": "eq.absent",
+ "apikey": service_role_key,
+ "": "empty_key",
+ },
+ )
+ assert res.ok
diff --git a/testinfra/test_ami_nix.py b/testinfra/test_ami_nix.py
index b89183ea..18a366b3 100644
--- a/testinfra/test_ami_nix.py
+++ b/testinfra/test_ami_nix.py
@@ -343,7 +343,7 @@ def test_postgrest_can_connect_to_db(host):
# There would be an error if the `apikey` query parameter isn't removed,
# since PostgREST treats query parameters as conditions.
#
-# Worth testing since remove_apikey_query_parameter.lua uses regexp instead
+# Worth testing since remove_apikey_query_parameters uses regexp instead
# of parsed query parameters.
def test_postgrest_starting_apikey_query_parameter_is_removed(host):
res = requests.get(
@@ -387,4 +387,53 @@ def test_postgrest_ending_apikey_query_parameter_is_removed(host):
"apikey": service_role_key,
},
)
- assert res.ok
\ No newline at end of file
+ assert res.ok
+
+# There would be an error if the empty key query parameter isn't removed,
+# since PostgREST treats empty key query parameters as malformed input.
+#
+# Worth testing since remove_apikey_and_empty_key_query_parameters uses regexp instead
+# of parsed query parameters.
+def test_postgrest_starting_empty_key_query_parameter_is_removed(host):
+ res = requests.get(
+ f"http://{host.backend.get_hostname()}/rest/v1/buckets",
+ headers={
+ "accept-profile": "storage",
+ },
+ params={
+ "": "empty_key",
+ "id": "eq.absent",
+ "apikey": service_role_key,
+ },
+ )
+ assert res.ok
+
+
+def test_postgrest_middle_empty_key_query_parameter_is_removed(host):
+ res = requests.get(
+ f"http://{host.backend.get_hostname()}/rest/v1/buckets",
+ headers={
+ "accept-profile": "storage",
+ },
+ params={
+ "apikey": service_role_key,
+ "": "empty_key",
+ "id": "eq.absent",
+ },
+ )
+ assert res.ok
+
+
+def test_postgrest_ending_empty_key_query_parameter_is_removed(host):
+ res = requests.get(
+ f"http://{host.backend.get_hostname()}/rest/v1/buckets",
+ headers={
+ "accept-profile": "storage",
+ },
+ params={
+ "id": "eq.absent",
+ "apikey": service_role_key,
+ "": "empty_key",
+ },
+ )
+ assert res.ok
[parent: cd9c3f0d27e0]