Skip to content

Commit

Permalink
[example] describe module inheritance
Browse files Browse the repository at this point in the history
with an example blacklist module

[spec] test blacklist example
  • Loading branch information
mikz committed May 10, 2017
1 parent af3d333 commit 9565e6a
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 3 deletions.
37 changes: 37 additions & 0 deletions examples/custom-module/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,40 @@ And see in the apicast output:
```
2016/11/16 16:52:00 [warn] 98009#0: *5 [lua] verbose.lua:7: call(): upstream response time: 0.001 upstream connect time: 0.000 while logging request, client: 127.0.0.1, server: _, request: "GET /?user_key=foo HTTP/1.1", upstream: "http://127.0.0.1:8081/?user_key=foo", host: "echo"
```

## Writing own module

There is example module of IP blacklist in [`blacklist.lua`](blacklist.lua).

To honour the module inheritance, but still be able to override some methods from the `apicast` module, you'll
need some clever use of metatables. Here is a recommended skeleton of the module inheritance:

```lua
-- load and initialize the parent module
local apicast = require('apicast').new()

-- _NAME and _VERSION are used in User-Agent when connecting to the Service Management API
local _M = { _VERSION = '0.0', _NAME = 'Example Module' }
-- define a table, that is going to be this module metatable
-- if your table does not define a property, __index is going to get used
-- and so on until there are no metatables to check
-- so in this case the inheritance works like mod -> _M -> apicast
local mt = { __index = setmetatable(_M, { __index = apicast }) }

function _M.new()
-- this method is going to get called after this file is required
-- so create new table for internal state (global) and set the metatable for inheritance
return setmetatable({}, mt)
end

-- to run some custom code in log phase lets override the method
function _M.log()
ngx.log(ngx.WARN,
'upstream response time: ', ngx.var.upstream_response_time, ' ',
'upstream connect time: ', ngx.var.upstream_connect_time)
-- and the original apicast method should be executed too
return apicast:log()
end

return _M
```
70 changes: 70 additions & 0 deletions examples/custom-module/blacklist.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
local apicast = require('apicast').new()
local iputils = require("resty.iputils")
local default_balancer = require('resty.balancer.round_robin').call
local resty_balancer = require('resty.balancer')

local _M = { _VERSION = '0.0' }
local mt = { __index = setmetatable(_M, { __index = apicast }) }

local ipv4 = {
unspecified = { '0.0.0.0/8' },
broadcast = { '255.255.255.255/32' },
multicast = { '224.0.0.0/4' },
linkLocal = { '169.254.0.0/16' },
loopback = { '127.0.0.0/8' },
private = { '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16' },
reserved = { '192.0.0.0/24' }
}

local blacklist = {}

for _,cidrs in pairs(ipv4) do
local list = iputils.parse_cidrs(cidrs)

for i=1,#list do
table.insert(blacklist, list[i])
end
end


function _M.new()
return setmetatable({
blacklist = blacklist
}, mt)
end

function _M:init()
iputils.enable_lrucache()
apicast:init()
end

local balancer_with_blacklist = resty_balancer.new(function(peers)
local peer, i = default_balancer(peers)

local ip = peer[1]
local blacklisted, err = iputils.ip_in_cidrs(ip, blacklist)

if blacklisted then
return nil, 'blacklisted'
elseif err then
return nil, err
else
return peer, i
end
end)

function _M:balancer()
local balancer = balancer_with_blacklist
local host = ngx.var.proxy_host -- NYI: return to lower frame
local peers = balancer:peers(ngx.ctx[host])

local peer, err = balancer:set_peer(peers)

if not peer then
ngx.status = ngx.HTTP_SERVICE_UNAVAILABLE
ngx.log(ngx.ERR, "failed to set current backend peer: ", err)
ngx.exit(ngx.status)
end
end

return _M
8 changes: 5 additions & 3 deletions examples/custom-module/verbose.lua
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
local apicast = require('apicast')
local apicast = require('apicast').new()

local _M = { _VERSION = '0.0' }
local mt = { __index = setmetatable(_M, { __index = apicast }) }

function _M.new()
return setmetatable(_M, { __index = apicast.new() })
return setmetatable({}, mt)
end

function _M.log()
ngx.log(ngx.WARN,
'upstream response time: ', ngx.var.upstream_response_time, ' ',
'upstream connect time: ', ngx.var.upstream_connect_time)
return apicast:log()
end

return _M
return _M
24 changes: 24 additions & 0 deletions spec/examples/custom-module/blacklist_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
local _M = require 'examples.custom-module.blacklist'
local apicast = require 'apicast'

describe('blacklist', function()
it('returns new module instance', function()
local blacklist = _M.new()

assert.table(blacklist)
assert.equal(_M.balancer, blacklist.balancer)
assert.equal(_M.init, blacklist.init)
end)

it('has all apicast methods', function()
local blacklist = _M.new()

assert['function'](blacklist.init)

for _,fun in ipairs{'init_worker', 'rewrite', 'post_action', 'access', 'log'} do
assert.equal(apicast[fun], blacklist[fun], fun .. " is not inherited from apicast")
end

assert['function'](blacklist.balancer)
end)
end)

0 comments on commit 9565e6a

Please sign in to comment.