diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d21a3aa1..ce0b32ea9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased +### Added + +- Support for loading configration from custom URL [PR #323](https://github.com/3scale/apicast/pull/323) + ## [3.0.0-beta3] - 2017-03-20 ### Changed diff --git a/apicast/src/configuration_loader.lua b/apicast/src/configuration_loader.lua index 4a72d7b31..c21d85b90 100644 --- a/apicast/src/configuration_loader.lua +++ b/apicast/src/configuration_loader.lua @@ -23,7 +23,7 @@ local _M = { } function _M.load(host) - return mock_loader.call() or file_loader.call() or remote_loader_v2.call() or remote_loader_v1.call(host) + return mock_loader.call() or file_loader.call() or remote_loader_v2:call(host) or remote_loader_v1.call(host) end function _M.boot(host) diff --git a/apicast/src/configuration_loader/remote_v2.lua b/apicast/src/configuration_loader/remote_v2.lua index c20cc1a11..aea0863e5 100644 --- a/apicast/src/configuration_loader/remote_v2.lua +++ b/apicast/src/configuration_loader/remote_v2.lua @@ -2,6 +2,7 @@ local setmetatable = setmetatable local format = string.format local ipairs = ipairs local insert = table.insert +local encode_args = ngx.encode_args local resty_url = require 'resty.url' local http_ng = require "resty.http_ng" @@ -28,14 +29,70 @@ function _M.new(url, options) } } + local path = resty_url.split(endpoint or '') + return setmetatable({ endpoint = endpoint, + path = path and path[6], options = opts, http_client = http_client }, mt) end +function _M:index(host) + local http_client = self.http_client + + if not http_client then + return nil, 'not initialized' + end + + local path = self.path + + if not path then + return nil, 'wrong endpoint url' + end + + local env = resty_env.get('THREESCALE_DEPLOYMENT_ENV') + + if not env then + return nil, 'missing environment' + end + + local url = resty_url.join(self.endpoint, '/', env, '.json?', encode_args({ host = host })) + local res, err = http_client.get(url) + + if not res and err then + ngx.log(ngx.DEBUG, 'index get error: ', err, ' url: ', url) + return nil, err + end + + ngx.log(ngx.DEBUG, 'index get status: ', res.status, ' url: ', url) + + if res.status == 200 then + local json = cjson.decode(res.body) + + local configs = {} + + local proxy_configs = json.proxy_configs or {} + + for i=1, #proxy_configs do + configs[i] = proxy_configs[i].proxy_config.content + end + + return cjson.encode({ services = configs }) + else + return nil, 'invalid status' + end +end + function _M:call(environment) + if self == _M then + local host = environment + local index = _M.new():index(host) + + if index then return index end + end + if not self then return _M.new():call() end diff --git a/spec/configuration_loader/remote_v2_spec.lua b/spec/configuration_loader/remote_v2_spec.lua index 6ede11a79..ff7277f4a 100644 --- a/spec/configuration_loader/remote_v2_spec.lua +++ b/spec/configuration_loader/remote_v2_spec.lua @@ -165,6 +165,34 @@ describe('Configuration Rmote Loader V2', function() end) end) + + describe(':index', function() + before_each(function() + loader = _M.new('http://example.com/something/with/path', { client = test_backend }) + end) + + it('returns configuration for all services', function() + env.set('THREESCALE_DEPLOYMENT_ENV', 'production') + test_backend.expect{ url = 'http://example.com/something/with/path/production.json?host=foobar.example.com' }. + respond_with{ status = 200, body = cjson.encode({ proxy_configs = { + { + proxy_config = { + version = 42, + environment = 'staging', + content = { id = 2, backend_version = 2 } + } + } + }})} + + local config = assert(loader:index('foobar.example.com')) + + assert.truthy(config) + assert.equals('string', type(config)) + + assert.equals(1, #(cjson.decode(config).services)) + end) + end) + describe('.call', function() it('gets environment from ENV', function() local _, err = loader.call()