From b60e25f1db7f75ba162026ff7fe46f0a559b886b Mon Sep 17 00:00:00 2001 From: Elvin Efendi Date: Mon, 13 Apr 2020 00:10:01 -0400 Subject: [PATCH] ingress-nginx lua plugins documentation --- .../nginx-configuration/configmap.md | 3 +- rootfs/etc/nginx/lua/plugins/README.md | 35 +++++++++++++++++++ .../nginx/lua/plugins/hello_world/main.lua | 6 +--- .../nginx/lua/plugins/hello_world/test/.empty | 0 .../plugins/hello_world/test/main_test.lua | 25 +++++++++++++ 5 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 rootfs/etc/nginx/lua/plugins/README.md delete mode 100644 rootfs/etc/nginx/lua/plugins/hello_world/test/.empty create mode 100644 rootfs/etc/nginx/lua/plugins/hello_world/test/main_test.lua diff --git a/docs/user-guide/nginx-configuration/configmap.md b/docs/user-guide/nginx-configuration/configmap.md index b736550b3..ba1fc54a2 100755 --- a/docs/user-guide/nginx-configuration/configmap.md +++ b/docs/user-guide/nginx-configuration/configmap.md @@ -468,8 +468,7 @@ _References:_ ## plugins -Configures plugins to use placed in the directory /etc/nginx/lua/plugins. Every plugin has to have main.lua in the root. -Every plugin has to bundle all of its dependencies. The execution order follows the definition. +Activates plugins installed in `/etc/nginx/lua/plugins`. Refer to [ingress-nginx plugins README](../../../rootfs/etc/nginx/lua/plugins/README.md) for more information on how to write and install a plugin. ## server-tokens diff --git a/rootfs/etc/nginx/lua/plugins/README.md b/rootfs/etc/nginx/lua/plugins/README.md new file mode 100644 index 000000000..f22ed0070 --- /dev/null +++ b/rootfs/etc/nginx/lua/plugins/README.md @@ -0,0 +1,35 @@ +# Custom Lua plugins + +ingress-nginx uses [https://github.com/openresty/lua-nginx-module](https://github.com/openresty/lua-nginx-module) to run custom Lua code +within Nginx workers. It is recommended to familiarize yourself with that ecosystem before deploying your custom Lua based ingress-nginx plugin. + +### Writing a plugin + +Every ingress-nginx Lua plugin is expected to have `main.lua` file and all of its dependencies. +`main.lua` is the entry point of the plugin. The plugin manager uses convention over configuration +strategy and automatically runs functions defined in `main.lua` in the corresponding Nginx phase based on their name. + +Nginx has different [request processing phases](http://nginx.org/en/docs/dev/development_guide.html#http_phases). +By defining functions with the following names, you can run your custom Lua code in the corresponding Nginx phase: + + - `init_worker`: useful for initializing some data per Nginx worker process + - `rewrite`: useful for modifying request, changing headers, redirection, dropping request, doing authentication etc + - `header`: this is called when backend response header is received, it is useful for modifying response headers + - `log`: this is called when request processing is commpleted and response is delivered to the client + +Check this [`hello_world`](https://github.com/kubernetes/ingress-nginx/tree/master/rootfs/etc/nginx/lua/plugins/hello_world) plugin as a simple example or refer to [OpenID Connect integration](https://github.com/ElvinEfendi/ingress-nginx-openidc/tree/master/rootfs/etc/nginx/lua/plugins/openidc) for more advanced usage. + +Do not forget to write tests for your plugin. + +### Installing a plugin + +There are two options: + + - mount your plugin into `/etc/nginx/lua/plugins/` in the ingress-nginx pod + - build your own ingress-nginx image like it is done in the [example](https://github.com/ElvinEfendi/ingress-nginx-openidc/tree/master/rootfs/etc/nginx/lua/plugins/openidc) and install your plugin during image build + +Mounting is the quickest option. + +### Enabling plugins + +Once your plugin is ready you need to use [`plugins` configuration setting](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#plugins) to activate it. Let's say you want to active `hello_world` and `open_idc` plugins, then you set `plugins` setting to `"hello_world, open_idc"`. _Note_ that the plugins will be executed in the given order. diff --git a/rootfs/etc/nginx/lua/plugins/hello_world/main.lua b/rootfs/etc/nginx/lua/plugins/hello_world/main.lua index 799daa33e..af56b956a 100644 --- a/rootfs/etc/nginx/lua/plugins/hello_world/main.lua +++ b/rootfs/etc/nginx/lua/plugins/hello_world/main.lua @@ -1,14 +1,10 @@ local _M = {} function _M.rewrite() - ngx.req.set_header("x-hello-world", "1") -end - -function _M.access() local ua = ngx.var.http_user_agent if ua == "hello" then - ngx.exit(403) + ngx.req.set_header("x-hello-world", "1") end end diff --git a/rootfs/etc/nginx/lua/plugins/hello_world/test/.empty b/rootfs/etc/nginx/lua/plugins/hello_world/test/.empty deleted file mode 100644 index e69de29bb..000000000 diff --git a/rootfs/etc/nginx/lua/plugins/hello_world/test/main_test.lua b/rootfs/etc/nginx/lua/plugins/hello_world/test/main_test.lua new file mode 100644 index 000000000..20e914be1 --- /dev/null +++ b/rootfs/etc/nginx/lua/plugins/hello_world/test/main_test.lua @@ -0,0 +1,25 @@ +_G._TEST = true + +local main = require("plugins.hello_world.main") + +-- The unit tests are run within a timer phase in a headless Nginx process. +-- Since `set_header` and `ngx.var.http_` API are disabled in this phase we have to stub it +-- to avoid `API disabled in the current context` error. + +describe("main", function() + describe("rewrite", function() + it("sets x-hello-world header to 1 when user agent is hello", function() + ngx.var = { http_user_agent = "hello" } + stub(ngx.req, "set_header") + main.rewrite() + assert.stub(ngx.req.set_header).was_called_with("x-hello-world", "1") + end) + + it("does not set x-hello-world header to 1 when user agent is not hello", function() + ngx.var = { http_user_agent = "not-hello" } + stub(ngx.req, "set_header") + main.rewrite() + assert.stub(ngx.req.set_header).was_not_called_with("x-hello-world", "1") + end) + end) +end)