Skip to content

Commit

Permalink
Add support for set-variable in operation-switch (#282)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexsong93 authored and mhamann committed Mar 13, 2018
1 parent c389313 commit 8ad9bbb
Show file tree
Hide file tree
Showing 5 changed files with 308 additions and 54 deletions.
24 changes: 24 additions & 0 deletions scripts/lua/lib/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,28 @@ function _Utils.hash(str)
return resty_str.to_hex(digest)
end

--- Return the length of the table
-- @param table
function _Utils.tableLength(table)
local count = 0
for _ in pairs(table) do
count = count + 1
end
return count
end

--- Create a deep clone of the given table
-- @param table table to clone
function _Utils.deepCloneTable(table)
local tblRes = {}
if type(table) == "table" then
for k,v in pairs(table) do
tblRes[k] = _Utils.deepCloneTable(v)
end
else
tblRes = table
end
return tblRes
end

return _Utils
119 changes: 86 additions & 33 deletions scripts/lua/management/lib/swagger.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
-- Module for parsing swagger file

local _M = {}
local utils = require "lib/utils"

-- Convert passed-in swagger body to valid lua table
-- @param swagger swagger file to parse
Expand All @@ -38,16 +39,34 @@ function _M.parseSwagger(swagger)
for verb, value in pairs(verbObj) do
decoded.resources[path].operations[verb] = {}
local verbObj = decoded.resources[path].operations[verb]
verbObj.policies = utils.deepCloneTable(policies) or {}
verbObj.security = security
if backends ~= nil then
local backend = (backends["all"] ~= nil) and backends["all"] or backends[value.operationId]
verbObj.backendUrl = backend.backendUrl
verbObj.backendMethod = (backend.backendMethod == 'keep') and verb or backend.backendMethod
if backend.policy ~= nil then
local globalReqMappingPolicy = nil;
for _, policy in pairs(verbObj.policies) do
if policy.type == 'reqMapping' then
globalReqMappingPolicy = policy;
end
end
if globalReqMappingPolicy ~= nil then
for _, v in pairs(backend.policy.value) do
globalReqMappingPolicy.value[#globalReqMappingPolicy.value+1] = v
end
else
verbObj.policies[#verbObj.policies+1] = {
type = 'reqMapping',
value = backend.policy.value
}
end
end
else
verbObj.backendUrl = ''
verbObj.backendMethod = verb
end
verbObj.policies = policies
verbObj.security = security
end
end
return decoded
Expand All @@ -66,10 +85,18 @@ function parseBackends(swagger)
local caseObj = v.case
for _, case in pairs(caseObj) do
for _, op in pairs(case.operations) do
res[op] = {
backendUrl = case.execute[1]["invoke"]["target-url"],
backendMethod = case.execute[1]["invoke"].verb
}
res[op] = {}
for _, opPolicy in pairs(case.execute) do
if opPolicy.invoke ~= nil then
res[op].backendUrl = opPolicy.invoke["target-url"]
res[op].backendMethod = opPolicy.invoke.verb
elseif opPolicy["set-variable"] ~= nil then
local reqMappingPolicy = parseRequestMapping(case)
if reqMappingPolicy ~= nil then
res[op].policy = reqMappingPolicy
end
end
end
end
end
return res
Expand All @@ -91,17 +118,27 @@ end
function parsePolicies(swagger)
local policies = {}
-- parse rate limit
policies = parseRateLimit(swagger, policies)
policies = parseRequestMapping(swagger, policies)
local rlObj = swagger["x-gateway-rate-limit"]
rlObj = (rlObj == nil) and swagger["x-ibm-rate-limit"] or rlObj
local rateLimitPolicy = parseRateLimit(rlObj)
if rateLimitPolicy ~= nil then
policies[#policies+1] = rateLimitPolicy
end
-- parse set-variable
local configObj = swagger["x-gateway-configuration"]
configObj = (configObj == nil) and swagger["x-ibm-configuration"] or configObj
if configObj ~= nil then
local reqMappingPolicy = parseRequestMapping(configObj.assembly)
if reqMappingPolicy ~= nil then
policies[#policies+1] = reqMappingPolicy
end
end
return policies
end

--- Parse rate limit
function parseRateLimit(swagger, policies)
local rlObj = swagger["x-gateway-rate-limit"]
rlObj = (rlObj == nil) and swagger["x-ibm-rate-limit"] or rlObj
local unit
if rlObj ~= nil then
function parseRateLimit(rlObj)
if rlObj ~= nil and rlObj[1] ~= nil then
rlObj = rlObj[1]
if rlObj.unit == "second" then
unit = 1
Expand All @@ -114,7 +151,7 @@ function parseRateLimit(swagger, policies)
else
unit = 60 -- default to minute
end
policies[#policies+1] = {
return {
type = "rateLimit",
value = {
interval = unit * rlObj.units,
Expand All @@ -124,14 +161,14 @@ function parseRateLimit(swagger, policies)
}
}
end
return policies
return nil
end

--- Parse request mapping
function parseRequestMapping(swagger, policies)
function parseRequestMapping(configObj)
local valueList = {}
if swagger["x-ibm-configuration"] ~= nil then
for _, obj in pairs(swagger["x-ibm-configuration"].assembly.execute) do
if configObj ~= nil then
for _, obj in pairs(configObj.execute) do
for policy, v in pairs(obj) do
if policy == "set-variable" then
for _, actionObj in pairs(v.actions) do
Expand All @@ -156,12 +193,13 @@ function parseRequestMapping(swagger, policies)
end
end
if next(valueList) ~= nil then
policies[#policies+1] ={
return {
type = "reqMapping",
value = valueList
}
else
return nil
end
return policies
end

--- Parse security in swagger
Expand All @@ -170,19 +208,34 @@ function parseSecurity(swagger)
local security = {}
if swagger["securityDefinitions"] ~= nil then
local secObject = swagger["securityDefinitions"]
for key, sec in pairs(secObject) do
if sec.type == 'apiKey' then
security[#security+1] = {
type = sec.type,
scope = "api",
header = sec.name
}
elseif sec.type == 'oauth2' then
security[#security+1] = {
type = sec.type,
scope = "api",
provider = key
}
if utils.tableLength(secObject) == 2 then
secObj = {
type = 'clientSecret',
scope = 'api'
}
for key, sec in pairs(secObject) do
if key == 'client_id' then
secObj.idFieldName = sec.name
elseif key == 'client_secret' then
secObj.secretFieldName = sec.name
end
end
security[#security+1] = secObj
else
for key, sec in pairs(secObject) do
if sec.type == 'apiKey' then
security[#security+1] = {
type = sec.type,
scope = "api",
header = sec.name
}
elseif sec.type == 'oauth2' then
security[#security+1] = {
type = sec.type,
scope = "api",
provider = key
}
end
end
end
end
Expand Down
12 changes: 11 additions & 1 deletion tests/scripts/lua/management/examples/example2.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"rate": 100
}
],
"x-ibm-configuration": {
"x-gateway-configuration": {
"assembly": {
"execute": [
{
Expand All @@ -83,6 +83,16 @@
"getHello"
],
"execute": [
{
"set-variable": {
"actions": [
{
"set": "message.headers.foo",
"value": "bar"
}
]
}
},
{
"invoke": {
"target-url": "https://openwhisk.ng.bluemix.net/api/some/action/path.http",
Expand Down
102 changes: 102 additions & 0 deletions tests/scripts/lua/management/examples/example3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
{
"swagger": "2.0",
"info": {
"version": "1.0",
"title": "Hello World API"
},
"basePath": "/whisk2",
"schemes": [
"https"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/bye": {
"get": {
"operationId": "getBye",
"description": "Returns a greeting to the user!",
"responses": {
"200": {
"description": "Returns the greeting.",
"schema": {
"type": "string"
}
},
"400": {
"description": "Invalid characters in \"user\" were provided."
}
}
},
"post": {
"operationId": "postBye",
"description": null
}
}
},
"securityDefinitions": {},
"security": [],
"x-ibm-rate-limit": [],
"x-gateway-configuration": {
"assembly": {
"execute": [
{
"operation-switch": {
"case": [
{
"operations": [
"getBye"
],
"execute": [
{
"set-variable": {
"actions": [
{
"set": "message.headers.foo",
"value": "bar"
}
]
}
},
{
"set-variable": {
"actions": [
{
"set": "message.headers.hello",
"value": "world"
}
]
}
},
{
"invoke": {
"target-url": "https://openwhisk.ng.bluemix.net/api/some/action/path.http",
"verb": "keep"
}
}
]
},
{
"operations": [
"postBye"
],
"execute": [
{
"invoke": {
"target-url": "https://openwhisk.ng.bluemix.net/api/[email protected]/demo/createuser",
"verb": "keep"
}
}
]
}
],
"otherwise": []
}
}
]
}
}
}
Loading

0 comments on commit 8ad9bbb

Please sign in to comment.