Skip to content

Commit 086af0d

Browse files
authored
Merge pull request #1571 from tkan145/THREESCALE-12133-2.16
THREESCALE-12133 optimize configuration reload (2.16)
2 parents bd2a95c + f5dcd20 commit 086af0d

File tree

5 files changed

+97
-33
lines changed

5 files changed

+97
-33
lines changed

gateway/src/apicast/configuration_loader/remote_v2.lua

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -103,33 +103,36 @@ local function service_config_endpoint(portal_endpoint, service_id, env, version
103103
)
104104
end
105105

106+
local function get_oidc_issuer_endpoint(proxy_content)
107+
return proxy_content.proxy and proxy_content.proxy.oidc_issuer_endpoint
108+
end
109+
106110
local function parse_proxy_configs(self, proxy_configs)
107111
local config = { services = array(), oidc = array() }
108112

109113
for i, proxy_conf in ipairs(proxy_configs) do
110114
local proxy_config = proxy_conf.proxy_config
115+
local content = proxy_config.content
111116

112-
-- Copy the config because parse_service have side-effects. It adds
113-
-- liquid templates in some policies and those cannot be encoded into a
114-
-- JSON. We should get rid of these side effects.
115-
local original_proxy_config = deepcopy(proxy_config)
116-
117-
local service = configuration.parse_service(proxy_config.content)
117+
config.services[i] = content
118118

119+
local issuer_endpoint = get_oidc_issuer_endpoint(content)
120+
local oidc
121+
if issuer_endpoint then
122+
oidc = self.oidc:call(issuer_endpoint, self.ttl)
123+
end
119124
-- We always assign a oidc to the service, even an empty one with the
120125
-- service_id, if not on APICAST_SERVICES_LIST will fail on filtering
121-
local oidc = self:oidc_issuer_configuration(service)
122126
if not oidc then
123127
oidc = {}
124128
end
125129

126130
-- deepcopy because this can be cached, and we want to have a deepcopy to
127131
-- avoid issues with service_id
128132
local oidc_copy = deepcopy(oidc)
129-
oidc_copy.service_id = service.id
133+
oidc_copy.service_id = tostring(content.id)
130134

131135
config.oidc[i] = oidc_copy
132-
config.services[i] = original_proxy_config.content
133136
end
134137
return cjson.encode(config)
135138
end
@@ -449,10 +452,6 @@ function _M:services()
449452
return services
450453
end
451454

452-
function _M:oidc_issuer_configuration(service)
453-
return self.oidc:call(service.oidc.issuer_endpoint, self.ttl)
454-
end
455-
456455
function _M:config(service, environment, version, service_regexp_filter)
457456
local http_client = self.http_client
458457

@@ -480,20 +479,22 @@ function _M:config(service, environment, version, service_regexp_filter)
480479

481480
if res.status == 200 then
482481
local proxy_config = cjson.decode(res.body).proxy_config
483-
484-
-- Copy the config because parse_service have side-effects. It adds
485-
-- liquid templates in some policies and those cannot be encoded into a
486-
-- JSON. We should get rid of these side effects.
487-
local original_proxy_config = deepcopy(proxy_config)
482+
local content = proxy_config.content
488483

489484
local config_service = configuration.parse_service(proxy_config.content)
490485
if service_regexp_filter and not config_service:match_host(service_regexp_filter) then
491486
return nil, "Service filtered out because APICAST_SERVICES_FILTER_BY_URL"
492487
end
493488

494-
original_proxy_config.oidc = self:oidc_issuer_configuration(config_service)
489+
local issuer_endpoint = get_oidc_issuer_endpoint(content)
490+
local oidc
491+
492+
if issuer_endpoint then
493+
oidc = self.oidc:call(issuer_endpoint, self.ttl)
494+
end
495495

496-
return original_proxy_config
496+
proxy_config.oidc = oidc
497+
return proxy_config
497498
else
498499
return nil, status_code_error(res)
499500
end

gateway/src/apicast/policy_chain.lua

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,12 +193,15 @@ function _M:add_policy(name, version, ...)
193193
end
194194
end
195195

196+
local default_policy_order_check = PolicyOrderChecker.new(policy_manifests_loader.get_all())
197+
196198
-- Checks if there are any policies placed in the wrong place in the chain.
197199
-- It doesn't return anything, it prints error messages when there's a problem.
198200
function _M:check_order(manifests)
199-
PolicyOrderChecker.new(
200-
manifests or policy_manifests_loader.get_all()
201-
):check(self)
201+
if manifests then
202+
return PolicyOrderChecker.new(manifests):check(self)
203+
end
204+
default_policy_order_check:check(self)
202205
end
203206

204207
local function call_chain(phase_name)

gateway/src/apicast/policy_config_validator.lua

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,35 @@
33
-- Validates a policy configuration against a policy config JSON schema.
44

55
local jsonschema = require('jsonschema')
6+
local lrucache = require("resty.lrucache")
67

7-
local _M = { }
8+
local cached_validator = lrucache.new(100)
9+
10+
local _M = {
11+
_VERSION=0.1
12+
}
13+
14+
local function create_validator(schema)
15+
local ok, res = pcall(jsonschema.generate_validator, schema)
16+
if ok then
17+
return res
18+
end
19+
20+
return nil, res
21+
end
22+
23+
local function get_validator(schema)
24+
local validator, err = cached_validator:get(schema)
25+
if not validator then
26+
validator, err = create_validator(schema)
27+
if not validator then
28+
return nil, err
29+
end
30+
cached_validator:set(schema, validator)
31+
end
32+
33+
return validator, nil
34+
end
835

936
--- Validate a policy configuration
1037
-- Checks if a policy configuration is valid according to the given schema.
@@ -13,7 +40,10 @@ local _M = { }
1340
-- @treturn boolean True if the policy configuration is valid. False otherwise.
1441
-- @treturn string Error message only when the policy config is invalid.
1542
function _M.validate_config(config, config_schema)
16-
local validator = jsonschema.generate_validator(config_schema or {})
43+
local validator, err = get_validator(config_schema or {})
44+
if not validator then
45+
return false, err
46+
end
1747
return validator(config or {})
1848
end
1949

gateway/src/apicast/policy_loader.lua

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ local concat = table.concat
1616
local setmetatable = setmetatable
1717
local pcall = pcall
1818

19+
local isempty = require('table.isempty')
20+
21+
-- Module-level cache storage (one per worker process)
22+
local manifests_cache = {}
23+
1924
local _M = {}
2025

2126
local resty_env = require('resty.env')
@@ -70,8 +75,26 @@ local function lua_load_path(load_path)
7075
return format('%s/?.lua', load_path)
7176
end
7277

78+
-- Get a cached manifest by policy name and version
79+
-- @tparam string name The policy name
80+
-- @tparam string version The policy version
81+
-- @treturn table|nil The cached manifest table, or nil if not cached
82+
local function get_cached_manifest(name, version)
83+
local manifests = manifests_cache[name]
84+
if manifests then
85+
for _, manifest in ipairs(manifests) do
86+
if version == manifest.version then
87+
return manifest
88+
end
89+
end
90+
end
91+
end
92+
7393
local function load_manifest(name, version, path)
74-
local manifest = read_manifest(path)
94+
local manifest = get_cached_manifest(name, version)
95+
if not manifest then
96+
manifest = read_manifest(path)
97+
end
7598

7699
if manifest then
77100
if manifest.version ~= version then
@@ -110,8 +133,8 @@ end
110133
function _M:load_path(name, version, paths)
111134
local failures = {}
112135

113-
for _, path in ipairs(paths or self.policy_load_paths()) do
114-
local manifest, load_path = load_manifest(name, version, format('%s/%s/%s', path, name, version) )
136+
if version == 'builtin' then
137+
local manifest, load_path = load_manifest(name, version, format('%s/%s', self.builtin_policy_load_path(), name) )
115138

116139
if manifest then
117140
return load_path, manifest.configuration
@@ -120,8 +143,8 @@ function _M:load_path(name, version, paths)
120143
end
121144
end
122145

123-
if version == 'builtin' then
124-
local manifest, load_path = load_manifest(name, version, format('%s/%s', self.builtin_policy_load_path(), name) )
146+
for _, path in ipairs(paths or self.policy_load_paths()) do
147+
local manifest, load_path = load_manifest(name, version, format('%s/%s/%s', path, name, version) )
125148

126149
if manifest then
127150
return load_path, manifest.configuration
@@ -130,6 +153,7 @@ function _M:load_path(name, version, paths)
130153
end
131154
end
132155

156+
133157
return nil, nil, failures
134158
end
135159

@@ -173,9 +197,15 @@ end
173197
-- Returns all the policy modules
174198
function _M:get_all()
175199
local policy_modules = {}
200+
local manifests
176201

177-
local policy_manifests_loader = require('apicast.policy_manifests_loader')
178-
local manifests = policy_manifests_loader.get_all()
202+
if isempty(manifests_cache) then
203+
local policy_manifests_loader = require('apicast.policy_manifests_loader')
204+
manifests = policy_manifests_loader.get_all()
205+
manifests_cache = manifests
206+
else
207+
manifests = manifests_cache
208+
end
179209

180210
for policy_name, policy_manifests in pairs(manifests) do
181211
for _, manifest in ipairs(policy_manifests) do

spec/configuration_loader/remote_v2_spec.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ UwIDAQAB
651651
it('does not crash on empty issuer', function()
652652
local service = { oidc = { issuer_endpoint = '' }}
653653

654-
assert.falsy(loader:oidc_issuer_configuration(service))
654+
assert.falsy(loader.oidc:call(service.oidc.issuer_endpoint, 0))
655655
end)
656656
end)
657657

0 commit comments

Comments
 (0)