Skip to content

Commit b27eb0c

Browse files
authored
Merge pull request #1564 from tkan145/THREESCALE-12133-optimize-configuration-reload
THREESCALE-12133 optimize configuration reload
2 parents 1260f7a + e5d8629 commit b27eb0c

5 files changed

Lines changed: 97 additions & 33 deletions

File tree

gateway/src/apicast/configuration_loader/remote_v2.lua

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

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

108112
for i, proxy_conf in ipairs(proxy_configs) do
109113
local proxy_config = proxy_conf.proxy_config
114+
local content = proxy_config.content
110115

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

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

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

130134
config.oidc[i] = oidc_copy
131-
config.services[i] = original_proxy_config.content
132135
end
133136
return cjson.encode(config)
134137
end
@@ -451,10 +454,6 @@ function _M:services()
451454
return services
452455
end
453456

454-
function _M:oidc_issuer_configuration(service)
455-
return self.oidc:call(service.oidc.issuer_endpoint, self.ttl)
456-
end
457-
458457
function _M:config(service, environment, version, service_regexp_filter)
459458
local http_client = self.http_client
460459

@@ -482,20 +481,22 @@ function _M:config(service, environment, version, service_regexp_filter)
482481

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

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

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

498-
return original_proxy_config
498+
proxy_config.oidc = oidc
499+
return proxy_config
499500
else
500501
return nil, status_code_error(res)
501502
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)