SDEWAN API update 98/3298/1
authorHuifeng Le <huifeng.le@intel.com>
Tue, 17 Mar 2020 06:21:46 +0000 (14:21 +0800)
committerHuifeng Le <huifeng.le@intel.com>
Tue, 17 Mar 2020 06:25:52 +0000 (14:25 +0800)
update SDEWAN Rest API with plural format

Signed-off-by: Huifeng Le <huifeng.le@intel.com>
Change-Id: I83eb6ff24e4bb571162eb0a42df798da01ced7da

cnf/build/rest_v1/firewall_rest.lua
cnf/build/rest_v1/ipsec_rest.lua
cnf/build/rest_v1/mwan3_rest.lua
cnf/build/rest_v1/utils.lua
openwrt/mwan3.go
openwrt/openwrtclient.go

index d1531c8..28afdfd 100644 (file)
@@ -94,14 +94,10 @@ zone_checker = {
 function index()
     ver = "v1"
     configuration = "firewall"
-    entry({"sdewan", configuration, ver, "zones"}, call("get_zones"))
-    entry({"sdewan", configuration, ver, "redirects"}, call("get_redirects"))
-    entry({"sdewan", configuration, ver, "rules"}, call("get_rules"))
-    entry({"sdewan", configuration, ver, "forwardings"}, call("get_forwardings"))
-    entry({"sdewan", configuration, ver, "zone"}, call("handle_request")).leaf = true
-    entry({"sdewan", configuration, ver, "redirect"}, call("handle_request")).leaf = true
-    entry({"sdewan", configuration, ver, "rule"}, call("handle_request")).leaf = true
-    entry({"sdewan", configuration, ver, "forwarding"}, call("handle_request")).leaf = true
+    entry({"sdewan", configuration, ver, "zones"}, call("handle_request")).leaf = true
+    entry({"sdewan", configuration, ver, "redirects"}, call("handle_request")).leaf = true
+    entry({"sdewan", configuration, ver, "rules"}, call("handle_request")).leaf = true
+    entry({"sdewan", configuration, ver, "forwardings"}, call("handle_request")).leaf = true
 end
 
 function is_network_interface_available(interface)
@@ -215,11 +211,6 @@ function is_zone_available(name)
     return true, name
 end
 
--- get /zones
-function get_zones()
-    utils.handle_get_objects("zones", uci_conf, "zone", zone_validator)
-end
-
 -- delete a zone
 function delete_zone(name, check_used)
     -- check whether zone is defined
@@ -259,27 +250,9 @@ end
 function update_zone(zone)
     local name = zone.name
     res, code, msg = delete_zone(name, false)
-    if res == true then
+    if res == true or code == 404 then
         return utils.create_object(_M, firewall_processor, "zone", zone)
     end
 
     return false, code, msg
-end
-
--- Redirect APIs
--- get /redirects
-function get_redirects()
-    utils.handle_get_objects("redirects", uci_conf, "redirect", redirect_validator)
-end
-
--- Rule APIs
--- get /rules
-function get_rules()
-    utils.handle_get_objects("rules", uci_conf, "rule", rule_validator)
-end
-
--- Forwarding APIs
--- get /forwardings
-function get_forwardings()
-    utils.handle_get_objects("forwardings", uci_conf, "forwarding", forwarding_validator)
-end
+end
\ No newline at end of file
index a158941..244249c 100644 (file)
@@ -74,10 +74,8 @@ proposal_checker = {
 function index()
     ver = "v1"
     configuration = "ipsec"
-    entry({"sdewan", configuration, ver, "proposals"}, call("get_proposals"))
-    entry({"sdewan", configuration, ver, "sites"}, call("get_sites"))
-    entry({"sdewan", configuration, ver, "proposal"}, call("handle_request")).leaf = true
-    entry({"sdewan", configuration, ver, "site"}, call("handle_request")).leaf = true
+    entry({"sdewan", configuration, ver, "proposals"}, call("handle_request")).leaf = true
+    entry({"sdewan", configuration, ver, "sites"}, call("handle_request")).leaf = true
 end
 
 -- Request Handler
@@ -169,12 +167,6 @@ function save_connection(value)
     return true, ret_value
 end
 
--- Site APIs
--- get /sites
-function get_sites()
-    utils.handle_get_objects("sites", uci_conf, "remote", site_validator)
-end
-
 -- Proposal APIs
 -- check if proposal is used by connection, site
 function is_proposal_used(name)
@@ -186,10 +178,12 @@ function is_proposal_used(name)
         uci:foreach(uci_conf, section_name,
             function(section)
                 for j=1, #checker do
-                    for k=1, #section[checker[j]] do
-                        if name == section[checker[j]][k] then
-                            is_used = true
-                            return false
+                    if section[checker[j]] ~= nil then
+                        for k=1, #section[checker[j]] do
+                            if name == section[checker[j]][k] then
+                                is_used = true
+                                return false
+                            end
                         end
                     end
                 end
@@ -213,11 +207,6 @@ function is_proposal_available(name)
     return true, name
 end
 
--- get /proposals
-function get_proposals()
-    utils.handle_get_objects("proposals", uci_conf, "proposal", proposal_validator)
-end
-
 -- delete a proposal
 function delete_proposal(name, check_used)
     -- check whether proposal is defined
@@ -257,7 +246,7 @@ end
 function update_proposal(proposal)
     local name = proposal.name
     res, code, msg = delete_proposal(name, false)
-    if res == true then
+    if res == true or code == 404 then
         return utils.create_object(_M, ipsec_processor, "proposal", proposal)
     end
 
index dd801b0..05902fd 100644 (file)
@@ -34,17 +34,16 @@ rule_validator = {
 }
 
 mwan3_processor = {
-    policy={get="get_policy", update="update_policy", create="create_policy", delete="delete_policy", validator=policy_validator},
+    get_type=function(value) if value == "policies" then return "policy" elseif value == "rules" then return "rule" else return "" end end,
+    policy={gets="get_policies",get="get_policy", update="update_policy", create="create_policy", delete="delete_policy", validator=policy_validator},
     rule={validator=rule_validator},
     configuration="mwan3"
 }
 
 function index()
     ver = "v1"
-    entry({"sdewan", "mwan3", ver, "policies"}, call("get_policies"))
-    entry({"sdewan", "mwan3", ver, "rules"}, call("get_rules"))
-    entry({"sdewan", "mwan3", ver, "policy"}, call("handle_request")).leaf = true
-    entry({"sdewan", "mwan3", ver, "rule"}, call("handle_request")).leaf = true
+    entry({"sdewan", "mwan3", ver, "policies"}, call("handle_request")).leaf = true
+    entry({"sdewan", "mwan3", ver, "rules"}, call("handle_request")).leaf = true
 end
 
 -- Request Handler
@@ -84,6 +83,9 @@ function get_policy(name)
     if members == nil then
         return nil
     end
+    if members[".type"] ~= "policy" then
+        return nil
+    end
     members = members["use_member"]
 
     local policy = {}
@@ -124,7 +126,7 @@ function get_policies()
         end
     )
 
-    utils.response_object(res)
+    return res
 end
 
 -- create a policy
@@ -223,15 +225,9 @@ end
 function update_policy(policy)
     local name = policy.name
     res, code, msg = delete_policy(name, false)
-    if res == true then
+    if res == true or code == 404 then
         return create_policy(policy)
     end
 
     return false, code, msg
-end
-
--- Rule APIs
--- get /rules
-function get_rules()
-    utils.handle_get_objects("rules", "mwan3", "rule", rule_validator)
-end
+end
\ No newline at end of file
index 5e35951..f3627aa 100644 (file)
@@ -26,6 +26,10 @@ function start_with(s, prefix)
     return (string.find(s, "^" .. prefix) ~= nil)
 end
 
+function end_with(s, postfix)
+    return (string.find(s, postfix .. "$") ~= nil)
+end
+
 -- check ip
 function is_match(s, reg)
     local ret = string.match(s, reg)
@@ -195,6 +199,9 @@ function get_uci_section(configuration, validator, object_type, name)
             return nil
         end
     else
+        if object_data[".type"] ~= object_type then
+            return nil
+        end
         -- name is defined as section name
         local obj = {}
         obj["name"] = name
@@ -245,7 +252,7 @@ function set_data(configuration, data_validator, src, target)
                 else
                     if v["validator"] ~= nil and type(v["validator"]) == "table" then
                         if value.section ~= nil then
-                            target[name] = get_uci_section(configuration, value.section, value.name)
+                            target[name] = get_uci_section(configuration, v["validator"], value.section, value.name)
                         else
                             target[name] = get_uci_section(configuration, v["validator"], get_validator_type(v["validator"]), value)
                         end
@@ -259,30 +266,11 @@ function set_data(configuration, data_validator, src, target)
 end
 
 -- get
-function get_objects(type_names, configuration, type_name, validator)
-    local res = {}
-    res[type_names] = {}
-
-    local index = 1
-    uci:foreach(configuration, type_name,
-        function (section)
-            local obj = {}
-            obj["name"] = section[".name"]
-            set_data(configuration, validator, section, obj)
-            res[type_names][index] = obj
-            index = index + 1
-        end
-    )
-
-    return res
-end
-
-function handle_get_objects(type_names, configuration, type_name, validator)
-    if not (validate_req_method("GET")) then
-        return
+function get_object_type(value)
+    if end_with(value, "s") then
+        return string.sub(value, 1, string.len(value)-1)
     end
-
-    response_object(get_objects(type_names, configuration, type_name, validator))
+    return value
 end
 
 function get_object(module_table, processors, object_type, name)
@@ -291,26 +279,80 @@ function get_object(module_table, processors, object_type, name)
        and module_table[processors[object_type]["get"]] ~= nil then
             return module_table[processors[object_type]["get"]](name)
     else
-        return get_uci_section(processors["configuration"], processors[object_type].validator, object_type, name)
+        local object_conf_type = get_validator_type(processors[object_type].validator)
+        if object_conf_type == nil then
+            object_conf_type = object_type
+        end
+        return get_uci_section(processors["configuration"], processors[object_type].validator, object_conf_type, name)
+    end
+end
+
+function get_objects(module_table, processors, object_types, object_type)
+    if processors ~= nil and processors[object_type] ~= nil
+       and processors[object_type]["gets"] ~= nil
+       and module_table[processors[object_type]["gets"]] ~= nil then
+            return module_table[processors[object_type]["gets"]]()
+    else
+        local res = {}
+        res[object_types] = {}
+
+        local index = 1
+        local object_conf_type = get_validator_type(processors[object_type].validator)
+        if object_conf_type == nil then
+            object_conf_type = object_type
+        end
+        uci:foreach(processors["configuration"], object_conf_type,
+            function (section)
+                local obj = {}
+                obj["name"] = section[".name"]
+                set_data(processors["configuration"], processors[object_type].validator, section, obj)
+                res[object_types][index] = obj
+                index = index + 1
+            end
+        )
+
+        return res
     end
 end
 
 function handle_get(module_table, processors)
-    local uri_list = get_URI_list(7)
+    local uri_list = get_URI_list()
     if uri_list == nil then
         return
     end
 
-    local object_type = uri_list[#uri_list-1]
-    local name = uri_list[#uri_list]
-    local obj = get_object(module_table, processors, object_type, name)
+    if #uri_list == 6 then
+        -- get objects
+        local object_types = uri_list[#uri_list]
+        local object_type = get_object_type(object_types)
+        if processors["get_type"] ~= nil and type(processors["get_type"]) == "function" then
+            object_type = processors["get_type"](object_types)
+        end
+        local objs = get_objects(module_table, processors, object_types, object_type)
+        if objs == nil then
+            response_error(404, "Cannot find " .. object_type)
+            return
+        end
+        response_object(objs)
+    elseif #uri_list == 7 then
+        -- get object
+        local object_types = uri_list[#uri_list-1]
+        local object_type = get_object_type(object_types)
+        if processors["get_type"] ~= nil and type(processors["get_type"]) == "function" then
+            object_type = processors["get_type"](object_types)
+        end
+        local name = uri_list[#uri_list]
+        local obj = get_object(module_table, processors, object_type, name)
 
-    if obj == nil then
-        response_error(404, "Cannot find " .. object_type .. "[" .. name .. "]" )
+        if obj == nil then
+            response_error(404, "Cannot find " .. object_type .. "[" .. name .. "]" )
+            return
+        end
+        response_object(obj)
+    else
+        response_error(400, "Bad request URI")
         return
     end
-
-    response_object(obj)
 end
 
 -- put
@@ -322,7 +364,7 @@ function update_object(module_table, processors, object_type, obj)
     else
         local name = obj.name
         res, code, msg = delete_object(module_table, processors, object_type, name)
-        if res == true then
+        if res == true or code == 404 then
             return create_object(module_table, processors, object_type, obj)
         end
 
@@ -336,7 +378,12 @@ function handle_put(module_table, processors)
         return
     end
 
-    local object_type = uri_list[#uri_list-1]
+    local object_types = uri_list[#uri_list-1]
+    local object_type = get_object_type(object_types)
+    if processors["get_type"] ~= nil and type(processors["get_type"]) == "function" then
+        object_type = processors["get_type"](object_types)
+    end
+
     local name = uri_list[#uri_list]
     -- check content and get object
     local obj = get_and_validate_body_object(processors[object_type].validator)
@@ -474,7 +521,12 @@ function handle_post(module_table, processors)
         return
     end
 
-    local object_type = uri_list[#uri_list]
+    local object_types = uri_list[#uri_list]
+    local object_type = get_object_type(object_types)
+    if processors["get_type"] ~= nil and type(processors["get_type"]) == "function" then
+        object_type = processors["get_type"](object_types)
+    end
+
     -- check content and get policy object
     local obj = get_and_validate_body_object(processors[object_type].validator)
     if obj == nil then
@@ -516,14 +568,16 @@ function delete_uci_section(configuration, validator, obj, object_type)
     -- delete depedency uci section
     for i,v in pairs(validator) do
         if(type(v) == "table") then
-            if v["item_validator"] ~= nil and type(v["item_validator"]) == "table" then
-                for j=1, #obj[v["name"]] do
-                    local sub_obj = obj[v["name"]][j]
-                    delete_uci_section(configuration, v["item_validator"], obj[v["name"]][j], v["name"])
-                end
-            else
-                if v["validator"] ~= nil and type(v["validator"]) == "table" then
-                    delete_uci_section(configuration, v["validator"], obj[v["name"]], v["name"])
+            if obj[v["name"]] ~= nil then
+                if v["item_validator"] ~= nil and type(v["item_validator"]) == "table" then
+                    for j=1, #obj[v["name"]] do
+                        local sub_obj = obj[v["name"]][j]
+                        delete_uci_section(configuration, v["item_validator"], obj[v["name"]][j], v["name"])
+                    end
+                else
+                    if v["validator"] ~= nil and type(v["validator"]) == "table" then
+                        delete_uci_section(configuration, v["validator"], obj[v["name"]], v["name"])
+                    end
                 end
             end
         end
@@ -573,7 +627,11 @@ function handle_delete(module_table, processors)
         return
     end
 
-    local object_type = uri_list[#uri_list-1]
+    local object_types = uri_list[#uri_list-1]
+    local object_type = get_object_type(object_types)
+    if processors["get_type"] ~= nil and type(processors["get_type"]) == "function" then
+        object_type = processors["get_type"](object_types)
+    end
     local name = uri_list[#uri_list]
 
     res, code, msg = delete_object(module_table, processors, object_type, name)
@@ -692,7 +750,7 @@ end
 function get_URI_list(required_lenth)
     local uri = luci.http.getenv("REQUEST_URI")
     local uri_list = split_and_trim(uri, "/")
-    if not (#uri_list == required_lenth) then
+    if (required_lenth ~= nil) and (not (#uri_list == required_lenth)) then
         response_error(400, "Bad request URI")
         return nil
     end
index 5860e3d..8d6c6a2 100644 (file)
@@ -104,7 +104,7 @@ func (m *Mwan3Client) GetPolicies() (*SdewanPolicies, error) {
 
 // get policy
 func (m *Mwan3Client) GetPolicy(policy_name string) (*SdewanPolicy, error) {
-       response, err := m.OpenwrtClient.Get(mwan3BaseURL + "policy/" + policy_name)
+       response, err := m.OpenwrtClient.Get(mwan3BaseURL + "policies/" + policy_name)
        if err != nil {
                return nil, err
        }
@@ -121,7 +121,7 @@ func (m *Mwan3Client) GetPolicy(policy_name string) (*SdewanPolicy, error) {
 // create policy
 func (m *Mwan3Client) CreatePolicy(policy SdewanPolicy) (*SdewanPolicy, error) {
        policy_obj, _ := json.Marshal(policy)
-       response, err := m.OpenwrtClient.Post(mwan3BaseURL+"policy", string(policy_obj))
+       response, err := m.OpenwrtClient.Post(mwan3BaseURL+"policies", string(policy_obj))
        if err != nil {
                return nil, err
        }
@@ -137,7 +137,7 @@ func (m *Mwan3Client) CreatePolicy(policy SdewanPolicy) (*SdewanPolicy, error) {
 
 // delete policy
 func (m *Mwan3Client) DeletePolicy(policy_name string) error {
-       _, err := m.OpenwrtClient.Delete(mwan3BaseURL + "policy/" + policy_name)
+       _, err := m.OpenwrtClient.Delete(mwan3BaseURL + "policies/" + policy_name)
        if err != nil {
                return err
        }
@@ -149,7 +149,7 @@ func (m *Mwan3Client) DeletePolicy(policy_name string) error {
 func (m *Mwan3Client) UpdatePolicy(policy SdewanPolicy) (*SdewanPolicy, error) {
        policy_obj, _ := json.Marshal(policy)
        policy_name := policy.Name
-       response, err := m.OpenwrtClient.Put(mwan3BaseURL+"policy/"+policy_name, string(policy_obj))
+       response, err := m.OpenwrtClient.Put(mwan3BaseURL+"policies/"+policy_name, string(policy_obj))
        if err != nil {
                return nil, err
        }
@@ -182,7 +182,7 @@ func (m *Mwan3Client) GetRules() (*SdewanRules, error) {
 
 // get rule
 func (m *Mwan3Client) GetRule(rule string) (*SdewanRule, error) {
-       response, err := m.OpenwrtClient.Get(mwan3BaseURL + "rule/" + rule)
+       response, err := m.OpenwrtClient.Get(mwan3BaseURL + "rules/" + rule)
        if err != nil {
                return nil, err
        }
@@ -199,7 +199,7 @@ func (m *Mwan3Client) GetRule(rule string) (*SdewanRule, error) {
 // create rule
 func (m *Mwan3Client) CreateRule(rule SdewanRule) (*SdewanRule, error) {
        rule_obj, _ := json.Marshal(rule)
-       response, err := m.OpenwrtClient.Post(mwan3BaseURL+"rule", string(rule_obj))
+       response, err := m.OpenwrtClient.Post(mwan3BaseURL+"rules", string(rule_obj))
        if err != nil {
                return nil, err
        }
@@ -215,7 +215,7 @@ func (m *Mwan3Client) CreateRule(rule SdewanRule) (*SdewanRule, error) {
 
 // delete rule
 func (m *Mwan3Client) DeleteRule(rule_name string) error {
-       _, err := m.OpenwrtClient.Delete(mwan3BaseURL + "rule/" + rule_name)
+       _, err := m.OpenwrtClient.Delete(mwan3BaseURL + "rules/" + rule_name)
        if err != nil {
                return err
        }
@@ -227,7 +227,7 @@ func (m *Mwan3Client) DeleteRule(rule_name string) error {
 func (m *Mwan3Client) UpdateRule(rule SdewanRule) (*SdewanRule, error) {
        rule_obj, _ := json.Marshal(rule)
        rule_name := rule.Name
-       response, err := m.OpenwrtClient.Put(mwan3BaseURL+"rule/"+rule_name, string(rule_obj))
+       response, err := m.OpenwrtClient.Put(mwan3BaseURL+"rules/"+rule_name, string(rule_obj))
        if err != nil {
                return nil, err
        }
index a187da0..b80f09a 100644 (file)
@@ -5,6 +5,7 @@ import (
        "fmt"
        "io/ioutil"
        "net/http"
+       "runtime"
        "strings"
 )
 
@@ -24,6 +25,11 @@ type openwrtClient struct {
        token    string
 }
 
+func CloseClient(o *openwrtClient) {
+       o.logout()
+       runtime.SetFinalizer(o, nil)
+}
+
 func NewOpenwrtClient(ip string, user string, password string) *openwrtClient {
        client := &openwrtClient{
                ip:       ip,
@@ -32,6 +38,7 @@ func NewOpenwrtClient(ip string, user string, password string) *openwrtClient {
                token:    "",
        }
 
+       runtime.SetFinalizer(client, CloseClient)
        return client
 }
 
@@ -89,6 +96,17 @@ func (o *openwrtClient) login() error {
        return nil
 }
 
+// logout to openwrt http server
+func (o *openwrtClient) logout() error {
+       if o.token != "" {
+               _, err:= o.Get("admin/logout")
+               o.token = ""
+               return err
+       }
+
+       return nil
+}
+
 // call openwrt restful API
 func (o *openwrtClient) call(method string, url string, request string) (string, error) {
        for i := 0; i < 2; i++ {