Implement API CRUD operations
diff --git a/api-gateway-config/conf.d/management_apis.conf b/api-gateway-config/conf.d/management_apis.conf
index 92af22d..0d9e30d 100644
--- a/api-gateway-config/conf.d/management_apis.conf
+++ b/api-gateway-config/conf.d/management_apis.conf
@@ -38,14 +38,13 @@
             local mgmt = require("management")
             local requestMethod = ngx.req.get_method()
             if requestMethod == "GET" then
-                mgmt.getResource()
+                mgmt.getAPIs()
             elseif requestMethod == "PUT" then
                 mgmt.addAPI()
             elseif requestMethod == "POST" then
-                ngx.status = 400
-                ngx.say("Use PUT")
+                mgmt.addAPI()
             elseif requestMethod == "DELETE" then
-                mgmt.deleteResource()
+                mgmt.deleteAPI()
             else
                 ngx.status = 400
                 ngx.say("Invalid verb")
diff --git a/api-gateway-config/scripts/lua/lib/redis.lua b/api-gateway-config/scripts/lua/lib/redis.lua
index 1369c7a..7ea41b2 100644
--- a/api-gateway-config/scripts/lua/lib/redis.lua
+++ b/api-gateway-config/scripts/lua/lib/redis.lua
@@ -33,6 +33,10 @@
 
 local _M = {}
 
+----------------------------
+-- Initialization/Cleanup --
+----------------------------
+
 --- Initialize and connect to Redis
 -- @param host redis host
 -- @param port redis port
@@ -78,6 +82,59 @@
   end
 end
 
+---------------------------
+----------- APIs ----------
+---------------------------
+
+--- Add API to redis
+-- @param red Redis client instance
+-- @param id id of API
+-- @param apiObj the api to add
+function _M.addAPI(red, id, apiObj)
+  local ok, err = red:hset("apis", id, apiObj)
+  if not ok then
+    request.err(500, utils.concatStrings({"Failed adding API to redis: ", err}))
+  end
+end
+
+--- Get all APIs from redis
+-- @param red Redis client instance
+function _M.getAllAPIs(red)
+  local res, err = red:hgetall("apis")
+  if not res then
+    request.err(500, utils.concatStrings({"Failed getting APIs from redis: ", err}))
+  end
+  return res
+end
+
+--- Get a single API from redis given its id
+-- @param redis Redis client instance
+-- @param id id of API to get
+function _M.getAPI(red, id)
+  local api, err = red:hget("apis", id)
+  if not api then
+    request.err(500, utils.concatStrings({"Failed getting API from redis: ", err}))
+  end
+  if api == ngx.null then
+    request.err(404, utils.concatStrings({"Unknown API id ", id, "."}))
+  end
+  return cjson.decode(api)
+end
+
+--- Delete an API from redis given its id
+-- @param redis Redis client instance
+-- @param id id of API to delete
+function _M.deleteAPI(red, id)
+  local ok, err = red:hdel("apis", id)
+  if not ok then
+    request.err(500, utils.concatStrings({"Failed deleting API from redis: ", err}))
+  end
+end
+
+-----------------------------
+--------- Resources ---------
+-----------------------------
+
 --- Generate Redis object for resource
 -- @param ops list of operations for a given resource
 -- @param apiId resource api id (nil if no api)
@@ -155,6 +212,10 @@
   end
 end
 
+-----------------------------
+--- API Key Subscriptions ---
+-----------------------------
+
 --- Create/update subscription/apikey in redis
 -- @param red redis client instance
 -- @param key redis subscription key to create
@@ -183,6 +244,10 @@
   end
 end
 
+-----------------------------------
+------- Pub/Sub with Redis --------
+-----------------------------------
+
 --- Subscribe to redis
 -- @param redisSubClient the redis client that is listening for the redis key changes
 -- @param redisGetClient the redis client that gets the changed resource to update the conf file
diff --git a/api-gateway-config/scripts/lua/lib/utils.lua b/api-gateway-config/scripts/lua/lib/utils.lua
index fe49819..003b74d 100644
--- a/api-gateway-config/scripts/lua/lib/utils.lua
+++ b/api-gateway-config/scripts/lua/lib/utils.lua
@@ -75,9 +75,20 @@
   return concatStrings({"(?<path_" , x , ">([a-zA-Z0-9\\-\\s\\_\\%]*))"})
 end
 
+--- Generate random uuid
+function uuid()
+  local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
+  math.randomseed(os.time())
+  return string.gsub(template, '[xy]', function (c)
+    local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
+    return string.format('%x', v)
+  end)
+end
+
 _Utils.concatStrings = concatStrings
 _Utils.serializeTable = serializeTable
 _Utils.convertTemplatedPathParam = convertTemplatedPathParam
+_Utils.uuid = uuid
 
 return _Utils
 
diff --git a/api-gateway-config/scripts/lua/management.lua b/api-gateway-config/scripts/lua/management.lua
index 194fabd..8cd3a65 100644
--- a/api-gateway-config/scripts/lua/management.lua
+++ b/api-gateway-config/scripts/lua/management.lua
@@ -36,7 +36,11 @@
 
 local _M = {}
 
---- Add/update a resource to redis and create/update an nginx conf file given PUT JSON body
+--------------------------
+---------- APIs ----------
+--------------------------
+
+--- Add an api to the Gateway
 -- PUT http://0.0.0.0:9000/APIs
 -- PUT JSON body:
 -- {
@@ -71,10 +75,11 @@
     local gatewayPath = utils.concatStrings({basePath, ngx.escape_uri(path)})
     addResource(red, resource, gatewayPath, decoded.tenantId)
   end
-  -- Add current redis connection in the ngx_lua cosocket connection pool
-  redis.close(red)
-  -- Return managed url object
+  -- Generate random uuid for api
+  local uuid = utils.uuid()
+  -- Create managed url object
   local managedUrlObj = {
+    id = uuid,
     name = decoded.name,
     basePath = utils.concatStrings({"/", basePath}),
     tenantId = decoded.tenantId,
@@ -82,6 +87,11 @@
     managedUrl = utils.concatStrings({"http://0.0.0.0:8080/api/", decoded.tenantId, "/", basePath})
   }
   managedUrlObj = cjson.encode(managedUrlObj):gsub("\\", "")
+  -- Add API object to redis
+  redis.addAPI(red, uuid, managedUrlObj)
+  -- Add current redis connection in the ngx_lua cosocket connection pool
+  redis.close(red)
+  -- Return managed url object
   ngx.header.content_type = "application/json; charset=utf-8"
   request.success(200, managedUrlObj)
 end
@@ -169,57 +179,85 @@
   filemgmt.createResourceConf(BASE_CONF_DIR, tenantId, gatewayPath, resourceObj)
 end
 
---- Get resource from redis
--- GET http://0.0.0.0:9000/resources/<tenant>/<url-encoded-resource>
-function _M.getResource()
-  local requestURI = string.gsub(ngx.var.request_uri, "?.*", "")
-  local list = parseRequestURI(requestURI)
-  local tenant = list[2]
-  local gatewayPath = list[3]
-  local redisKey = utils.concatStrings({list[1], ":", tenant, ":", ngx.unescape_uri(gatewayPath)})
-  -- Initialize and connect to redis
-  local red = redis.init(REDIS_HOST, REDIS_PORT, REDIS_PASS, 1000)
-  local resourceObj = redis.getResource(red, redisKey, REDIS_FIELD)
-  if resourceObj == nil then
-    request.err(404, "Resource doesn't exist.")
+--- Get one or all APIs from the gateway
+-- PUT http://0.0.0.0:9000/APIs
+function _M.getAPIs()
+  local uri = string.gsub(ngx.var.request_uri, "?.*", "")
+  if uri:len() <= 6 then
+    getAllAPIs()
+  else
+    local id = uri:sub(7)
+    getAPI(id)
   end
-  -- Add current redis connection in the ngx_lua cosocket connection pool
-  redis.close(red)
-  -- Get available operations for the given resource
-  resourceObj = cjson.decode(resourceObj)
-  local operations = {}
-  for k in pairs(resourceObj.operations) do
-    operations[#operations+1] = k
-  end
-  -- Return managed url object
-  local managedUrlObj = {
-    managedUrl = utils.concatStrings({"http://0.0.0.0:8080/api/", tenant, "/", gatewayPath}),
-    availableOperations = operations
-  }
-  managedUrlObj = cjson.encode(managedUrlObj):gsub("\\", "")
-  ngx.header.content_type = "application/json; charset=utf-8"
-  request.success(200, managedUrlObj)
 end
 
---- Delete resource from redis
--- DELETE http://0.0.0.0:9000/resources/<tenant>/<url-encoded-resource>
-function _M.deleteResource()
-  local requestURI = string.gsub(ngx.var.request_uri, "?.*", "")
-  local list = parseRequestURI(requestURI)
-  local tenant = list[2]
-  local gatewayPath = list[3]
-  local redisKey = utils.concatStrings({list[1], ":", tenant, ":", ngx.unescape_uri(gatewayPath)})
-  -- Initialize and connect to redis
+--- Get all APIs in redis
+function getAllAPIs()
   local red = redis.init(REDIS_HOST, REDIS_PORT, REDIS_PASS, 1000)
-  -- Return if resource doesn't exist
-  redis.deleteResource(red, redisKey, REDIS_FIELD)
-  -- Delete conf file
-  filemgmt.deleteResourceConf(BASE_CONF_DIR, tenant, gatewayPath)
-  -- Add current redis connection in the ngx_lua cosocket connection pool
+  local res = redis.getAllAPIs(red)
   redis.close(red)
-  request.success(200, "Resource deleted.")
+  local apiList = {}
+  for k, v in pairs(res) do
+    if k%2 == 0 then
+      apiList[#apiList+1] = cjson.decode(v)
+    end
+  end
+  apiList = cjson.encode(apiList)
+  ngx.header.content_type = "application/json; charset=utf-8"
+  request.success(200, apiList)
 end
 
+--- Get API by its id
+-- @param id
+function getAPI(id)
+  local red = redis.init(REDIS_HOST, REDIS_PORT, REDIS_PASS, 1000)
+  local api = redis.getAPI(red, id)
+  redis.close(red)
+  ngx.header.content_type = "application/json; charset=utf-8"
+  request.success(200, cjson.encode(api))
+end
+
+--- Delete API from gateway
+-- DELETE http://0.0.0.0:9000/APIs/<id>
+function _M.deleteAPI()
+  local uri = string.gsub(ngx.var.request_uri, "?.*", "")
+  if uri:len() <= 6 then
+    request.err(400, "No id specified.")
+  end
+  local id = uri:sub(7)
+  local red = redis.init(REDIS_HOST, REDIS_PORT, REDIS_PASS, 1000)
+  local api = redis.getAPI(red, id)
+  -- Delete all resources for the API
+  local basePath = api.basePath:sub(2)
+  for path, v in pairs(api.resources) do
+    local gatewayPath = utils.concatStrings({basePath, ngx.escape_uri(path)})
+    deleteResource(red, gatewayPath, api.tenantId)
+  end
+  redis.deleteAPI(red, id)
+  redis.close(red)
+  request.success(200, {})
+end
+
+--- Helper function for deleting resource in redis and appropriate conf files
+-- @param red redis instance
+-- @param gatewayPath path in gateway
+-- @param tenantId tenant id
+function deleteResource(red, gatewayPath, tenantId)
+  local redisKey = utils.concatStrings({"resources:", tenantId, ":", ngx.unescape_uri(gatewayPath)})
+  redis.deleteResource(red, redisKey, REDIS_FIELD)
+  filemgmt.deleteResourceConf(BASE_CONF_DIR, tenantId, gatewayPath)
+end
+
+-----------------------------
+---------- Tenants ----------
+-----------------------------
+
+
+
+------------------------------
+----- Pub/Sub with Redis -----
+------------------------------
+
 --- Subscribe to redis
 -- GET http://0.0.0.0:9000/subscribe
 function _M.subscribe()
@@ -261,6 +299,10 @@
   request.success(200, "Subscription created.")
 end
 
+---------------------------
+------ Subscriptions ------
+---------------------------
+
 --- Delete apikey/subscription from redis
 -- DELETE http://0.0.0.0:9000/subscriptions
 -- Body: