Commit 11e34d43 authored by zdc's avatar zdc

move to JSON api, clear code

* now all operations work through JSON API
* deleted not needed anymore code
* deleted http/template import
* changed html page
parent 6b87ce1d
...@@ -45,7 +45,7 @@ user = "lookis" ...@@ -45,7 +45,7 @@ user = "lookis"
password = "" password = ""
command_01 = "ping count=5" command_01 = "ping count=5"
command_01_name = "ping" command_01_name = "ping"
command_02 = "tool traceroute count=1" command_02 = "tool traceroute count=1 max-hops=30"
command_02_name = "traceroute" command_02_name = "traceroute"
command_03 = "ip route print where" command_03 = "ip route print where"
command_03_name = "show route" command_03_name = "show route"
......
...@@ -3,7 +3,6 @@ package main ...@@ -3,7 +3,6 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"html/template"
"encoding/json" "encoding/json"
"log" "log"
"net" "net"
...@@ -30,24 +29,21 @@ type Router struct { ...@@ -30,24 +29,21 @@ type Router struct {
RouterCommands []RouterCommands RouterCommands []RouterCommands
} }
// declare variables for page template // declare variables for JSON interface
type DataOut struct { type JsonIn struct {
RoutersList []Router Router, Action, Argument string
OutputHeader, OutputBody string
} }
type JsonOut struct {
// fill error details Status, Result string
func PrepareError (RoutersRaw []Router, HeaderRaw, BodyRaw string) DataOut {
log.Printf("Error! %s: \"%s\"", HeaderRaw, BodyRaw)
output := DataOut{ RoutersList: RoutersRaw, OutputHeader: HeaderRaw, OutputBody: BodyRaw }
return output
} }
// fill normal output // fill response in JSON
func PrepareOutput (RoutersRaw []Router, HeaderRaw, BodyRaw string) DataOut { func PrepareJson (StatusRaw, ResultRaw string) JsonOut {
output := DataOut{ RoutersList: RoutersRaw, OutputHeader: HeaderRaw, OutputBody: BodyRaw } if StatusRaw == "Error" {
log.Printf("Error! \"%s\"", ResultRaw)
}
output := JsonOut{ Status: "<strong>"+StatusRaw+"</strong>", Result: "<pre>"+ResultRaw+"</pre>" }
return output return output
} }
...@@ -77,9 +73,9 @@ func GetCommand (router, command string) (string, bool) { ...@@ -77,9 +73,9 @@ func GetCommand (router, command string) (string, bool) {
} }
// connect to router and run command // connect to router and run command
func SSHRun (router_ip, port, username, password, command, argument, suffix string) DataOut { func SSHRun (router_ip, port, username, password, command, argument, suffix string) JsonOut {
var rawoutput []byte var rawoutput []byte
var output DataOut var output JsonOut
var allok bool = true var allok bool = true
// setting auth options // setting auth options
...@@ -93,7 +89,7 @@ func SSHRun (router_ip, port, username, password, command, argument, suffix stri ...@@ -93,7 +89,7 @@ func SSHRun (router_ip, port, username, password, command, argument, suffix stri
// connect to router // connect to router
connection, err := ssh.Dial("tcp", router_ip+":"+port, sshConfig) connection, err := ssh.Dial("tcp", router_ip+":"+port, sshConfig)
if err != nil { if err != nil {
output = PrepareError (RouterList, "Unable to connect", router_ip) output = PrepareJson ("Error", "Unable to connect: "+router_ip)
allok = false allok = false
} }
...@@ -101,7 +97,7 @@ func SSHRun (router_ip, port, username, password, command, argument, suffix stri ...@@ -101,7 +97,7 @@ func SSHRun (router_ip, port, username, password, command, argument, suffix stri
// create ssh session // create ssh session
session, err := connection.NewSession() session, err := connection.NewSession()
if err != nil { if err != nil {
output = PrepareError (RouterList, "Connection failed", "failed to create session") output = PrepareJson ("Error", "Connection failed: failed to create session")
allok = false allok = false
connection.Close() connection.Close()
} else { } else {
...@@ -109,11 +105,11 @@ func SSHRun (router_ip, port, username, password, command, argument, suffix stri ...@@ -109,11 +105,11 @@ func SSHRun (router_ip, port, username, password, command, argument, suffix stri
// run command and save output // run command and save output
rawoutput, err = session.Output(command+" "+argument+suffix) rawoutput, err = session.Output(command+" "+argument+suffix)
if err != nil { if err != nil {
output = PrepareError (RouterList, "Cannot execute command", command+" "+argument+suffix) output = PrepareJson ("Error", "Cannot execute command: "+command+" "+argument+suffix)
allok = false allok = false
connection.Close() connection.Close()
} else { } else {
output = PrepareOutput (RouterList, "Result", ByteToString(rawoutput)) output = PrepareJson ("Result", ByteToString(rawoutput))
connection.Close() connection.Close()
} }
} }
...@@ -132,6 +128,22 @@ func GetRouterName (RouterId string) string { ...@@ -132,6 +128,22 @@ func GetRouterName (RouterId string) string {
return RouterName return RouterName
} }
// check router in request
func CheckRouter (RouterId string) bool {
var RouterStatus bool
for i := range RouterList {
if RouterList[i].RouterId == RouterId {
RouterStatus = true
break
} else {
RouterStatus = false
}
}
return RouterStatus
}
// get command list for router from config file // get command list for router from config file
func GetRouterCommands (RouterId string) []RouterCommands { func GetRouterCommands (RouterId string) []RouterCommands {
var CommandList []RouterCommands var CommandList []RouterCommands
...@@ -178,76 +190,91 @@ func ParseRoutersFromConfig () []Router { ...@@ -178,76 +190,91 @@ func ParseRoutersFromConfig () []Router {
return routers return routers
} }
// show page and base logic // show page
func ShowPage (w http.ResponseWriter, r *http.Request) { func ShowPage (w http.ResponseWriter, r *http.Request) {
// select html template
t, _ := template.ParseFiles(datapath+"/page_main.gtpl")
// check HTTP method // check HTTP method
if r.Method == "POST" { if r.Method == "GET" {
http.ServeFile(w, r, datapath+"/page_main.gtpl")
} else {
w.Write([]byte("Not allowed!"))
}
}
// show JSON with routers and commands
func ShowJSON (w http.ResponseWriter, r *http.Request) {
// check method
switch r.Method {
// if GET, then show router list with commands
case "GET":
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
jsonout, _ := json.MarshalIndent(ParseRoutersFromConfig(), "", "\t")
w.Write(jsonout)
// if POST, process request and show answer
case "POST":
var Command, argument, suffix string var Command, argument, suffix string
var router_ip, port, username, password string var router_ip, port, username, password string
var output DataOut var input_router, input_action, input_argument string
var allok bool = true var output JsonOut
var CommandState bool var routerState, CommandState bool
var jsonrequest JsonIn
// get POST data
input_router := r.PostFormValue("router") w.Header().Set("Content-Type", "application/json; charset=UTF-8")
input_action := r.PostFormValue("action") // decode JSON to variable jsonrequest
input_argument := r.PostFormValue("argument") jsonbody := json.NewDecoder(r.Body)
err := jsonbody.Decode(&jsonrequest)
if err != nil {
PrepareJson ("Error", "Cannot decode JSON")
goto ShowOutput
}
input_router = jsonrequest.Router
input_action = jsonrequest.Action
input_argument = jsonrequest.Argument
// check for selected router exist // check for selected router exist
if viper.IsSet(input_router+".address") == false { routerState = CheckRouter(input_router)
output = PrepareError (RouterList, "Bad router id", input_router) if routerState == true {
allok = false // setting router variables from config file
router_ip = viper.GetString(input_router+".address")
port = viper.GetString(input_router+".port")
username = viper.GetString(input_router+".user")
password = viper.GetString(input_router+".password")
} else { } else {
// setting router variables from config file output = PrepareJson ("Error", "Bad router id: "+input_router)
router_ip = viper.GetString(input_router+".address") goto ShowOutput
port = viper.GetString(input_router+".port")
username = viper.GetString(input_router+".user")
password = viper.GetString(input_router+".password")
} }
// check and get command for selected action // check and get command for selected action
Command, CommandState = GetCommand(input_router, input_action) Command, CommandState = GetCommand(input_router, input_action)
if CommandState == false { if CommandState == false {
output = PrepareError (RouterList, "Bad command", input_action) output = PrepareJson ("Error", "Bad command: "+input_action)
allok = false goto ShowOutput
} }
// check for argument // check for argument
if net.ParseIP(input_argument) == nil { if net.ParseIP(input_argument) == nil {
output = PrepareError (RouterList, "Bad argument", input_argument) output = PrepareJson ("Error", "Bad argument: "+input_argument)
allok = false goto ShowOutput
} else { } else {
argument = input_argument argument = input_argument
} }
// connect to router and run command // connect to router and run command
if allok == true { // check if command need suffix
// check if command need suffix if viper.IsSet(input_router+".command_"+input_action+"_suffix") != false {
if viper.IsSet(input_router+".command_"+input_action+"_suffix") != false { suffix = " "+viper.GetString(input_router+".command_"+input_action+"_suffix")
suffix = " "+viper.GetString(input_router+".command_"+input_action+"_suffix")
}
output = SSHRun(router_ip, port, username, password, Command, argument, suffix)
// show result to user
t.Execute(w, output)
} else {
// show result to user
t.Execute(w, output)
} }
} else { output = SSHRun(router_ip, port, username, password, Command, argument, suffix)
// show page without result
output := PrepareOutput(RouterList, "", "") // show result to user
t.Execute(w, output) ShowOutput:
jsonout, _ := json.MarshalIndent(output, "", "\t")
w.Write(jsonout)
default:
w.Write([]byte("Not allowed!"))
} }
} }
// show JSON with routers and commands
func ShowJSON (w http.ResponseWriter, r *http.Request) {
jsonout, _ := json.MarshalIndent(ParseRoutersFromConfig(), "", "\t")
w.Write(jsonout)
}
func main() { func main() {
// set config // set config
flag.StringVar(&datapath, "data", "", "data directory") flag.StringVar(&datapath, "data", "", "data directory")
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
</head> </head>
<body> <body>
<p>&nbsp;</p> <p>&nbsp;</p>
<form action="/" method="post"> <form>
<table style="margin-left: auto; margin-right: auto;"> <table style="margin-left: auto; margin-right: auto;">
<tbody> <tbody>
<tr> <tr>
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
<td style="width: 50px;">&nbsp;</td> <td style="width: 50px;">&nbsp;</td>
<td> <td>
<select id="router" name="router"> <select id="router" name="router">
{{range .RoutersList}}<option value="{{ .RouterId }}">{{ .RouterName }}</option>
{{else}}<option>no enabled routers</option>{{end}}
</select> </select>
</td> </td>
</tr> </tr>
...@@ -36,12 +34,12 @@ ...@@ -36,12 +34,12 @@
<tr> <tr>
<td>Argument</td> <td>Argument</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td><input name="argument" type="text" /></td> <td><input id="argument" name="argument" type="text" /></td>
</tr> </tr>
<tr> <tr>
<td style="text-align: center;" colspan="3"> <td style="text-align: center;" colspan="3">
<p>&nbsp;</p> <p>&nbsp;</p>
<p><input type="submit" value="Do it!" /></p> <p><button type="button" onclick="doit()">Do it!</button></p>
</td> </td>
</tr> </tr>
</tbody> </tbody>
...@@ -50,10 +48,10 @@ ...@@ -50,10 +48,10 @@
<table style="margin-left: auto; margin-right: auto;"> <table style="margin-left: auto; margin-right: auto;">
<tbody> <tbody>
<tr> <tr>
<td><strong>{{.OutputHeader}}</strong></td> <td id="output-header" style="text-align: center;"></td>
</tr> </tr>
<tr> <tr>
<td><pre>{{.OutputBody}}</pre></td> <td id="output-body"><pre></pre></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
...@@ -67,6 +65,7 @@ ...@@ -67,6 +65,7 @@
$.getJSON( "json", function (jsonraw) { $.getJSON( "json", function (jsonraw) {
jsondata = jsonraw; jsondata = jsonraw;
// fill actions for selected router // fill actions for selected router
FillInRouter();
FillInAction(); FillInAction();
}); });
...@@ -83,7 +82,19 @@ ...@@ -83,7 +82,19 @@
option.value = OptionData.CommandId; option.value = OptionData.CommandId;
option.text = OptionData.CommandName; option.text = OptionData.CommandName;
action.add(option); action.add(option);
}); });
}
function FillInRouter() {
var router = document.getElementById('router');
// add routers to list
$.each(jsondata, function(i, v) {
var option = document.createElement("option");
option.value = v.RouterId;
option.text = v.RouterName;
router.add(option);
});
} }
function FillInAction() { function FillInAction() {
...@@ -99,6 +110,33 @@ ...@@ -99,6 +110,33 @@
} }
}); });
} }
function doit() {
// get selected form values
var router = document.getElementById('router').value;
var action = document.getElementById('action').value;
var argument = document.getElementById('argument').value;
// format JSON
var request_data = JSON.stringify({ "router": router, "action": action, "argument": argument });
document.getElementById("output-header").innerHTML = "Please wait...";
// make POST request to server with JSON data
$.ajax({
url: '/json',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: request_data,
dataType: "json"
}).done(DrawResult);
}
// show result to user
function DrawResult(jsonresult) {
document.getElementById("output-header").innerHTML = jsonresult['Status'];
document.getElementById("output-body").innerHTML = jsonresult['Result'];
}
</script> </script>
</body> </body>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment