Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[management] split management api #276

Merged
merged 4 commits into from
Mar 2, 2017
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
4 changes: 4 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ REDIS_HOST=redis

# Set number of worker processes.
# APICAST_WORKERS=2

# How much to open the Management API. Allowed values are: disabled, status, debug.
# OpenShift template has status as the default value to use it for healt checks.
APICAST_MANAGEMENT_API=debug
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Reduce use of global objects [PR #273](https://github.com/3scale/apicast/pull/273)
- Load V2 configuration for all services in parallel [PR #272](https://github.com/3scale/apicast/pull/272)
- Configuration is using LRU cache [PR #274](https://github.com/3scale/apicast/pull/274)
- Management API not opened by default [PR #276](https://github.com/3scale/apicast/pull/276)

### Added

Expand Down
1 change: 1 addition & 0 deletions apicast/conf/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ env APICAST_MODULE;
env APICAST_MISSING_CONFIGURATION;
env APICAST_REQUEST_LOGS;
env APICAST_RESPONSE_CODES;
env APICAST_MANAGEMENT_API;
env AUTO_UPDATE_INTERVAL;
env BACKEND_ENDPOINT_OVERRIDE;

Expand Down
63 changes: 49 additions & 14 deletions apicast/src/management.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,26 @@ local configuration_parser = require('configuration_parser')
local configuration_loader = require('configuration_loader')
local inspect = require('inspect')
local resolver_cache = require('resty.resolver.cache')
local env = require('resty.env')

local live = cjson.encode({status = 'live', success = true})

local function json_response(body, status)
ngx.header.content_type = 'application/json; charset=utf-8'
ngx.status = status or 200
ngx.status = status or ngx.HTTP_OK
ngx.say(cjson.encode(body))
end

function _M.ready()
local status = _M.status()
local code = status.success and 200 or 412
local code = status.success and ngx.HTTP_OK or 412

ngx.status = code
ngx.say(cjson.encode(status))
end

function _M.live()
ngx.status = 200
ngx.status = ngx.HTTP_OK
ngx.say(live)
end

Expand All @@ -48,7 +49,7 @@ function _M.config()
local contents = cjson.encode(config.configured and { services = config:all() } or nil)

ngx.header.content_type = 'application/json; charset=utf-8'
ngx.status = 200
ngx.status = ngx.HTTP_OK
ngx.say(contents)
end

Expand All @@ -63,12 +64,19 @@ function _M.update_config()
data = assert(io.open(file)):read('*a')
end

local config = configuration_parser.decode(data)
proxy:configure(config)
-- TODO: respond with proper 304 Not Modified when config is the same
local response = cjson.encode({ status = 'ok', config = config or cjson.null })
ngx.header.content_type = 'application/json; charset=utf-8'
ngx.say(response)
local config, err = configuration_parser.decode(data)

if config then
local configured, error = proxy:configure(config)
-- TODO: respond with proper 304 Not Modified when config is the same
if configured and #(configured.services) > 0 then
json_response({ status = 'ok', config = config, services = #(configured.services)})
else
json_response({ status = 'not_configured', config = config, services = 0, error = error }, ngx.HTTP_NOT_ACCEPTABLE)
end
else
json_response({ status = 'error', config = config or cjson.null, error = err}, ngx.HTTP_BAD_REQUEST)
end
end

function _M.delete_config()
Expand Down Expand Up @@ -100,20 +108,47 @@ function _M.dns_cache()
return json_response(cache:all())
end

function _M.router()
local r = router.new()
function _M.disabled()
ngx.exit(ngx.HTTP_FORBIDDEN)
end

local routes = {}

function routes.disabled(r)
r:get('/', _M.disabled)
end

function routes.status(r)
r:get('/status/ready', _M.ready)
r:get('/status/live', _M.live)
end

function routes.debug(r)
r:get('/config', _M.config)
r:put('/config', _M.update_config)
r:post('/config', _M.update_config)
r:delete('/config', _M.delete_config)

r:get('/status/ready', _M.ready)
r:get('/status/live', _M.live)
routes.status(r)

r:get('/dns/cache', _M.dns_cache)

r:post('/boot', _M.boot)
end

function _M.router()
local r = router.new()

local name = env.value('APICAST_MANAGEMENT_API') or 'status'
local api = routes[name]

ngx.log(ngx.DEBUG, 'management api mode: ', name)

if api then
api(r)
else
ngx.log(ngx.ERR, 'invalid management api setting: ', name)
end

return r
end
Expand Down
36 changes: 36 additions & 0 deletions apicast/src/resty/env.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
------------
-- Resty ENV
-- OpenResty module for working with ENV variables.
--
-- @module resty.env
-- @author mikz
-- @license Apache License Version 2.0

local _M = {
_VERSION = '0.1'
}
Expand All @@ -12,10 +20,30 @@ local function fetch(name)
return value
end

--- Return the raw value from ENV. Uses local cache.
-- @tparam string name name of the environment variable
function _M.get(name)
return _M.env[name] or fetch(name)
end

local value_mapping = {
[''] = false
}

--- Return value from ENV.
--- Returns false if it is empty. Uses @{get} internally.
-- @tparam string name name of the environment variable
function _M.value(name)
local value = _M.get(name)
local mapped = value_mapping[value]

if mapped == nil then
return value
else
return mapped
end
end

local env_mapping = {
['true'] = true,
['false'] = false,
Expand All @@ -24,17 +52,25 @@ local env_mapping = {
[''] = false
}

--- Returns true/false from ENV variable.
--- Converts 0 to false and 1 to true.
-- @tparam string name name of the environment variable
function _M.enabled(name)
return env_mapping[_M.get(name)]
end

--- Sets value to the local cache.
-- @tparam string name name of the environment variable
-- @tparam string value value to be cached
-- @see resty.env.get
function _M.set(name, value)
local env = _M.env
local previous = env[name]
env[name] = value
return previous
end

--- Reset local cache.
function _M.reset()
_M.env = {}
return _M
Expand Down
3 changes: 2 additions & 1 deletion doc/config.ld
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
file = {
'../apicast/src/configuration/service.lua'
'../apicast/src/configuration/service.lua',
'../apicast/src/resty/env.lua'
}
dir = '../doc/api'
project = 'APIcast'
Expand Down
13 changes: 12 additions & 1 deletion doc/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,15 @@ Note that when deploying APIcast v2 with OpenShift, some of thee parameters can

URI that overrides backend endpoint from the configuration. Useful when deploying outside OpenShift deployed AMP.

**Example**: `https://backend.example.com`.
**Example**: `https://backend.example.com`.

- `APICAST_MANAGEMENT_API`

**Values:**

- `disabled`: completely disabled, just listens on the port
- `status`: only the `/status/` endpoints enabled for health checks
- `debug`: full API is open

The [Management API](./management-api.md) is powerful and can control the APIcast configuration.
You should enable the debug level only for debugging.
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ services:
- gateway
entrypoint: ""
dns: 127.0.0.1
environment:
APICAST_MANAGEMENT_API: debug
dns_search:
- example.com
prove:
Expand Down
6 changes: 6 additions & 0 deletions openshift/apicast-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ objects:
value: "${REDIS_HOST}"
- name: REDIS_PORT
value: "${REDIS_PORT}"
- name: APICAST_MANAGEMENT_API
value: "${MANAGEMENT_API}"
image: "${THREESCALE_GATEWAY_IMAGE}"
imagePullPolicy: Always
name: "${THREESCALE_GATEWAY_NAME}"
Expand Down Expand Up @@ -158,3 +160,7 @@ parameters:
name: REDIS_PORT
required: false
value: "6379"
- name: MANAGEMENT_API
description: "Scope of the Management API. Can be disabled, status or debug. At least status required for health checks."
required: false
value: "status"
12 changes: 12 additions & 0 deletions spec/resty/env_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ describe('env', function()
end)
end)

describe('.value', function()
it('returns false instead of empty value', function()
_M.set('KEY', '')
assert.equal(false, _M.value('KEY'))
end)

it('returns the value if not emptu', function()
_M.set('KEY', 'value')
assert.equal('value', _M.value('KEY'))
end)
end)

describe('.set', function()
it('saves value to the cache', function()
_M.set('SOME_MISSING_KEY', 'val')
Expand Down
Loading