diff --git a/.busted b/.busted index 7d7e86c5e..b1ab83a81 100644 --- a/.busted +++ b/.busted @@ -10,7 +10,9 @@ local default = { verbose = true, ['shuffle-tests'] = true, ['shuffle-files'] = true, - lpath = path.join(root, 'spec/?.lua;') .. path.join(root, 'gateway/src/?.lua;'), + + -- src/?/policy.lua allows us to require apicast.policy.apolicy + lpath = path.join(root, 'spec/?.lua;') .. path.join(root, 'gateway/src/?.lua;gateway/src/?/policy.lua'), } if ci then diff --git a/CHANGELOG.md b/CHANGELOG.md index a881ee5fb..6afafa5c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased +## Added + +- Definition of JSON schemas for policy configurations [PR #522](https://github.com/3scale/apicast/pull/522) + ## Fixed - Detecting local rover installation from the CLI [PR #519](https://github.com/3scale/apicast/pull/519) diff --git a/doc/policies.md b/doc/policies.md index f83deef06..814502128 100644 --- a/doc/policies.md +++ b/doc/policies.md @@ -72,8 +72,8 @@ replaceable with custom ones. ## Write your own policy To write your own policy you need to write a Lua module that instantiates a -[Policy](../gateway/src/apicast/policy.lua) and defines a method for each of -the phases where it needs to execute something. +[Policy](../gateway/src/apicast/policy/policy.lua) and defines a method for +each of the phases where it needs to execute something. Suppose that we wanted to run a policy that logged a message in the `rewrite` and the `header_filter` phases. This is how our module would look @@ -125,10 +125,10 @@ end In the [policy folder](../gateway/src/apicast/policy) you can find several policies. These ones are quite simple and can be used as examples to write your own: -- [Echo](../gateway/src/apicast/policy/echo.lua) -- [Phase logger](../gateway/src/apicast/policy/phase_logger.lua) -- [CORS](../gateway/src/apicast/policy/cors.lua) -- [Headers](../gateway/src/apicast/policy/headers.lua) +- [Echo](../gateway/src/apicast/policy/echo) +- [Phase logger](../gateway/src/apicast/policy/phase_logger) +- [CORS](../gateway/src/apicast/policy/cors) +- [Headers](../gateway/src/apicast/policy/headers) ## Integrate your policies diff --git a/examples/policy_chain/README.md b/examples/policy_chain/README.md index a6f33624c..dab382ab1 100644 --- a/examples/policy_chain/README.md +++ b/examples/policy_chain/README.md @@ -4,7 +4,7 @@ Environment configuration can define the global policy chain. You can provide cu ## Using Echo Policy -[Echo policy](../../gateway/src/apicast/policy/echo.lua) accepts configuration option to terminate the request phase. See the example in [`configuration.lua`](./configuration.lua). +[Echo policy](../../gateway/src/apicast/policy/echo) accepts configuration option to terminate the request phase. See the example in [`configuration.lua`](./configuration.lua). You can start it as: diff --git a/gateway/bin/apicast b/gateway/bin/apicast index 054293d0f..85607d1ec 100755 --- a/gateway/bin/apicast +++ b/gateway/bin/apicast @@ -23,7 +23,8 @@ if ($rover && !$lua_path) { chdir $apicast; -$ENV{LUA_PATH} = "$apicast/src/?.lua;${lua_path}"; +# src/?/policy.lua allows us to require apicast.policy.apolicy +$ENV{LUA_PATH} = "$apicast/src/?.lua;$apicast/src/?/policy.lua;${lua_path}"; $ENV{PWD} = $cwd; my @args = ('resty', "$bindir/cli", @ARGV); diff --git a/gateway/conf/nginx.conf.liquid b/gateway/conf/nginx.conf.liquid index 112e43eba..636a72044 100644 --- a/gateway/conf/nginx.conf.liquid +++ b/gateway/conf/nginx.conf.liquid @@ -42,7 +42,8 @@ http { log_format time '[$time_local] $host:$server_port $remote_addr:$remote_port "$request" $status $body_bytes_sent ($request_time) $post_action_impact'; access_log off; - lua_package_path ";;{{prefix}}/?.lua;{{prefix}}/src/?.lua"; + # src/?/policy.lua allows us to require apicast.policy.apolicy + lua_package_path ";;{{prefix}}/?.lua;{{prefix}}/src/?.lua;{{prefix}}/src/?/policy.lua"; {% if nameservers %} resolver {{ nameservers | join: " " }}; diff --git a/gateway/libexec/boot.lua b/gateway/libexec/boot.lua index 9d9fb4675..feb1077c7 100644 --- a/gateway/libexec/boot.lua +++ b/gateway/libexec/boot.lua @@ -1,5 +1,7 @@ pcall(require, 'luarocks.loader') -package.path = package.path .. ";./src/?.lua" + +-- src/?/policy.lua allows us to require apicast.policy.apolicy +package.path = package.path .. ";./src/?.lua;./src/?/policy.lua" local configuration = require 'apicast.configuration_loader' diff --git a/gateway/src/apicast/policy/apicast.lua b/gateway/src/apicast/policy/apicast/policy.lua similarity index 100% rename from gateway/src/apicast/policy/apicast.lua rename to gateway/src/apicast/policy/apicast/policy.lua diff --git a/gateway/src/apicast/policy/cors.lua b/gateway/src/apicast/policy/cors/policy.lua similarity index 100% rename from gateway/src/apicast/policy/cors.lua rename to gateway/src/apicast/policy/cors/policy.lua diff --git a/gateway/src/apicast/policy/cors/schema.json b/gateway/src/apicast/policy/cors/schema.json new file mode 100644 index 000000000..af482ff55 --- /dev/null +++ b/gateway/src/apicast/policy/cors/schema.json @@ -0,0 +1,36 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CORS policy configuration", + "type": "object", + "properties": { + "allow_headers": { + "type": "array", + "items": { + "type": "string" + } + }, + "allow_methods": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "GET", + "HEAD", + "POST", + "PUT", + "DELETE", + "PATCH", + "OPTIONS", + "TRACE", + "CONNECT" + ] + } + }, + "allow_origin": { + "type": "string" + }, + "allow_credentials": { + "type": "boolean" + } + } +} diff --git a/gateway/src/apicast/policy/echo.lua b/gateway/src/apicast/policy/echo/policy.lua similarity index 100% rename from gateway/src/apicast/policy/echo.lua rename to gateway/src/apicast/policy/echo/policy.lua diff --git a/gateway/src/apicast/policy/echo/schema.json b/gateway/src/apicast/policy/echo/schema.json new file mode 100644 index 000000000..c8354195c --- /dev/null +++ b/gateway/src/apicast/policy/echo/schema.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Echo policy configuration", + "type": "object", + "properties": { + "status": { + "type": "integer" + }, + "exit": { + "type": "string", + "enum": ["request", "phase"] + } + } +} diff --git a/gateway/src/apicast/policy/find_service.lua b/gateway/src/apicast/policy/find_service/policy.lua similarity index 100% rename from gateway/src/apicast/policy/find_service.lua rename to gateway/src/apicast/policy/find_service/policy.lua diff --git a/gateway/src/apicast/policy/headers.lua b/gateway/src/apicast/policy/headers/policy.lua similarity index 100% rename from gateway/src/apicast/policy/headers.lua rename to gateway/src/apicast/policy/headers/policy.lua diff --git a/gateway/src/apicast/policy/headers/schema.json b/gateway/src/apicast/policy/headers/schema.json new file mode 100644 index 000000000..65b101abe --- /dev/null +++ b/gateway/src/apicast/policy/headers/schema.json @@ -0,0 +1,30 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Headers policy configuration", + "type": "object", + "definitions": { + "commands": { + "type": "array", + "items": { + "type": "object", + "properties": { + "op": { + "type": "string", + "enum": ["add", "set", "push"] + }, + "header": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": ["op", "header", "value"] + } + } + }, + "properties": { + "request": { "$ref": "#/definitions/commands" }, + "response": { "$ref": "#/definitions/commands" } + } +} diff --git a/gateway/src/apicast/policy/load_configuration.lua b/gateway/src/apicast/policy/load_configuration/policy.lua similarity index 100% rename from gateway/src/apicast/policy/load_configuration.lua rename to gateway/src/apicast/policy/load_configuration/policy.lua diff --git a/gateway/src/apicast/policy/local_chain.lua b/gateway/src/apicast/policy/local_chain/policy.lua similarity index 100% rename from gateway/src/apicast/policy/local_chain.lua rename to gateway/src/apicast/policy/local_chain/policy.lua diff --git a/gateway/src/apicast/policy/phase_logger.lua b/gateway/src/apicast/policy/phase_logger/policy.lua similarity index 100% rename from gateway/src/apicast/policy/phase_logger.lua rename to gateway/src/apicast/policy/phase_logger/policy.lua diff --git a/gateway/src/apicast/policy.lua b/gateway/src/apicast/policy/policy.lua similarity index 100% rename from gateway/src/apicast/policy.lua rename to gateway/src/apicast/policy/policy.lua diff --git a/spec/policy/apicast_spec.lua b/spec/policy/apicast/policy_spec.lua similarity index 100% rename from spec/policy/apicast_spec.lua rename to spec/policy/apicast/policy_spec.lua diff --git a/spec/policy/find_service_spec.lua b/spec/policy/find_service/policy_spec.lua similarity index 100% rename from spec/policy/find_service_spec.lua rename to spec/policy/find_service/policy_spec.lua diff --git a/spec/policy/load_configuration_spec.lua b/spec/policy/load_configuration/policy_spec.lua similarity index 100% rename from spec/policy/load_configuration_spec.lua rename to spec/policy/load_configuration/policy_spec.lua diff --git a/t/TestAPIcast.pm b/t/TestAPIcast.pm index da0c1fccb..8d2233862 100644 --- a/t/TestAPIcast.pm +++ b/t/TestAPIcast.pm @@ -16,7 +16,8 @@ our $path = $ENV{TEST_NGINX_APICAST_PATH} ||= "$pwd/gateway"; our $spec = "$pwd/spec"; our $servroot = $Test::Nginx::Util::ServRoot; -$ENV{TEST_NGINX_LUA_PATH} = "$path/src/?.lua;;"; +# src/?/policy.lua allows us to require apicast.policy.apolicy +$ENV{TEST_NGINX_LUA_PATH} = "$path/src/?.lua;$path/src/?/policy.lua;;"; $ENV{TEST_NGINX_MANAGEMENT_CONFIG} = "$path/conf.d/management.conf"; $ENV{TEST_NGINX_UPSTREAM_CONFIG} = "$path/http.d/upstream.conf"; $ENV{TEST_NGINX_BACKEND_CONFIG} = "$path/conf.d/backend.conf";