Initial 2024-01-26
This commit is contained in:
122
cmpSnipper/cmpSnipper.go
Normal file
122
cmpSnipper/cmpSnipper.go
Normal file
@@ -0,0 +1,122 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"plugin"
|
||||
)
|
||||
|
||||
type cmpPluginStruct struct {
|
||||
Name string
|
||||
Plug *plugin.Plugin
|
||||
}
|
||||
|
||||
|
||||
type App struct {
|
||||
Conf interface{}
|
||||
ErrIsDir error // = errors.New("Is directory")
|
||||
|
||||
CliList []cmpWbsCliStruct
|
||||
|
||||
cmpSnipperHttpServ cmpSnipperHttpServ
|
||||
|
||||
Rand4d int
|
||||
|
||||
PlugList []cmpPluginStruct
|
||||
|
||||
SshList []cmpSshCliStruct
|
||||
}
|
||||
|
||||
func (app *App) PlugInit(name string, file string) {
|
||||
qqq := map[string]interface{}{
|
||||
"Aaa": "Bbb",
|
||||
}
|
||||
|
||||
var plug cmpPluginStruct
|
||||
|
||||
var p *plugin.Plugin
|
||||
|
||||
p, err := plugin.Open(file)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return
|
||||
}
|
||||
|
||||
plug.Name = name
|
||||
plug.Plug = p
|
||||
|
||||
plugInitReq, err := plug.Plug.Lookup("CmpPlug1Init")
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return
|
||||
}
|
||||
|
||||
plugInitFnc := plugInitReq.(func(int, func(any, ...interface{}), map[string]interface{}) interface{})
|
||||
|
||||
plugInitRes := plugInitFnc(33, app.Log, qqq)
|
||||
|
||||
app.Log("%+v", plugInitRes)
|
||||
|
||||
app.PlugList = append(app.PlugList, plug)
|
||||
}
|
||||
|
||||
func (app *App) PlugCall(pnam string, fnam string) {
|
||||
for _, plug := range app.PlugList {
|
||||
if plug.Name != pnam {
|
||||
continue
|
||||
}
|
||||
|
||||
plugFuncReq, err := plug.Plug.Lookup(fnam)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return
|
||||
}
|
||||
|
||||
plugFuncFnc := plugFuncReq.(func() error)
|
||||
|
||||
plugFuncRes := plugFuncFnc()
|
||||
|
||||
app.Log("%+v", plugFuncRes)
|
||||
}
|
||||
}
|
||||
|
||||
func (app *App) Prep() (error) {
|
||||
app.ErrIsDir = errors.New("Is directory")
|
||||
|
||||
app.LogSetup()
|
||||
|
||||
var err = app.ConfLoadFile("secret/zest.json");
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (app *App) Proc() error {
|
||||
var err error // = make(chan error, 1)
|
||||
|
||||
var term = make(chan bool, 1)
|
||||
|
||||
go app.WaitSignal(term)
|
||||
|
||||
err = app.HttpServStart()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
<-term
|
||||
|
||||
app.HttpServStop()
|
||||
|
||||
app.Log("Terminating")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// end
|
103
cmpSnipper/cmpSnipperConf.go
Normal file
103
cmpSnipper/cmpSnipperConf.go
Normal file
@@ -0,0 +1,103 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"strconv"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
func (app *App) IfcGet(ifc interface{}, arr ...string) (interface{}, error) {
|
||||
var cnt = len(arr);
|
||||
var idx string
|
||||
|
||||
for j := 0; j < cnt; j++ {
|
||||
idx = arr[j]
|
||||
|
||||
switch v := ifc.(type) {
|
||||
case string:
|
||||
app.Log("Convert string to ifc")
|
||||
ifc = ifc.(interface{})
|
||||
|
||||
case map[string]interface{}:
|
||||
// app.Log("Valid ifc " + idx)
|
||||
ifc = v[idx];
|
||||
|
||||
default:
|
||||
app.Log("Invalid type variable %s %T", idx, ifc)
|
||||
return nil, errors.New("Invalid type variable");
|
||||
}
|
||||
}
|
||||
|
||||
if ifc == nil {
|
||||
return nil, errors.New("Undefine variable " + idx);
|
||||
}
|
||||
|
||||
// app.Log("Found ifc %s %T", idx, ifc)
|
||||
|
||||
return ifc, nil;
|
||||
}
|
||||
|
||||
func (app *App) ConfGetIfc(arr ...string) (interface{}, error) {
|
||||
return app.IfcGet(app.Conf, arr...);
|
||||
}
|
||||
|
||||
func (app *App) ConfGetStr(arr ...string) (string, error) {
|
||||
ifc, err := app.ConfGetIfc(arr...);
|
||||
|
||||
if err != nil {
|
||||
return "", err;
|
||||
}
|
||||
|
||||
switch ifc.(type) {
|
||||
case string:
|
||||
return ifc.(string), nil;
|
||||
case float64:
|
||||
f := ifc.(float64)
|
||||
u := uint64(f)
|
||||
return strconv.FormatUint(u, 10), nil;
|
||||
default:
|
||||
return "", errors.New("Invalid type value !s");
|
||||
}
|
||||
|
||||
return "", errors.New("Invalid type value");
|
||||
}
|
||||
|
||||
func (app *App) ConfGetArr(arr ...string) ([]interface{}, error) {
|
||||
ifc, err := app.ConfGetIfc(arr...);
|
||||
|
||||
if err != nil {
|
||||
return nil, err;
|
||||
}
|
||||
|
||||
switch v := ifc.(type) {
|
||||
case []interface{}:
|
||||
return v, nil
|
||||
default:
|
||||
fmt.Printf("Invalid type value %+q\n", ifc)
|
||||
return nil, errors.New("Invalid type value !s");
|
||||
}
|
||||
|
||||
return nil, errors.New("Invalid type value");
|
||||
}
|
||||
|
||||
func (app *App) ConfLoadFile(file string) error {
|
||||
data, err := app.FileReadLimit(file, 1048576);
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// fmt.Println(string(data));
|
||||
|
||||
err = json.Unmarshal(data, &app.Conf)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
84
cmpSnipper/cmpSnipperHttpServ.go
Normal file
84
cmpSnipper/cmpSnipperHttpServ.go
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type tcpKeepAliveListener struct {
|
||||
*net.TCPListener
|
||||
}
|
||||
|
||||
type cmpSnipperHttpServ struct {
|
||||
HttpListener net.Listener
|
||||
}
|
||||
|
||||
func (app *App) HttpServStart() error {
|
||||
var err error;
|
||||
|
||||
// var subjHttpPortString string = "7070";
|
||||
// var subjHttpPortUint16 uint16 = subjConf.Http.Port;
|
||||
|
||||
host, err := app.ConfGetStr("http", "host")
|
||||
|
||||
// fmt.Printf("Success load : %+v\n", host)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
port, err := app.ConfGetStr("http", "port")
|
||||
|
||||
// fmt.Printf("Success load : %+v\n", port)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// if subjHttpPortUint16 == 0 || subjHttpPortString != strconv.FormatUint(uint64(subjHttpPortUint16), 10) {
|
||||
// fmt.Printf("Invalid http.port %s != %d\n", subjHttpPortString, subjHttpPortUint16)
|
||||
// app.Log(".Fatal");
|
||||
// }
|
||||
|
||||
|
||||
httpFileServer := http.FileServer(http.Dir("static"))
|
||||
http.Handle("/go-prefix/static/", http.StripPrefix("/go-prefix/static/", httpFileServer))
|
||||
|
||||
http.HandleFunc("/" , app.HttpReq);
|
||||
http.HandleFunc("/go-prefix/ws" , app.HttpWebSockHand)
|
||||
|
||||
var addr = host + ":" + port
|
||||
|
||||
server := &http.Server{Addr: addr}
|
||||
|
||||
app.Log("Listenning: '%s'", port);
|
||||
|
||||
app.cmpSnipperHttpServ.HttpListener, err = net.Listen("tcp", addr)
|
||||
|
||||
// defer app.HttpServClose()
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
err = server.Serve(tcpKeepAliveListener{app.cmpSnipperHttpServ.HttpListener.(*net.TCPListener)})
|
||||
|
||||
if err == nil {
|
||||
app.Log(err)
|
||||
return // err
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (app *App) HttpServStop() {
|
||||
app.cmpSnipperHttpServ.HttpListener.Close()
|
||||
|
||||
app.Log("Server Closed")
|
||||
}
|
245
cmpSnipper/cmpSnipperHttpUtil.go
Normal file
245
cmpSnipper/cmpSnipperHttpUtil.go
Normal file
@@ -0,0 +1,245 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (app *App) HttpRespText(w http.ResponseWriter, data []byte) {
|
||||
w.Write(data)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (app *App) HttpRespJson(w http.ResponseWriter, data any) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
jsonResp, err := json.MarshalIndent(data, "", "\t")
|
||||
|
||||
if err != nil {
|
||||
app.Log("Error happened in JSON marshal. Err: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
app.HttpRespText(w, jsonResp)
|
||||
}
|
||||
|
||||
func HttpRespCodeText(w http.ResponseWriter, req *http.Request, code int, cont string, mesg any) {
|
||||
w.WriteHeader(code)
|
||||
|
||||
w.Header().Set("Content-Type", cont)
|
||||
|
||||
|
||||
}
|
||||
|
||||
func (app *App) HttpRespForbidden(w http.ResponseWriter, req *http.Request, mesg string) {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
|
||||
resp := make(map[string]any)
|
||||
resp["code"] = 403
|
||||
resp["status"] = "Forbidden"
|
||||
resp["message"] = mesg
|
||||
|
||||
app.HttpRespJson(w, resp)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (app *App) HttpReqDir1(w http.ResponseWriter, req *http.Request, targ string, path string) {
|
||||
resp := map[string]interface{}{
|
||||
"path" : path,
|
||||
"directory": targ,
|
||||
"content" : nil,
|
||||
}
|
||||
|
||||
entries, err := os.ReadDir(targ)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
app.HttpRespForbidden(w, req, "Server error")
|
||||
}
|
||||
|
||||
var slice []interface{};
|
||||
|
||||
for _, e := range entries {
|
||||
slice = append(slice, map[string]interface{}{
|
||||
"name": e.Name(),
|
||||
})
|
||||
|
||||
// fmt.Println(e.Name());
|
||||
}
|
||||
|
||||
resp["content"] = slice
|
||||
|
||||
app.HttpRespJson(w, resp)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (app *App) HttpReqDir(w http.ResponseWriter, req *http.Request, targ string, path string) {
|
||||
finx := path + "/index.html"
|
||||
|
||||
data, err := app.FileReadLimit(finx, 1048576);
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
app.HttpReqDir1(w, req, targ, path)
|
||||
return
|
||||
}
|
||||
|
||||
if err == app.ErrIsDir {
|
||||
app.HttpReqDir1(w, req, targ, path)
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
app.Log("Err: %s", err)
|
||||
app.HttpRespForbidden(w, req, "Server error")
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
|
||||
app.HttpRespText(w, data)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (app *App) HttpReq(w http.ResponseWriter, req *http.Request) {
|
||||
// https://go.dev/src/net/http/request.go
|
||||
|
||||
// fmt.Printf("Request: %+v\n", req)
|
||||
|
||||
var auri = (strings.Split(req.RequestURI, "/"))
|
||||
auri[0] = "/"
|
||||
|
||||
var aidx = 0
|
||||
|
||||
app.Log("Auri: %+v", auri)
|
||||
|
||||
var locTarg map[string]interface{}
|
||||
var locEnd bool
|
||||
|
||||
locList, err := app.ConfGetArr("http", "location")
|
||||
|
||||
if err != nil {
|
||||
app.HttpRespForbidden(w, req, "Invalid http.location")
|
||||
return
|
||||
}
|
||||
|
||||
for uid, uri := range auri {
|
||||
locEnd = false
|
||||
|
||||
for _, locIfc := range locList {
|
||||
var locMap map[string]interface{};
|
||||
|
||||
switch v := locIfc.(type) {
|
||||
case map[string]interface{}:
|
||||
locMap = v;
|
||||
}
|
||||
|
||||
if locMap == nil {
|
||||
app.Log("Not Found")
|
||||
continue
|
||||
}
|
||||
|
||||
locUri := locMap["uri"]
|
||||
|
||||
if 1 == 0 {
|
||||
// fmt.Printf("Found: %+v\n", locUri)
|
||||
continue
|
||||
}
|
||||
|
||||
if locUri != uri {
|
||||
// fmt.Printf(" %s != %s\n", locUri, uri)
|
||||
continue
|
||||
}
|
||||
|
||||
// fmt.Printf("Found: %s\n", uri)
|
||||
|
||||
locTarg = locMap
|
||||
locEnd = true
|
||||
aidx = uid
|
||||
|
||||
switch v := locMap["list"].(type) {
|
||||
case []interface{}:
|
||||
locList = v;
|
||||
// fmt.Printf("Found list\n");
|
||||
}
|
||||
}
|
||||
|
||||
if !locEnd {
|
||||
break
|
||||
}
|
||||
}
|
||||
/*
|
||||
fmt.Printf("Targ %+v\n", locTarg);
|
||||
fmt.Printf("Targ %+v\n", locEnd );
|
||||
fmt.Printf("Targ %s \n", locTarg["uri"] );
|
||||
fmt.Printf("Targ %+v\n", auri[(aidx+1):]);
|
||||
*/
|
||||
switch locTarg["type"] {
|
||||
case "json":
|
||||
targ := locTarg["targ"].(string)
|
||||
|
||||
app.HttpRespJson(w, locTarg[targ])
|
||||
|
||||
return
|
||||
|
||||
case "func":
|
||||
targ := locTarg["targ"].(string)
|
||||
parm := locTarg["parm"]
|
||||
|
||||
resp, err := app.CallFuncByName(targ, parm)
|
||||
|
||||
if err != nil {
|
||||
app.Log("Err: %s", err)
|
||||
break
|
||||
}
|
||||
|
||||
app.HttpRespJson(w, resp)
|
||||
|
||||
return
|
||||
|
||||
case "directory":
|
||||
targ := locTarg["targ"].(string)
|
||||
|
||||
path := targ + "/" + strings.Join(auri[(aidx+1):], "/")
|
||||
|
||||
app.Log("Location: %s", path)
|
||||
|
||||
data, err := app.FileReadLimit(path, 1048576);
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
break
|
||||
}
|
||||
|
||||
if err == app.ErrIsDir {
|
||||
app.HttpReqDir(w, req, targ, path)
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
app.Log("Err: %s", err)
|
||||
app.HttpRespForbidden(w, req, "Server error")
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
|
||||
app.HttpRespText(w, data)
|
||||
|
||||
return
|
||||
|
||||
case "redirect":
|
||||
http.Redirect(w, req, locTarg["targ"].(string), int(locTarg["code"].(float64)))
|
||||
|
||||
return
|
||||
|
||||
// case "ws":
|
||||
}
|
||||
|
||||
app.HttpRespForbidden(w, req, "Invalid type")
|
||||
}
|
168
cmpSnipper/cmpSnipperHttpWsHandle.go
Normal file
168
cmpSnipper/cmpSnipperHttpWsHandle.go
Normal file
@@ -0,0 +1,168 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"time"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type cmpWbsCliStruct struct {
|
||||
W http.ResponseWriter
|
||||
Connect *websocket.Conn
|
||||
HostPort string
|
||||
}
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
HandshakeTimeout: 60 * time.Second,
|
||||
}
|
||||
|
||||
func (app *App) HttpWebSockHand(w http.ResponseWriter, req *http.Request) {
|
||||
conn, err := upgrader.Upgrade(w, req, nil)
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return
|
||||
}
|
||||
|
||||
app.Log("HttpWebSockHand:for")
|
||||
|
||||
HostPort := req.Header.Get("X-Real-Ip")
|
||||
|
||||
if HostPort == "" {
|
||||
HostPort = req.Header.Get("X-Forwarded-For")
|
||||
}
|
||||
|
||||
if HostPort == "" {
|
||||
HostPort = req.RemoteAddr
|
||||
}
|
||||
|
||||
app.Log("New client: %s", HostPort)
|
||||
|
||||
var cmpWbsCli cmpWbsCliStruct = cmpWbsCliStruct{
|
||||
w,
|
||||
conn,
|
||||
HostPort,
|
||||
}
|
||||
|
||||
|
||||
app.CliList = append(app.CliList, cmpWbsCli)
|
||||
|
||||
app.Log(app.CliList)
|
||||
|
||||
for i, cli := range app.CliList {
|
||||
app.Log("Client %s, %s", i, cli.HostPort)
|
||||
}
|
||||
|
||||
for {
|
||||
var inp = map[string]interface{}{}
|
||||
var out = map[string]interface{}{
|
||||
"snip": "",
|
||||
"result": nil,
|
||||
}
|
||||
|
||||
err := conn.ReadJSON(&inp)
|
||||
|
||||
if err != nil {
|
||||
app.Log("Read JSON: %s", err)
|
||||
app.Log(err)
|
||||
|
||||
var list []cmpWbsCliStruct
|
||||
|
||||
for _, ii := range app.CliList {
|
||||
if ii.HostPort == HostPort {
|
||||
continue
|
||||
}
|
||||
|
||||
list = append(list, ii)
|
||||
}
|
||||
|
||||
app.CliList = list
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
app.Log("Received message: %+v", inp)
|
||||
|
||||
out["snip"] = inp["snip"]
|
||||
|
||||
// app.Log("Copy snip OK")
|
||||
|
||||
var snip string;
|
||||
|
||||
snip = inp["snip"].(string)
|
||||
|
||||
// app.Log("Look snip")
|
||||
|
||||
if app.SnipExists(snip) {
|
||||
out["result"], err = app.SnipCall(cmpWbsCli, snip, inp)
|
||||
|
||||
if err != nil {
|
||||
out["error"] = "Server error"
|
||||
}
|
||||
} else {
|
||||
out["error"] = "Unknown snip"
|
||||
app.Log("Unknow snip:", inp["snip"])
|
||||
}
|
||||
|
||||
err = conn.WriteJSON(out)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
}
|
||||
|
||||
// for
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (app *App) HttpWebSockSendTo(cmpWbsCli cmpWbsCliStruct, snip string, result map[string]interface{}) {
|
||||
var err error
|
||||
|
||||
out := map[string]interface{}{
|
||||
"snip": snip,
|
||||
"result": result,
|
||||
}
|
||||
|
||||
err = cmpWbsCli.Connect.WriteJSON(out)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (app *App) HttpWebSockSendAll(snip string, result map[string]interface{}) {
|
||||
var err error
|
||||
|
||||
app.Log("Send to all")
|
||||
|
||||
out := map[string]interface{}{
|
||||
"snip": snip,
|
||||
"result": result,
|
||||
}
|
||||
|
||||
for _, ii := range app.CliList {
|
||||
if ii.HostPort == "" {
|
||||
break
|
||||
}
|
||||
|
||||
err = ii.Connect.WriteJSON(out)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
57
cmpSnipper/cmpSnipperLog.go
Normal file
57
cmpSnipper/cmpSnipperLog.go
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
func (app *App) LogMod(arg interface{}) string {
|
||||
var str string
|
||||
|
||||
switch t := arg.(type) {
|
||||
case nil:
|
||||
str = /* "N:" + */ "null"
|
||||
|
||||
case string:
|
||||
str = /* "S:" + */ t
|
||||
|
||||
case error:
|
||||
str = /* "E:" + */ t.Error()
|
||||
|
||||
case byte:
|
||||
str = /* "B:" + */ string(t)
|
||||
|
||||
case []byte:
|
||||
str = /* "A:" + */ string(t)
|
||||
|
||||
case interface{}:
|
||||
obyte, _ := json.MarshalIndent(arg, "", "\t")
|
||||
str = /* "J:" + */ string(obyte)
|
||||
|
||||
default:
|
||||
str = /* "U:" + */ fmt.Sprintf("Unknown type %T", t)
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
func (app *App) Log(farg any, iargs ...interface{}) {
|
||||
var str = app.LogMod(farg)
|
||||
|
||||
log.SetPrefix(time.Now().UTC().Format("2006-01-02 15:04:05") + ": ")
|
||||
|
||||
oargs := make([]interface{}, len(iargs))
|
||||
|
||||
for k, arg := range iargs {
|
||||
oargs[k] = app.LogMod(arg)
|
||||
}
|
||||
|
||||
log.Output(2, fmt.Sprintf(str + "\n", oargs...))
|
||||
}
|
||||
|
||||
func (app *App) LogSetup() {
|
||||
log.SetFlags( log.Lshortfile );
|
||||
}
|
84
cmpSnipper/cmpSnipperSignal.go
Normal file
84
cmpSnipper/cmpSnipperSignal.go
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (app *App) WaitSignal(term chan bool) {
|
||||
var sigreq = make(chan os.Signal, 1)
|
||||
|
||||
for true {
|
||||
signal.Notify(sigreq)
|
||||
sigrcv := <-sigreq
|
||||
|
||||
// app.Log("Got signal: %s", sigrcv)
|
||||
|
||||
if sigrcv == syscall.SIGTERM {
|
||||
term <- true
|
||||
// continue
|
||||
return
|
||||
}
|
||||
|
||||
if sigrcv == syscall.SIGINT {
|
||||
term <- true
|
||||
// continue
|
||||
return
|
||||
}
|
||||
|
||||
if sigrcv == syscall.SIGQUIT {
|
||||
term <- true
|
||||
// continue
|
||||
return
|
||||
}
|
||||
|
||||
if sigrcv == syscall.SIGUSR1 {
|
||||
app.Log("Got signal: %s", sigrcv)
|
||||
continue
|
||||
}
|
||||
|
||||
if sigrcv == syscall.SIGUSR2 {
|
||||
app.Log("Got signal: %s", sigrcv)
|
||||
|
||||
app.Log("Rand 4d: %d", app.Rand4d)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// 1) SIGHUP
|
||||
// 2) SIGINT
|
||||
// 3) SIGQUIT
|
||||
// 4) SIGILL
|
||||
// 5) SIGTRAP
|
||||
// 6) SIGABRT
|
||||
// 7) SIGBUS
|
||||
// 8) SIGFPE
|
||||
// 9) SIGKILL
|
||||
// 10) SIGUSR1
|
||||
// 11) SIGSEGV
|
||||
// 12) SIGUSR2
|
||||
// 13) SIGPIPE
|
||||
// 14) SIGALRM
|
||||
// 15) SIGTERM
|
||||
// 16) SIGSTKFLT
|
||||
// 17) SIGCHLD
|
||||
// 18) SIGCONT
|
||||
// 19) SIGSTOP
|
||||
// 20) SIGTSTP
|
||||
// 21) SIGTTIN
|
||||
// 22) SIGTTOU
|
||||
// 23) SIGURG
|
||||
// 24) SIGXCPU
|
||||
// 25) SIGXFSZ
|
||||
// 26) SIGVTALRM
|
||||
// 27) SIGPROF
|
||||
// 28) SIGWINCH
|
||||
// 29) SIGIO
|
||||
// 30) SIGPWR
|
||||
// 31) SIGSYS
|
||||
|
||||
app.Log("Got signal: %s", sigrcv)
|
||||
}
|
||||
}
|
78
cmpSnipper/cmpSnipperSnip.go
Normal file
78
cmpSnipper/cmpSnipperSnip.go
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"errors"
|
||||
)
|
||||
|
||||
func (app *App) SnipExists(funcName string) bool {
|
||||
snipName := app.UpperFirst(funcName) + "Snip"
|
||||
refCls := reflect.ValueOf(app)
|
||||
refMth := refCls.MethodByName(snipName)
|
||||
|
||||
if !refMth.IsValid() {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (app *App) SnipCall(cmpWbsCli cmpWbsCliStruct, fnName string, ifcII interface{}) (interface{}, error) {
|
||||
snName := app.UpperFirst(fnName) + "Snip"
|
||||
refCls := reflect.ValueOf(app)
|
||||
refMth := refCls.MethodByName(snName)
|
||||
|
||||
if !refMth.IsValid() {
|
||||
app.Log("Call method \"%s\" not found", snName)
|
||||
return nil, errors.New("Call method not founnd")
|
||||
}
|
||||
|
||||
app.Log("Call method \"%s\"", snName)
|
||||
|
||||
ifcIM := map[string]interface{}{
|
||||
"InputArgument" : ifcII,
|
||||
"HostPort" : cmpWbsCli.HostPort,
|
||||
}
|
||||
|
||||
refIL := []reflect.Value{
|
||||
reflect.ValueOf(ifcIM),
|
||||
}
|
||||
|
||||
refOL := refMth.Call(refIL)
|
||||
|
||||
infOI := refOL[0].Interface()
|
||||
|
||||
app.Log("Interface output item %+v", infOI)
|
||||
|
||||
return infOI, nil
|
||||
}
|
||||
|
||||
func (app *App) SnipGetCli(parm any) (cmpWbsCliStruct, error) {
|
||||
var err error
|
||||
var cmpWbsCli cmpWbsCliStruct
|
||||
|
||||
HostPortIfc, err := app.IfcGet(parm.(map[string]interface{}), "HostPort")
|
||||
|
||||
if err != nil {
|
||||
app.Log("Invalid iterface")
|
||||
return cmpWbsCli, err
|
||||
}
|
||||
|
||||
HostPort, ok := HostPortIfc.(string)
|
||||
|
||||
if !ok {
|
||||
app.Log("Invalid string")
|
||||
return cmpWbsCli, errors.New("Can't covert to string")
|
||||
}
|
||||
|
||||
for _, ii := range app.CliList {
|
||||
if HostPort != ii.HostPort {
|
||||
continue
|
||||
}
|
||||
|
||||
return ii, nil
|
||||
}
|
||||
|
||||
return cmpWbsCli, errors.New("Client " + HostPort + " not found")
|
||||
}
|
12
cmpSnipper/cmpSnipperSnipCliList.go
Normal file
12
cmpSnipper/cmpSnipperSnipCliList.go
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
func (app *App) CliListSnip(parm any) (any, error) {
|
||||
// app.Log("")
|
||||
|
||||
ret := map[string]interface{}{
|
||||
"list" : app.CliList,
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
32
cmpSnipper/cmpSnipperSnipLeftMenu.go
Normal file
32
cmpSnipper/cmpSnipperSnipLeftMenu.go
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
func (app *App) LeftMenuSnip(parm any) (any, error) {
|
||||
// app.Log("Read data")
|
||||
|
||||
mainMenuFile, err := app.ConfGetStr("mainMenuFile")
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := app.FileReadLimit(mainMenuFile, 1048576)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var res = map[string]interface{}{}
|
||||
|
||||
err = json.Unmarshal(data, &res)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
70
cmpSnipper/cmpSnipperSnipPing.go
Normal file
70
cmpSnipper/cmpSnipperSnipPing.go
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"context"
|
||||
"time"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (app *App) PingSnip(parm any) (any, error) {
|
||||
// log.Println("PingSnip")
|
||||
|
||||
path, err := exec.LookPath("ping")
|
||||
|
||||
app.Log("Prog:", path)
|
||||
|
||||
if err != nil {
|
||||
return map[string]interface{}{
|
||||
"retval" : 127,
|
||||
"error" : "No prog",
|
||||
}, nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10 * time.Second)
|
||||
|
||||
defer cancel()
|
||||
|
||||
cmd := exec.CommandContext(ctx, "ping", "-c", "4", "8.8.8.8")
|
||||
|
||||
cmd.Stdin = strings.NewReader("")
|
||||
|
||||
var stdout strings.Builder
|
||||
cmd.Stdout = &stdout
|
||||
|
||||
var stderr strings.Builder
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
var exitCode int;
|
||||
|
||||
err = cmd.Run()
|
||||
|
||||
if err != nil {
|
||||
// try to get the exit code
|
||||
if exitError, ok := err.(*exec.ExitError); ok {
|
||||
ws := exitError.Sys().(syscall.WaitStatus)
|
||||
exitCode = ws.ExitStatus()
|
||||
} else {
|
||||
// This will happen (in OSX) if `name` is not available in $PATH,
|
||||
// in this situation, exit code could not be get, and stderr will be
|
||||
// empty string very likely, so we use the default fail code, and format err
|
||||
// to string and set to stderr
|
||||
|
||||
app.Log("Could not get exit code for failed program")
|
||||
exitCode = 255
|
||||
}
|
||||
} else {
|
||||
// success, exitCode should be 0 if go is ok
|
||||
ws := cmd.ProcessState.Sys().(syscall.WaitStatus)
|
||||
exitCode = ws.ExitStatus()
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"retval" : exitCode,
|
||||
"error" : err,
|
||||
"stdout" : stdout.String(),
|
||||
"stderr" : stderr.String(),
|
||||
}, nil
|
||||
}
|
16
cmpSnipper/cmpSnipperSnipRand4d.go
Normal file
16
cmpSnipper/cmpSnipperSnipRand4d.go
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
func (app *App) Rand4dSnip(parm any) (any, error) {
|
||||
// app.Log("Rand4dSnip")
|
||||
|
||||
app.Rand4d = rand.Intn(10000) + 1000
|
||||
|
||||
return map[string]interface{}{
|
||||
"rand4d" : app.Rand4d,
|
||||
}, nil
|
||||
}
|
87
cmpSnipper/cmpSnipperUtil.go
Normal file
87
cmpSnipper/cmpSnipperUtil.go
Normal file
@@ -0,0 +1,87 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"os"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func (app *App) FileReadLimit(file string, mSize int64) ([]byte, error) {
|
||||
info, err := os.Stat(file)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
return nil, app.ErrIsDir
|
||||
}
|
||||
|
||||
fSize := info.Size()
|
||||
|
||||
if fSize > mSize {
|
||||
return nil, errors.New("File is big")
|
||||
}
|
||||
|
||||
fd, err := os.Open(file)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer fd.Close()
|
||||
|
||||
var rata = make([]byte, fSize);
|
||||
|
||||
rSize, err := fd.Read(rata);
|
||||
|
||||
if fSize != int64(rSize) {
|
||||
return nil, errors.New("Can't read full file size")
|
||||
}
|
||||
|
||||
return rata, nil
|
||||
}
|
||||
|
||||
func (app *App) UpperFirst(si string) string {
|
||||
bi := []byte(si)
|
||||
ss := strings.Title(string(bi[0]))
|
||||
bo := bi
|
||||
bo[0] = ss[0]
|
||||
|
||||
return string(bo)
|
||||
}
|
||||
|
||||
func (app *App) CallFuncByName(funcName string, ifcIL ...interface{}) ([]interface{}, error) {
|
||||
refCls := reflect.ValueOf(app)
|
||||
refMth := refCls.MethodByName(funcName)
|
||||
|
||||
if !refMth.IsValid() {
|
||||
app.Log("Call method \"%s\" not found", funcName)
|
||||
return nil, errors.New("Call method not founnd")
|
||||
}
|
||||
|
||||
app.Log("Call method \"%s\"", funcName)
|
||||
|
||||
refIL := make([]reflect.Value, len(ifcIL))
|
||||
|
||||
for i, ifcII := range ifcIL {
|
||||
refIL[i] = reflect.ValueOf(ifcII)
|
||||
}
|
||||
|
||||
// fmt.Println("reflect input list", refIL);
|
||||
|
||||
refOL := refMth.Call(refIL)
|
||||
|
||||
infOL := make([]interface{}, len(refOL))
|
||||
|
||||
for i, refOI := range refOL {
|
||||
infOL[i] = refOI.Interface()
|
||||
}
|
||||
|
||||
app.Log("Interface output list %+v", infOL)
|
||||
|
||||
return infOL, nil
|
||||
}
|
196
cmpSnipper/cmpSnippetHttpCli.go
Normal file
196
cmpSnipper/cmpSnippetHttpCli.go
Normal file
@@ -0,0 +1,196 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
// "crypto/md5"
|
||||
"net/http"
|
||||
// "os"
|
||||
"io"
|
||||
// "fmt"
|
||||
"bufio"
|
||||
// "io/ioutil"
|
||||
"bytes"
|
||||
"strings"
|
||||
// "golang.org/x/net/html"
|
||||
// "net/url"
|
||||
"encoding/json"
|
||||
"compress/gzip"
|
||||
"compress/flate"
|
||||
"github.com/andybalholm/brotli"
|
||||
)
|
||||
|
||||
func (app *App) HttpGet(url string) (map[string]interface{}) {
|
||||
ret := map[string]interface{}{
|
||||
"Error" : nil ,
|
||||
"RequestUrl" : url ,
|
||||
"StatusCode" : 0 ,
|
||||
"ContentRaw" : nil ,
|
||||
"ContentJson" : nil ,
|
||||
"Header" : nil ,
|
||||
"Content-Encoding" : "" ,
|
||||
"Content-Type" : "" ,
|
||||
"Content-Length" : "" ,
|
||||
}
|
||||
|
||||
app.Log(url)
|
||||
|
||||
cli := &http.Client{}
|
||||
|
||||
ifcRawHead, err := app.ConfGetIfc("httpTest", "head")
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
ret["Error"] = err
|
||||
return ret
|
||||
}
|
||||
|
||||
mapIfcHead := ifcRawHead.(map[string]interface{})
|
||||
|
||||
mapStrHead := make(map[string][]string)
|
||||
|
||||
for key, val := range mapIfcHead {
|
||||
mapStrHead[key] = []string{ val.(string) }
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
|
||||
req.Header = mapStrHead
|
||||
|
||||
res, err := cli.Do(req)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
ret["Error"] = err
|
||||
return ret
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
ret["Error"] = err
|
||||
return ret
|
||||
}
|
||||
|
||||
ret["StatusCode" ] = res.StatusCode
|
||||
ret["Content-Length"] = res.ContentLength
|
||||
ret["Header" ] = res.Header
|
||||
|
||||
// app.Log("Response status: %s", res.Status)
|
||||
// app.Log("Header: %+v", res.Header)
|
||||
|
||||
// app.Log("TransferEncoding: %+v", res.TransferEncoding)
|
||||
// app.Log("ContentLength: %+v", res.ContentLength)
|
||||
|
||||
var tmpl []string
|
||||
|
||||
tmpl = res.Header["Content-Encoding"]
|
||||
if len(tmpl) > 0 {
|
||||
ret["Content-Encoding"] = tmpl[0]
|
||||
}
|
||||
|
||||
tmpl = res.Header["Content-Type"]
|
||||
if len(tmpl) > 0 {
|
||||
tmpl = strings.Split(tmpl[0], ";")
|
||||
|
||||
if len(tmpl) > 0 {
|
||||
ret["Content-Type"] = tmpl[0]
|
||||
}
|
||||
}
|
||||
|
||||
// Content-Disposition: attachment; name="fieldName"; filename="myfile.txt"
|
||||
|
||||
|
||||
out := new(bytes.Buffer)
|
||||
var encReader io.Reader
|
||||
|
||||
switch ret["Content-Encoding"] {
|
||||
case "":
|
||||
encReader = bufio.NewReader(res.Body)
|
||||
case "br":
|
||||
encReader = brotli.NewReader(res.Body)
|
||||
case "gzip":
|
||||
encReader, err = gzip.NewReader(res.Body)
|
||||
case "deflate":
|
||||
encReader = flate.NewReader(res.Body)
|
||||
default:
|
||||
app.Log("Unknown Content-Encoding %s", ret["Content-Encoding"])
|
||||
encReader = bufio.NewReader(res.Body)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
ret["Error"] = err
|
||||
return ret
|
||||
}
|
||||
|
||||
size, err := out.ReadFrom(encReader)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
ret["Error"] = err
|
||||
return ret
|
||||
}
|
||||
|
||||
app.Log("Read %s", size)
|
||||
|
||||
var contRaw []byte = out.Bytes()
|
||||
ret["ContentRaw"] = contRaw
|
||||
|
||||
if ret["Content-Type"] == "application/json" {
|
||||
var contJson interface{}
|
||||
|
||||
err = json.Unmarshal(contRaw, &contJson)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
ret["Error"] = err
|
||||
return ret
|
||||
}
|
||||
|
||||
ret["ContentJson"] = contJson
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (app *App) CmpHttpTestSnip(parm any) (any, error) {
|
||||
var err error
|
||||
|
||||
cli, err := app.SnipGetCli(parm)
|
||||
|
||||
if err != nil {
|
||||
return map[string]interface{}{
|
||||
"status": "error",
|
||||
"error" : "Not client found",
|
||||
}, err
|
||||
}
|
||||
|
||||
url, err := app.ConfGetStr("httpTest", "url")
|
||||
|
||||
if err != nil {
|
||||
return map[string]interface{}{
|
||||
"status": "error",
|
||||
"error" : "Not test URL",
|
||||
}, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
var a map[string]interface{}
|
||||
|
||||
a = app.HttpGet(url)
|
||||
|
||||
app.Log(a)
|
||||
|
||||
app.HttpWebSockSendTo(cli, "cmpHttpTest", map[string]interface{}{
|
||||
"status" : "response",
|
||||
"response": a,
|
||||
})
|
||||
}()
|
||||
|
||||
|
||||
return map[string]interface{}{
|
||||
"status" : "request",
|
||||
"request": url,
|
||||
}, nil
|
||||
}
|
288
cmpSnipper/cmpSnippetSshCli.go
Normal file
288
cmpSnipper/cmpSnippetSshCli.go
Normal file
@@ -0,0 +1,288 @@
|
||||
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"io"
|
||||
"bufio"
|
||||
"strings"
|
||||
"net"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type cmpSshCliStruct struct {
|
||||
Host string
|
||||
Connect *ssh.Client
|
||||
Session *ssh.Session
|
||||
Output *bufio.Reader
|
||||
}
|
||||
|
||||
|
||||
func (app *App) SshAddHostKey(host string, remote net.Addr, pubKey ssh.PublicKey) error {
|
||||
app.Log(pubKey)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (app *App) SshConnReal(cmpSshCli *cmpSshCliStruct, host string, keyfile string) error {
|
||||
var err error
|
||||
|
||||
cmpSshCli.Host = host
|
||||
|
||||
key, err := app.FileReadLimit(keyfile, 1048576)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
signer, err := ssh.ParsePrivateKey(key)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
config := &ssh.ClientConfig{
|
||||
User: "root",
|
||||
Auth: []ssh.AuthMethod{
|
||||
// HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
// ssh.Password("yourpassword"),
|
||||
ssh.PublicKeys(signer),
|
||||
},
|
||||
// HostKeyCallback: ssh.FixedHostKey(hostKey),
|
||||
HostKeyCallback: ssh.HostKeyCallback(func(host string, remote net.Addr, key ssh.PublicKey) error {
|
||||
app.SshAddHostKey(host, remote, key)
|
||||
|
||||
return nil
|
||||
}),
|
||||
}
|
||||
|
||||
cmpSshCli.Connect, err = ssh.Dial("tcp", cmpSshCli.Host, config)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (app *App) SshSession(cmpSshCli *cmpSshCliStruct) error {
|
||||
var err error
|
||||
|
||||
cmpSshCli.Session, err = cmpSshCli.Connect.NewSession()
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// defer cmpSshCli.Session.Close()
|
||||
|
||||
modes := ssh.TerminalModes{
|
||||
ssh.ECHO: 0,
|
||||
}
|
||||
|
||||
err = cmpSshCli.Session.RequestPty("xterm", 50, 80, modes)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// sshIn, err := session.StdinPipe()
|
||||
// if err != nil {
|
||||
// app.Log(err)
|
||||
// return err
|
||||
// }
|
||||
|
||||
sshOut, err := cmpSshCli.Session.StdoutPipe()
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
sshErr, err := cmpSshCli.Session.StderrPipe()
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
output := io.MultiReader(sshOut, sshErr)
|
||||
|
||||
cmpSshCli.Output = bufio.NewReader(output)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (app *App) SshConn(host string, keyfile string) (int, error) {
|
||||
var err error
|
||||
|
||||
// app.Log(url)
|
||||
|
||||
var cmpSshCli cmpSshCliStruct
|
||||
|
||||
err = app.SshConnReal(&cmpSshCli, host, keyfile)
|
||||
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
err = app.SshSession(&cmpSshCli)
|
||||
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
app.SshList = append(app.SshList, cmpSshCli)
|
||||
|
||||
app.Log("Append new")
|
||||
|
||||
return len(app.SshList)-1, nil
|
||||
}
|
||||
|
||||
func (app *App) SshExec(cmpWbsCli cmpWbsCliStruct, idx int, cma []string) (error) {
|
||||
var err error
|
||||
|
||||
cmd := strings.Join(cma, " ")
|
||||
|
||||
cmpSshCli := app.SshList[idx]
|
||||
|
||||
// app.Log("idx: '%s', '%s'", idx, cmpSshCli.Host)
|
||||
|
||||
err = cmpSshCli.Session.Start(cmd)
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
res := map[string]interface{}{
|
||||
"string": nil,
|
||||
}
|
||||
|
||||
var bli []byte
|
||||
var sli string
|
||||
|
||||
for {
|
||||
bli, _, err = cmpSshCli.Output.ReadLine()
|
||||
|
||||
if err != nil {
|
||||
app.Log("Complete")
|
||||
break
|
||||
}
|
||||
|
||||
sli = string(bli)
|
||||
|
||||
app.Log(sli)
|
||||
|
||||
res["string"] = sli
|
||||
|
||||
app.HttpWebSockSendTo(cmpWbsCli, "cmpSshTest", res)
|
||||
}
|
||||
|
||||
cmpSshCli.Session.Wait()
|
||||
|
||||
app.Log("Free resource SshList[" + string(idx) + "]")
|
||||
|
||||
cmpSshCli.Session.Close()
|
||||
|
||||
cmpSshCli.Connect.Close()
|
||||
|
||||
|
||||
app.Log("Remove SshList[" + string(idx) + "]")
|
||||
|
||||
var list []cmpSshCliStruct
|
||||
|
||||
for i, li := range app.SshList {
|
||||
if i == idx {
|
||||
continue
|
||||
}
|
||||
|
||||
list = append(list, li)
|
||||
}
|
||||
|
||||
app.SshList = list
|
||||
|
||||
app.Log("End")
|
||||
|
||||
// done <- true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (app *App) CmpSshTestSnip(parm any) (any, error) {
|
||||
var err error
|
||||
|
||||
// var ifcIM map[string]interface{} = parm
|
||||
|
||||
cli, err := app.SnipGetCli(parm)
|
||||
|
||||
// app.Log(cli)
|
||||
|
||||
if err != nil {
|
||||
return map[string]interface{}{
|
||||
"string": "Not client found",
|
||||
}, err
|
||||
}
|
||||
|
||||
|
||||
host, err := app.ConfGetStr("sshTestHost", "HostPort")
|
||||
|
||||
if err != nil {
|
||||
return map[string]interface{}{
|
||||
"string": "Not set sshTestHost.HostPort",
|
||||
}, err
|
||||
}
|
||||
|
||||
keyfile, err := app.ConfGetStr("sshTestHost", "PrivateKeyFile")
|
||||
|
||||
if err != nil {
|
||||
return map[string]interface{}{
|
||||
"string": "Not set sshTestHost.PrivateKeyFile",
|
||||
}, err
|
||||
}
|
||||
|
||||
cmi, err := app.ConfGetIfc("sshTestHost", "Command")
|
||||
|
||||
if err != nil {
|
||||
return map[string]interface{}{
|
||||
"string": "Not set sshTestHost.Command",
|
||||
}, err
|
||||
}
|
||||
|
||||
cml := cmi.([]interface{})
|
||||
|
||||
cma := make([]string, len(cml))
|
||||
|
||||
for i, v := range cml {
|
||||
cma[i] = v.(string)
|
||||
}
|
||||
|
||||
/*
|
||||
if cma[0] == "none" {
|
||||
return map[string]interface{}{
|
||||
"string": "Can't get command",
|
||||
}, err
|
||||
}
|
||||
*/
|
||||
|
||||
idx, err := app.SshConn(host, keyfile)
|
||||
|
||||
if err != nil {
|
||||
return map[string]interface{}{
|
||||
"string": "Connection to '" + host + "' failed",
|
||||
}, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
app.SshExec(cli, idx, cma)
|
||||
}()
|
||||
|
||||
app.Log("Wait")
|
||||
|
||||
return map[string]interface{}{
|
||||
"string": "Launch: " + strings.Join(cma, " "),
|
||||
}, nil
|
||||
}
|
Reference in New Issue
Block a user