1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-25 16:58:06 +08:00
This commit is contained in:
shaoying 2019-05-11 17:16:05 +08:00
parent 23f0bb07b0
commit 8e1b86d554
16 changed files with 375 additions and 884 deletions

View File

@ -1,5 +1,3 @@
~ssh
config trust up true
~mdb
note model favor spirit spirit relate relate
note model money expend expend amount amount

View File

@ -1,5 +1,5 @@
~code
config save tmp/flash.json flash
~ssh
config save tmp/cert.json cert trust
~aaa
config save tmp/auth.json auth
~cli

View File

@ -2,8 +2,8 @@
config load tmp/runtime.json runtime
~aaa
config load tmp/auth.json auth
~code
config load tmp/flash.json flash
~ssh
config load tmp/cert.json cert trust
source etc/common.shy
~ssh

View File

@ -461,7 +461,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
for i := 1; i < len(arg); i++ { // 添加用户
if m.Cmd("aaa.auth", "ship", "username", arg[i], "userrole", role); i < len(arg)-2 {
switch arg[i+1] {
case "password", "uuid":
case "password", "uuid", "cert":
m.Cmd("aaa.auth", "ship", "username", arg[i], arg[i+1], arg[i+2])
i += 2
}
@ -628,26 +628,30 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
// 检查权限
m.Cmd("aaa.auth", "ship", "username", m.Option("username"), "userrole").Table(func(node map[string]string) {
if node["meta"] == "root" { // 超级用户
m.Log("info", "role: root")
m.Echo("true")
if m.Options("userrole") && node["meta"] != m.Option("userrole") {
return // 失败
} else if node["meta"] == "root" { // 超级用户
} else if len(arg) > 2 { // 接口权限
if m.Cmds("aaa.auth", m.Option("bench"), "ship", "check", arg[2]) {
m.Echo("true")
} else if cid := m.Cmdx("aaa.auth", "ship", "userrole", node["meta"], "componet", arg[1], "check", arg[2]); kit.Right(cid) {
m.Log("info", "role: %s", node["meta"])
m.Cmd("aaa.auth", m.Option("bench"), cid)
m.Echo("true")
} else {
return // 失败
}
} else if len(arg) > 1 { // 组件权限
if m.Cmds("aaa.auth", m.Option("bench"), "ship", "check", arg[1]) {
m.Echo("true")
} else if cid := m.Cmdx("aaa.auth", "ship", "userrole", node["meta"], "check", arg[1]); kit.Right(cid) {
m.Log("info", "role: %s", node["meta"])
m.Cmd("aaa.auth", m.Option("bench"), cid)
m.Echo("true")
} else {
return // 失败
}
}
m.Log("info", "role: %s %v", node["meta"], arg[1:])
m.Echo(node["meta"])
})
m.Log("right", "bench: %s sessid: %s user: %s com: %v result: %v",
@ -746,8 +750,8 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
// 生成证书
template := x509.Certificate{
SerialNumber: big.NewInt(1),
IsCA: true,
SerialNumber: big.NewInt(1),
IsCA: true,
BasicConstraintsValid: true,
KeyUsage: x509.KeyUsageCertSign,
Subject: pkix.Name{CommonName: kit.Format(common)},

View File

@ -466,32 +466,41 @@ func (m *Message) Format(arg ...interface{}) string {
}
}
meta = append(meta, "\n")
for i := len(ms) - 1; i >= 0; i-- {
msg := ms[i]
meta = append(meta, fmt.Sprintf("\n%s\n", msg.Format("time", "ship")))
meta = append(meta, fmt.Sprintf(" detail: %d %v\n", len(msg.Meta["detail"]), msg.Meta["detail"]))
meta = append(meta, fmt.Sprintf(" option: %d %v\n", len(msg.Meta["option"]), msg.Meta["option"]))
for _, k := range msg.Meta["option"] {
if v, ok := msg.Data[k]; ok {
meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v)))
} else if v, ok := msg.Meta[k]; ok {
meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v))
meta = append(meta, fmt.Sprintf("%s\n", msg.Format("time", "ship")))
if len(msg.Meta["detail"]) > 0 {
meta = append(meta, fmt.Sprintf(" detail: %d %v\n", len(msg.Meta["detail"]), msg.Meta["detail"]))
}
if len(msg.Meta["option"]) > 0 {
meta = append(meta, fmt.Sprintf(" option: %d %v\n", len(msg.Meta["option"]), msg.Meta["option"]))
for _, k := range msg.Meta["option"] {
if v, ok := msg.Data[k]; ok {
meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v)))
} else if v, ok := msg.Meta[k]; ok {
meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v))
}
}
}
meta = append(meta, fmt.Sprintf(" append: %d %v\n", len(msg.Meta["append"]), msg.Meta["append"]))
for _, k := range msg.Meta["append"] {
if v, ok := msg.Data[k]; ok {
meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v)))
} else if v, ok := msg.Meta[k]; ok {
meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v))
if len(msg.Meta["append"]) > 0 {
meta = append(meta, fmt.Sprintf(" append: %d %v\n", len(msg.Meta["append"]), msg.Meta["append"]))
for _, k := range msg.Meta["append"] {
if v, ok := msg.Data[k]; ok {
meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v)))
} else if v, ok := msg.Meta[k]; ok {
meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v))
}
}
}
meta = append(meta, fmt.Sprintf(" result: %d %v\n", len(msg.Meta["result"]), msg.Meta["result"]))
if len(msg.Meta["result"]) > 0 {
meta = append(meta, fmt.Sprintf(" result: %d %v\n", len(msg.Meta["result"]), msg.Meta["result"]))
}
}
case "stack":
pc := make([]uintptr, 100)
pc = pc[:runtime.Callers(2, pc)]
pc = pc[:runtime.Callers(6, pc)]
frames := runtime.CallersFrames(pc)
for {
@ -1570,7 +1579,7 @@ func (m *Message) Cmd(args ...interface{}) *Message {
msg := m
if strings.Contains(key, ":") {
ps := strings.Split(key, ":")
msg, key, arg = msg.Sess("ssh"), "sh", append([]string{"node", ps[0], "sync", ps[1]}, arg...)
msg, key, arg = msg.Sess("ssh"), "remote", append([]string{"sync", ps[0], ps[1]}, arg...)
defer func() { m.Copy(msg, "append").Copy(msg, "result") }()
m.Hand = true

View File

@ -1,115 +0,0 @@
package ctx
import (
"fmt"
"testing"
)
func TestCtx(t *testing.T) {
context := Context{Name: "root", Help: "默认",
Caches: map[string]*Cache{
"nclient": &Cache{"nclient", "10", "连接数量", func(c *Context) string {
return "10"
}},
},
Configs: map[string]*Config{
"limit": &Config{"limit", "10", "最大连接数", func(c *Context, arg string) {
}},
},
Commands: map[string]*Command{
"session": &Command{"session", "会话管理", func(c *Context, arg ...string) string {
return "ok"
}},
},
}
context.Index = map[string]*Context{"root": &context}
ctx := context.Index["root"]
ctx.Add("context", "hi", "hi", "nice")
if _, ok := context.Contexts["hi"]; !ok {
t.Fatal("root.ctxs add error")
}
if c, ok := context.Index["hi"]; ok {
ctx.Add("command", "hi", "session")
if _, ok := c.Commands["session"]; ok {
if c.Cmd("session") != "ok" {
t.Fatal("hi.cmds.session: run error")
}
} else {
t.Fatal("hi.cmds: add error")
}
ctx.Add("config", "hi", "limit")
ctx.Add("cache", "hi", "nclient")
} else {
t.Fatal("root.index add error")
}
return
if true {
ctx := context.Index["hi"]
if ctx.Cmd("session", "nice") == "ok" {
t.Log("hi.cmds.session: run")
} else {
t.Fatal("hi.cmds.session: run error")
}
t.Log()
ctx.Add("context", "he", "he", "nice")
for k, v := range ctx.Contexts {
t.Log("hi.ctxs", k, v.Name, v.Help)
}
if len(ctx.Contexts) != 1 {
t.Fatal("hi.ctxs: add error")
}
for k, v := range ctx.Index {
t.Log("hi.index:", k, v.Name, v.Help)
}
if len(ctx.Index) != 3 {
t.Fatal("hi.index: add error")
}
t.Log()
ctx.Add("command", "he", "session")
for k, v := range ctx.Contexts["he"].Commands {
t.Log("he.cmds:", k, v.Name, v.Help)
}
if len(ctx.Contexts["he"].Commands) != 1 {
t.Fatal("he.cmds: add error")
}
}
for k, v := range ctx.Index {
t.Log("root.index:", k, v.Name, v.Help)
}
if len(ctx.Index) != 3 {
t.Fatal("root.index add error")
}
t.Log()
for k, v := range ctx.Index {
t.Log(fmt.Sprintf("root.index.%s.cmds: %d", k, len(v.Commands)))
}
t.Log()
ctx.Del("command", "hi", "session")
for k, v := range ctx.Index {
t.Log(fmt.Sprintf("root.index.%s.cmds: %d", k, len(v.Commands)))
}
t.Log()
ctx.Del("context", "hi")
for k, v := range ctx.Contexts {
t.Log("root.ctxs:", k, v.Name, v.Help)
}
if len(ctx.Contexts) != 0 {
t.Fatal("root.ctxs: del error")
}
for k, v := range ctx.Index {
t.Log("root.index:", k, v.Name, v.Help)
}
if len(ctx.Index) != 1 {
t.Fatal("root.index del error")
}
}

View File

@ -1,28 +0,0 @@
package gdb
import (
"contexts/ctx"
"testing"
"time"
)
func TestLog(t *testing.T) {
m := ctx.Pulse.Spawn(Index)
m.Sess("gdb", m)
m.Target().Begin(m).Start(m)
go func() {
t.Logf("%s", m.Cmd("wait", "config", "demo").Result(0))
// t.Logf("%s", m.Cmd("demo", "what").Result(0))
}()
time.Sleep(time.Second * 3)
m.Spawn().Cmd("goon", "nice")
// gdb := m.Target().Server.(*GDB)
// gdb.Goon("yes", "command", "demo")
//
time.Sleep(time.Second * 3)
}

View File

@ -1,152 +0,0 @@
package lex
import (
"context"
"testing"
)
func TestLEX(t *testing.T) {
m := ctx.Pulse.Spawn(Index)
seed := map[string]map[string]string{
// "shy?": map[string]string{
// "s": "",
// "sh": "sh",
// "she": "sh",
// "shy": "shy",
// "shyyy": "shy",
// },
// "shy*": map[string]string{
// "s": "",
// "sh": "sh",
// "she": "sh",
// "shy": "shy",
// "shyyy": "shyyy",
// },
// "shy+": map[string]string{
// "s": "",
// "sh": "",
// "she": "",
// "shy": "shy",
// "shyyy": "shyyy",
// },
// "s?hy": map[string]string{
// "s": "",
// "sh": "",
// "she": "",
// "shy": "shy",
// "hy": "hy",
// },
// "s*hy": map[string]string{
// "s": "",
// "sh": "",
// "she": "",
// "shy": "shy",
// "ssshy": "ssshy",
// "hy": "hy",
// },
// "s+hy": map[string]string{
// "s": "",
// "sh": "",
// "she": "",
// "shy": "shy",
// "ssshy": "ssshy",
// "hy": "",
// },
// "sh[xyz]?": map[string]string{
// "s": "",
// "sh": "sh",
// "she": "sh",
// "shy": "shy",
// "shyyy": "shy",
// },
// "sh[xyz]*": map[string]string{
// "s": "",
// "sh": "sh",
// "she": "sh",
// "shy": "shy",
// "shyyy": "shyyy",
// "shyxz": "shyxz",
// },
// "sh[xyz]+": map[string]string{
// "s": "",
// "sh": "",
// "she": "",
// "shy": "shy",
// "shyyy": "shyyy",
// "shyxzy": "shyxzy",
// },
// "[xyz]?sh": map[string]string{
// "s": "",
// "sh": "sh",
// "zsh": "zsh",
// "zxyshy": "",
// },
// "[xyz]*sh": map[string]string{
// "s": "",
// "sh": "sh",
// "zsh": "zsh",
// "zxyshy": "zxysh",
// },
// "[xyz]+sh": map[string]string{
// "s": "",
// "sh": "",
// "zsh": "zsh",
// "zxyshy": "zxysh",
// },
// "[0-9]+": map[string]string{
// "hello": "",
// "hi123": "",
// "123": "123",
// "123hi": "123",
// },
// "0x[0-9a-fA-F]+": map[string]string{
// "hello": "",
// "0xhi123": "",
// "0x123": "0x123",
// "0xab123ab": "0xab123ab",
// "0x123ab": "0x123ab",
// },
"[a-zA-Z][a-zA-Z0-9]*": map[string]string{
"hello": "hello",
"hi123": "hi123",
"123": "",
},
"\"[^\"]*\"": map[string]string{
"hello": "",
"0xhi123": "",
"\"hi\"": "\"hi\"",
"\"\\\"hi\"": "\"\\\"hi\"",
},
}
m.Conf("debug", "on")
Index.Begin(m)
for k, s := range seed {
Index.Start(m)
m.Cmd("train", k)
for i, v := range s {
if m.Cmd("parse", i) != v {
t.Error("train&parse error:", k, i, v)
}
}
}
Index.Start(m)
m.Cmd("train", "[ \n\t]+", "1")
m.Cmd("train", "[a-zA-Z][a-zA-Z0-9]*", "2", "2")
m.Cmd("train", "0x[0-9]+", "3", "2")
m.Cmd("train", "[0-9]+", "3", "2")
m.Cmd("train", "\"[^\"]*\"", "4", "2")
m.Cmd("train", "'[^']*'", "4", "2")
lex := Index.Server.(*LEX)
for _, v := range lex.seed {
t.Log(v.page, v.hash, v.word)
}
m.Cmd("split", "hello 0x2134 \"hi he\" meet\\ you")
// m.Cmd("parse", "0x54 nice to meet")
// m.Cmd("parse", "737 nice to meet")
// m.Cmd("parse", "\"73 u\" nice to meet")
// m.Cmd("parse", "'hh h' nice to meet")
}

View File

@ -1,19 +0,0 @@
package log
import (
"contexts/ctx"
"testing"
)
func TestLog(t *testing.T) {
m := ctx.Pulse.Spawn(Index)
m.Target().Begin(m)
m.Sess("log", m)
m.Log("error", "what %v", 123)
m.Log("debug", "what %v", 123)
m.Log("info", "what %v", 123)
m.Log("cmd", "what %v", 123)
m.Log("begin", "what %v", 123)
m.Log("search", "what %v", 123)
m.Cmd("log", "search", "what %v", 123)
}

View File

@ -1,61 +0,0 @@
package mdb
import (
"context"
"flag"
"log"
"os"
"testing"
)
func TestOpen(t *testing.T) {
flag.Parse()
args := flag.Args()
if len(args) < 2 {
t.Fatal("usages: -args source driver [table]")
}
source := "user:word@/book"
driver := "mysql"
source = args[0]
driver = args[1]
//mysql -u root -p;
//create database book;
//grant all on book.* to user identified by 'word'
ctx.Start()
ctx.Index.Conf("debug", "off")
log.SetOutput(os.Stdout)
m := ctx.Pulse.Spawn(Index)
m.Meta = nil
m.Cmd("open", source, driver)
m.Meta = nil
m.Cmd("exec", "insert into program(time, hash, name) values(?, ?, ?)", "1", "2", "3")
m.Meta = nil
m.Cmd("exec", "insert into program(time, hash, name) values(?, ?, ?)", "1", "2", "3")
m.Meta = nil
m.Cmd("exec", "insert into program(time, hash, name) values(?, ?, ?)", "2", "3", "4")
m.Meta = nil
m.Cmd("query", "select time, hash, name from program")
t.Log()
for i, rows := 0, len(m.Meta[m.Meta["append"][0]]); i < rows; i++ {
for _, k := range m.Meta["append"] {
t.Log(k, m.Meta[k][i])
}
t.Log()
}
if len(m.Meta["append"]) != 3 || len(m.Meta[m.Meta["append"][0]]) != 2 {
t.Error()
}
m.Meta = nil
// Index.Exit(m)
}

View File

@ -2,10 +2,6 @@ package ssh
import (
"contexts/ctx"
"encoding/base64"
"fmt"
"os"
"path"
"strings"
"toolkit"
)
@ -29,7 +25,7 @@ func (ssh *SSH) Start(m *ctx.Message, arg ...string) bool {
return true
}
func (ssh *SSH) Close(m *ctx.Message, arg ...string) bool {
return true
return false
}
var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
@ -37,12 +33,10 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
"nnode": &ctx.Cache{Name: "nnode", Value: "0", Help: "节点数量"},
},
Configs: map[string]*ctx.Config{
"current": &ctx.Config{Name: "current", Value: "", Help: "当前主机"},
"trust": &ctx.Config{Name: "trust", Value: map[string]interface{}{}, Help: "可信主机"},
"node": &ctx.Config{Name: "node", Value: map[string]interface{}{}, Help: "主机信息"},
"timer": &ctx.Config{Name: "timer", Value: map[string]interface{}{"interval": "10s", "timer": ""}, Help: "断线重连"},
"cert": &ctx.Config{Name: "cert", Value: map[string]interface{}{}, Help: "用户证书"},
"node": &ctx.Config{Name: "node", Value: map[string]interface{}{}, Help: "节点信息"},
"cert": &ctx.Config{Name: "cert", Value: map[string]interface{}{}, Help: "用户信息"},
"trust": &ctx.Config{Name: "trust", Value: map[string]interface{}{"fresh": true, "user": true, "up": true}, Help: "可信节点"},
"timer": &ctx.Config{Name: "timer", Value: map[string]interface{}{"interval": "10s", "timer": ""}, Help: "断线重连"},
},
Commands: map[string]*ctx.Command{
"init": &ctx.Command{Name: "init", Help: "启动", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
@ -55,60 +49,273 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
}
m.Conf("runtime", "node.route", m.Conf("runtime", "node.name"))
m.Conf("runtime", "user.name", m.Conf("runtime", "boot.USER"))
m.Conf("runtime", "work.name", m.Conf("runtime", "boot.USER"))
return
}},
"cert": &ctx.Command{Name: "cert [node|user|work [create [args...]]]", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
"node": &ctx.Command{Name: "node [create|delete [name [type module]]]", Help: "节点", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmdy("ctx.config", "node", "format", "table", "fields", "type", "module", "create_time")
return
}
switch arg[0] {
case "create": // 添加节点
m.Log("info", "create node %s %s", arg[1], arg[2])
m.Confv("node", arg[1], map[string]interface{}{
"name": arg[1], "type": arg[2], "module": arg[3],
"create_time": m.Time(),
})
case "delete": // 删除节点
m.Log("info", "delete node %s %s", arg[1], kit.Formats(m.Conf("node", arg[1])))
delete(m.Confm("node"), arg[1])
}
return
}},
"cert": &ctx.Command{Name: "cert [node|user|work]", Help: []string{"认证",
"node [create|check text|trust node]",
"user [create|check text|share role node...|proxy node|trust node]",
"work [create node name|check node name]",
}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Add("append", "key", "node.cert")
m.Add("append", "route", m.Conf("runtime", "node.route"))
m.Add("append", "value", m.Conf("runtime", "node.cert"))
m.Add("append", "key", "user.cert")
m.Add("append", "route", m.Conf("runtime", "user.route"))
m.Add("append", "value", m.Conf("runtime", "user.cert"))
m.Add("append", "key", "work.name")
m.Add("append", "route", m.Conf("runtime", "work.route"))
m.Add("append", "value", m.Conf("runtime", "work.name"))
m.Table()
return
}
switch arg[0] {
case "node": // 节点证书
if len(arg) > 1 && arg[1] == "create" {
case "node": // 节点认证
if len(arg) == 1 {
m.Echo(m.Conf("runtime", "node.cert"))
break
}
switch arg[1] {
case "create": // 创建证书
msg := m.Cmd("aaa.rsa", "gen")
m.Conf("runtime", "node.cert", msg.Append("certificate"))
m.Conf("runtime", "node.key", msg.Append("private"))
}
m.Echo(m.Conf("runtime", "node.cert"))
m.Echo(m.Conf("runtime", "node.cert"))
case "user": // 用户证书
if len(arg) > 1 && arg[1] == "create" {
case "check": // 数字验签
if m.Option("node.cert", m.Cmd("aaa.auth", "nodes", m.Option("node.route"), "cert").Append("meta")); !m.Options("node.cert") {
m.Option("node.cert", m.Cmdx("ssh.remote", m.Option("node.route"), "check", "node"))
m.Cmd("aaa.auth", "nodes", m.Option("node.route"), "cert", m.Option("node.cert"))
}
if !m.Cmds("aaa.rsa", "verify", m.Option("node.cert"), m.Option("node.sign"), arg[2]) {
m.Log("warn", "node error")
m.Echo("false")
} else {
m.Echo("true")
}
case "trust": // 可信节点
if m.Confs("trust", arg[2]) {
m.Echo("true")
} else if m.Confs("trust", "user") && m.Conf("runtime", "user.route") == arg[2] {
m.Echo("true")
} else if m.Confs("trust", "up") && strings.HasPrefix(m.Conf("runtime", "node.route"), arg[2]) {
m.Echo("true")
}
}
case "user": // 用户认证
if len(arg) == 1 {
m.Echo(m.Conf("runtime", "user.cert"))
break
}
switch arg[1] {
case "create": // 创建证书
msg := m.Cmd("aaa.rsa", "gen")
m.Conf("runtime", "user.route", m.Conf("runtime", "node.route"))
m.Conf("runtime", "user.cert", msg.Append("certificate"))
m.Conf("runtime", "user.key", msg.Append("private"))
}
m.Echo(m.Conf("runtime", "user.cert"))
m.Echo(m.Conf("runtime", "user.cert"))
case "work": // 工作证书
if len(arg) > 1 && arg[1] == "create" {
if name := m.Cmdx("ssh.sh", "node", arg[2], "check", "work", m.Conf("runtime", "user.route"), m.Conf("runtime", "user.cert"), arg[3]); name != "" {
case "check": // 数字验签
if m.Option("user.cert", m.Cmd("aaa.auth", "username", m.Option("username"), "cert").Append("meta")); !m.Options("user.cert") {
m.Option("user.cert", m.Cmd("ssh.remote", m.Option("user.route"), "check", "user").Append("user.cert"))
m.Cmd("aaa.auth", "username", m.Option("username"), "cert", m.Option("user.cert"))
m.Cmd("aaa.auth", "username", m.Option("username"), "userrole", "void")
}
if !m.Options("user.cert") || !m.Cmds("aaa.rsa", "verify", m.Option("user.cert"), m.Option("user.sign"), arg[2]) {
m.Log("warn", "user error")
m.Echo("false")
} else {
m.Echo("true")
}
case "share": // 共享用户
for _, route := range arg[3:] {
user := m.Cmd("ssh.remote", route, "check", "user")
if m.Cmd("aaa.role", arg[2], "user", user.Append("user.name"), "cert", user.Append("user.cert")); arg[2] == "root" && route != m.Conf("runtime", "node.route") {
m.Conf("runtime", "user.route", user.Append("user.route"))
m.Conf("runtime", "user.name", user.Append("user.name"))
m.Conf("runtime", "user.cert", user.Append("user.cert"))
m.Conf("runtime", "user.key", "")
}
}
case "proxy": // 代理用户
if len(arg) == 2 {
m.Cmdy("aaa.auth", "proxy")
break
}
if !m.Cmds("aaa.auth", "proxy", arg[2], "session") {
m.Cmdy("aaa.sess", "proxy", "proxy", arg[2])
}
case "trust": // 可信代理
hash := kit.Hashs("rand", m.Option("text.time", m.Time("stamp")), arg[2])
m.Option("user.sign", m.Cmdx("ssh.remote", m.Option("user.route"), "check", "user", arg[2], hash))
m.Echo("%s", m.Options("user.sign") && m.Cmds("ssh.check", hash))
}
case "work": // 公有认证
if len(arg) == 1 {
m.Echo(m.Conf("runtime", "work.name"))
break
}
switch arg[1] {
case "create": // 创建证书
if name := m.Cmdx("ssh.remote", arg[2], "check", "work", arg[3], m.Conf("runtime", "user.route"), m.Conf("runtime", "user.cert")); name != "" {
m.Conf("runtime", "work.route", arg[2])
m.Conf("runtime", "work.name", name)
m.Echo(name)
}
case "check": // 数字验签
if m.Option("user.route") != m.Cmdx("ssh.remote", arg[2], "check", "work", arg[3]) {
m.Log("warn", "work error")
m.Echo("false")
} else {
m.Echo("true")
}
}
m.Echo(m.Conf("runtime", "work.name"))
}
return
}},
"remote": &ctx.Command{Name: "remote auto|dial|listen args...", Help: "远程连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmdy("ctx.config", "node", "format", "table")
m.Meta["append"] = []string{"key", "type", "create_time"}
"check": &ctx.Command{Name: "check node|user|work", Help: []string{"验签",
"node", "user [node text]", "work name [node cert]",
}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
switch arg[0] {
case "node": // 节点验签
m.Echo(m.Conf("runtime", "node.cert"))
case "user": // 用户验签
if len(arg) == 1 {
m.Append("user.cert", m.Conf("runtime", "user.cert"))
m.Append("user.name", m.Conf("runtime", "user.name"))
m.Append("user.route", kit.Select(m.Conf("runtime", "node.route"), m.Conf("runtime", "user.route")))
} else { // 代理签证
if arg[1] == m.Conf("runtime", "node.route") || m.Cmds("aaa.auth", "proxy", arg[1], "session") {
m.Echo(m.Cmdx("aaa.rsa", "sign", m.Conf("runtime", "user.key"), arg[2]))
}
}
case "work": // 工作验签
if cert := m.Confm("cert", arg[1]); len(arg) == 2 {
if cert != nil {
m.Echo("%s", cert["user"])
}
} else { // 工作签证
if cert == nil {
m.Conf("cert", arg[1], map[string]interface{}{"create_time": m.Time(), "user": arg[2]})
} else if cert["user"] != arg[2] {
return // 签证失败
}
m.Echo(arg[1])
}
}
return
}},
"action": &ctx.Command{Name: "action", Help: "命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
hash := kit.Hashs(
m.Option("text.rand"),
m.Option("text.time"),
m.Option("text.cmd"),
m.Option("text.route"),
m.Option("node.route"),
m.Option("user.route"),
m.Option("user.name"),
m.Option("work.name"),
m.Option("work.route"),
)
// 文本验签
if m.Option("text.hash") != hash {
m.Echo("text error %s != %s", m.Option("text.hash"), hash)
m.Log("warn", "text error")
return
}
// 设备验签
if !m.Cmds("ssh.cert", "node", "check", hash) {
m.Echo("node error of %s", m.Option("node.route"))
return
}
// 用户验签
m.Option("username", m.Option("user.name"))
if !m.Confs("runtime", "user.route") && m.Confs("trust", "fresh") {
m.Log("warn", "trust fresh %s", m.Option("node.route"))
m.Option("trust", "fresh")
} else if m.Cmds("ssh.cert", "node", "trust", m.Option("node.route")) {
m.Log("warn", "trust node %s", m.Option("node.route"))
m.Option("trust", "node")
} else if m.Options("user.route") && m.Cmds("ssh.cert", "node", "trust", m.Option("user.route")) && m.Cmds("ssh.cert", "user", "trust", m.Option("node.route")) {
m.Log("warn", "trust user %s", m.Option("user.route"))
m.Option("trust", "user")
} else if m.Option("username", m.Option("work.name")); m.Options("work.route") && m.Cmds("ssh.cert", "node", "trust", m.Option("work.route")) && m.Cmds("ssh.cert", "work", "check", m.Option("work.route"), m.Option("username")) {
m.Log("warn", "trust work %s", m.Option("work.route"))
m.Option("trust", "work")
} else if m.Option("userrole", "void"); m.Confs("trust", "none") {
m.Log("warn", "trust none")
m.Option("trust", "none")
} else {
m.Log("warn", "user error of %s", m.Option("user.route"))
return
}
m.Log("info", "username: %s", m.Option("username"))
// 创建会话
m.Option("sessid", m.Cmdx("aaa.user", "session", "select"))
// 创建空间
m.Option("bench", m.Cmdx("aaa.sess", "bench", "select"))
// 权限检查
if !m.Cmds("aaa.work", "right", "remote", arg[0]) {
m.Echo("no right %s %s", "remote", arg[0])
return
}
// 执行命令
m.Cmdm(arg)
return
}},
"remote": &ctx.Command{Name: "remote auto|dial|listen args...", Help: "连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
// 设备证书
if !m.Confs("runtime", "node.cert") || !m.Confs("runtime", "node.key") {
msg := m.Cmd("aaa.rsa", "gen", "common", m.Confv("runtime", "node"))
m.Conf("runtime", "node.cert", msg.Append("certificate"))
m.Conf("runtime", "node.key", msg.Append("private"))
m.Cmd("ssh.cert", "node", "create")
}
switch arg[0] {
@ -134,7 +341,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
case "dial": // 连接主机
m.Call(func(nfs *ctx.Message) *ctx.Message {
// 断线重连
// 删除重连
if m.Confs("timer", "timer") {
m.Conf("timer", "timer", m.Cmdx("cli.timer", "delete", m.Conf("timer", "timer")))
}
@ -142,101 +349,82 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
// 注册设备
m.Spawn(nfs.Target()).Call(func(node *ctx.Message) *ctx.Message {
// 添加网关
m.Confv("node", node.Append("node.name"), map[string]interface{}{
"module": m.Cap("stream", nfs.Format("target")),
"create_time": m.Time(),
"type": "master",
"name": node.Append("node.name"),
m.Cmd("ssh.node", "create", node.Append("node.name"), "master", m.Cap("stream", nfs.Format("target")))
// 清理回调
nfs.Free(func(nfs *ctx.Message) bool {
m.Cmd("aaa.auth", m.Cmdx("aaa.auth", "nodes", node.Append("node.name")), "delete", "node")
m.Cmd("ssh.node", "delete", node.Append("node.name"))
m.Cap("stream", "")
// 断线重连
m.Conf("timer", "timer", m.Cmdx("cli.timer", "repeat", m.Conf("timer", "interval"), "context", "ssh", "remote", "redial", arg[1:]))
return true
})
// 本机路由
m.Conf("runtime", "node.route", node.Append("node.route")+"."+node.Result(0))
// 本机用户
if !m.Confs("runtime", "user.route") {
if m.Confs("runtime", "user.cert") && m.Confs("runtime", "user.key") {
m.Cmd("ssh.share", "root", m.Conf("runtime", "node.route"))
} else if node.Appends("user.route") {
m.Cmd("ssh.share", "root", node.Append("user.route"))
}
}
// 用户路由
if m.Confs("runtime", "user.cert") && m.Confs("runtime", "user.key") {
m.Conf("runtime", "user.route", m.Conf("runtime", "node.route"))
// 网关用户
if !node.Appends("user.route") {
m.Cmd("ssh.share", node.Append("node.route"), "root", m.Conf("runtime", "node.route"))
} else if node.Appends("user.route") && !m.Confs("runtime", "user.route") {
m.Cmd("ssh.node", "share", "root", node.Append("user.route"))
}
// 清理主机
nfs.Free(func(nfs *ctx.Message) bool {
m.Conf("timer", "timer", m.Cmdx("cli.timer", "repeat", m.Conf("timer", "interval"), "context", "ssh", "remote", "redial", arg[1:]))
m.Cmd("aaa.auth", m.Cmdx("aaa.auth", "nodes", node.Append("node.name")), "delete", "node")
m.Log("info", "delete node %s", node.Append("node.name"))
delete(m.Confm("node"), node.Append("node.name"))
m.Cap("stream", "")
return true
})
return nil
}, "send", "recv", "add", m.Conf("runtime", "node.name"), m.Conf("runtime", "node.type"), m.Conf("runtime", "node.cert"))
}, "send", "add", m.Conf("runtime", "node.name"), m.Conf("runtime", "node.type"), m.Conf("runtime", "node.cert"))
return nil
}, "nfs.remote", arg)
case "recv":
switch arg[1] {
case "add":
// 节点命名
name := arg[2]
for node := m.Confm("node", name); node != nil; node = m.Confm("node", name) {
name = fmt.Sprintf("%s_%d", arg[2], m.Capi("nnode", 1))
}
// 添加节点
m.Confv("node", name, map[string]interface{}{
"module": m.Format("source"),
"create_time": m.Time(),
"type": arg[3],
"name": name,
})
// 节点路由
m.Append("user.name", m.Conf("runtime", "user.name"))
m.Append("user.route", m.Conf("runtime", "user.route"))
m.Append("node.route", m.Conf("runtime", "node.route"))
m.Append("node.name", m.Conf("runtime", "node.name"))
m.Echo(name).Back(m)
// 清理节点
m.Sess("ms_source", false).Free(func(msg *ctx.Message) bool {
m.Cmd("aaa.auth", m.Cmdx("aaa.auth", "nodes", name), "delete", "node")
m.Log("info", "delete node %s", name)
delete(m.Confm("node"), name)
return true
})
case "add":
// 命名节点
name := arg[1]
for node := m.Confm("node", name); node != nil; node = m.Confm("node", name) {
name = kit.Format("%s_%s", arg[1], m.Capi("nnode", 1))
}
// 添加节点
m.Cmd("ssh.node", "create", name, arg[2], m.Format("source"))
// 清理回调
m.Sess("ms_source", false).Free(func(msg *ctx.Message) bool {
m.Cmd("aaa.auth", m.Cmdx("aaa.auth", "nodes", name), "delete", "node")
m.Cmd("ssh.node", "delete", name)
return true
})
// 同步信息
m.Append("node.name", m.Conf("runtime", "node.name"))
m.Append("node.route", m.Conf("runtime", "node.route"))
m.Append("user.route", m.Conf("runtime", "user.route"))
m.Append("user.name", m.Conf("runtime", "user.name"))
m.Echo(name).Back(m)
default:
// 拆分路由
if arg[0] == m.Conf("runtime", "node.name") || arg[0] == m.Conf("runtime", "node.route") {
arg[0] = ""
}
arg[0] = strings.TrimPrefix(arg[0], m.Conf("runtime", "node.route")+".")
arg[0] = strings.TrimPrefix(arg[0], m.Conf("runtime", "node.name")+".")
route, names, arg := arg[0], strings.SplitN(arg[0], ".", 2), arg[1:]
if len(names) > 1 && names[0] == "" && names[1] != "" {
names[0], names[1] = names[1], names[0]
}
// 同步异步
sync := !m.Options("remote_code")
sync := true
switch arg[0] {
case "async", "sync":
sync, arg = arg[0] == "sync", arg[1:]
}
// 路由转发
// 局域路由
if arg[0] == m.Conf("runtime", "node.name") || arg[0] == m.Conf("runtime", "node.route") {
arg[0] = ""
}
arg[0] = strings.TrimPrefix(arg[0], m.Conf("runtime", "node.route")+".")
arg[0] = strings.TrimPrefix(arg[0], m.Conf("runtime", "node.name")+".")
// 拆分路由
route, names, arg := arg[0], strings.SplitN(arg[0], ".", 2), arg[1:]
if len(names) > 1 && names[0] == "" && names[1] != "" {
names[0], names[1] = names[1], names[0]
}
if rest := kit.Select("", names, 1); names[0] != "" {
// 数字签名
if !m.Options("remote_code") && arg[0] != "check" {
// 数据哈希
hash, meta := kit.Hash("rand",
m.Option("text.time", m.Time("stamp")),
m.Option("text.cmd", strings.Join(arg, " ")),
@ -245,369 +433,55 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
m.Option("user.route", kit.Select(m.Conf("runtime", "node.route"), m.Conf("runtime", "user.route"))),
m.Option("user.name", m.Option("username")),
m.Option("work.name", m.Conf("runtime", "work.name")),
m.Option("work.route", m.Conf("runtime", "work.route")),
)
m.Option("text.rand", meta[0])
// 设备签名
m.Option("node.sign", m.Cmdx("aaa.rsa", "sign", m.Conf("runtime", "node.key"), m.Option("text.hash", hash)))
// 用户签名
if m.Options("user.sign") && m.Confs("runtime", "user.key") {
m.Option("user.sign", m.Cmdx("aaa.rsa", "sign", m.Conf("runtime", "user.key"), m.Option("text.hash", hash)))
}
}
// 查找路由
ps := []string{}
if names[0] == "%" || names[0] == "*" { // 广播命令
m.Confm("node", names[0], func(name string, node map[string]interface{}) {
if kit.Format(node["type"]) != "master" {
m.Find(kit.Format(node["module"]), true).Copy(m, "option").CallBack(sync, func(sub *ctx.Message) *ctx.Message {
return m.CopyFuck(sub, "append").CopyFuck(sub, "result").Echo("\n\n")
}, "send", rest, arg)
ps = append(ps, kit.Format(node["module"]))
}
})
} else if m.Confm("node", names[0], func(node map[string]interface{}) { // 单播命令
m.Find(kit.Format(node["module"]), true).Copy(m, "option").CallBack(sync, func(sub *ctx.Message) *ctx.Message {
return m.Copy(sub, "append").Copy(sub, "result")
}, "send", rest, arg)
ps = append(ps, kit.Format(node["module"]))
}) == nil { // 上报命令
m.Find(m.Cap("stream"), true).Copy(m, "option").CallBack(sync, func(sub *ctx.Message) *ctx.Message {
return m.Copy(sub, "append").Copy(sub, "result")
}, "send", strings.Join(names, "."), arg)
}) == nil && m.Caps("stream") { // 上报命令
rest = strings.Join(names, ".")
ps = append(ps, m.Cap("stream"))
}
if len(ps) == 0 {
m.Echo("error: not found %s", names[0]).Back(m)
return
}
// 路由转发
for _, p := range ps {
m.Find(p, true).Copy(m, "option").CallBack(sync, func(sub *ctx.Message) *ctx.Message {
return m.CopyFuck(sub, "append").CopyFuck(sub, "result").Echo("\n")
}, "send", rest, arg)
}
return
}
// 返回结果
// 远程回调
defer func() { m.Back(m) }()
// 查看证书
switch arg[0] {
case "check":
switch arg[1] {
case "node": // 设备证书
m.Echo(m.Conf("runtime", "node.cert"))
case "user":
if len(arg) == 2 { // 用户证书
m.Append("user.cert", m.Conf("runtime", "user.cert"))
m.Append("user.name", m.Conf("runtime", "user.name"))
m.Append("user.route", kit.Select(m.Conf("runtime", "node.route"), m.Conf("runtime", "user.route")))
} else { // 代理验证
if arg[2] == m.Conf("runtime", "node.route") || m.Cmds("aaa.auth", "proxy", arg[2], "session") {
m.Echo(m.Cmdx("aaa.rsa", "sign", m.Conf("runtime", "user.key"), arg[3]))
}
}
case "work":
if len(arg) == 2 { // 查看
if cert := m.Confm("cert", arg[2]); cert != nil {
m.Echo("%s", cert["user"])
return
}
} else { // 申请
if cert := m.Confm("cert", arg[4]); cert != nil {
if cert["user"] != arg[2] {
return
}
m.Echo(arg[4])
return
}
m.Conf("cert", arg[4], map[string]interface{}{
"create_time": m.Time(),
"user": arg[2],
})
m.Echo(arg[4])
}
}
return
}
if m.Options("remote_code") {
// 检查数据
hash, _ := kit.Hash(
m.Option("text.rand"),
m.Option("text.time"),
m.Option("text.cmd"),
m.Option("text.route"),
m.Option("node.route"),
m.Option("user.route"),
m.Option("user.name"),
m.Option("work.name"),
)
if m.Option("text.hash") != hash {
m.Log("warning", "text error")
return
}
// 设备证书
if m.Option("node.cert", m.Cmd("aaa.auth", "nodes", m.Option("node.route"), "cert").Append("meta")); !m.Options("node.cert") {
m.Option("node.cert", m.Spawn().Cmdx("ssh.remote", m.Option("node.route"), "sync", "check", "node"))
m.Cmd("aaa.auth", "nodes", m.Option("node.route"), "cert", m.Option("node.cert"))
}
// 设备验签
if !m.Cmds("aaa.rsa", "verify", m.Option("node.cert"), m.Option("node.sign"), m.Option("text.hash", hash)) {
m.Cmd("aaa.auth", "nodes", m.Option("node.route"), "cert", m.Option("node.cert"))
m.Log("warning", "node error")
m.Cmd("aaa.auth", "nodes", m.Option("node.route"), "node", "delete")
return
}
} else {
m.Option("user.name", m.Conf("runtime", "user.name"))
}
switch arg[0] {
case "share": // 设备权限
// 默认用户
if !m.Confs("runtime", "user.route") {
user := m.Spawn().Cmd("ssh.remote", m.Option("user.route"), "sync", "check", "user")
m.Conf("runtime", "user.route", user.Append("user.route"))
m.Conf("runtime", "user.name", user.Append("user.name"))
m.Conf("runtime", "user.cert", user.Append("user.cert"))
m.Cmd("aaa.role", "root", "user", user.Append("user.name"))
m.Cmd("aaa.auth", "username", user.Append("user.name"), "cert", user.Append("user.cert"))
return
}
// 共享用户
if !m.Options("remote_code") || (m.Options("user.sign") && m.Conf("runtime", "user.name") == m.Option("user.name")) {
if !m.Options("remote_code") || m.Cmds("aaa.rsa", "verify", m.Conf("runtime", "user.cert"), m.Option("user.sign"), m.Option("text.hash")) {
for _, v := range arg[2:] {
user := m.Spawn().Cmd("ssh.remote", v, "sync", "check", "user")
m.Cmd("aaa.user", arg[1], "user", user.Append("user.name"))
m.Cmd("aaa.auth", "username", user.Append("user.name"), "cert", user.Append("user.cert"))
}
return
}
}
// 申请权限
m.Spawn().Set("option", "remote_code", "").Cmds("ssh.remote", m.Conf("runtime", "user.route"), "sync", "apply", arg[1:])
return
case "apply": // 权限申请
for _, v := range arg[2:] {
user := m.Spawn().Cmd("ssh.remote", v, "sync", "check", "user")
m.Cmd("aaa.auth", "username", user.Append("user.name"), "cert", user.Append("user.cert"))
sess := m.Cmd("aaa.auth", "username", user.Append("user.name"), "session", "apply").Append("key")
if sess == "" {
sess = m.Cmdx("aaa.sess", "apply", "username", arg[2])
}
m.Cmd("aaa.auth", sess, "apply", m.Option("node.route"))
m.Cmd("aaa.auth", sess, "share", user.Append("user.route"))
}
return
case "login": // 用户代理
if !m.Cmds("aaa.auth", "proxy", m.Option("node.route")) {
return
}
sess := m.Cmd("aaa.auth", "username", m.Option("user.name"), "session", "proxy").Append("key")
if sess == "" {
sess = m.Cmdx("aaa.sess", "proxy", "username", m.Option("user.name"))
}
m.Cmd("aaa.auth", sess, "proxy", m.Option("node.route"))
m.Echo(sess)
return
}
if m.Options("remote_code") {
m.Log("info", "username %s", m.Option("work.name"))
if m.Option("username", m.Option("work.name")); m.Confs("trust", m.Option("node.route")) {
m.Log("info", "skip verify user of node %s", m.Option("node.route"))
} else if m.Confs("trust", "up") && strings.HasPrefix(m.Conf("runtime", "node.route"), m.Option("node.route")) {
m.Log("info", "skip verify user of up node %s", m.Option("node.route"))
} else {
// 用户签名
hash, _ := kit.Hash("rand", m.Option("text.time", m.Time("stamp")), m.Option("node.route"))
if m.Option("user.cert", m.Cmd("aaa.auth", "username", m.Option("username"), "cert").Append("meta")); !m.Options("user.cert") {
m.Option("user.cert", m.Cmd("ssh.remote", m.Option("user.route"), "sync", "check", "user").Append("user.cert"))
m.Log("fuck", "user.eert %v", m.Option("user.cert"))
m.Log("fuck", "wat %v", m.Cmd("aaa.auth", "username", m.Option("username"), "cert", m.Option("user.cert")))
}
m.Option("user.sign", m.Spawn().Cmdx("ssh.remote", m.Option("user.route"), "sync", "check", "user", m.Option("node.route"), hash))
// 代理验签
if !m.Options("user.cert") || !m.Options("user.sign") || !m.Cmds("aaa.rsa", "verify", m.Option("user.cert"), m.Option("user.sign"), hash) {
m.Log("warn", "user error")
m.Echo("no right of %s", m.Option("text.route"))
return
}
}
// 创建会话
m.Option("sessid", m.Cmdx("aaa.user", "session", "select"))
// 创建空间
m.Option("bench", m.Cmdx("aaa.sess", "bench", "select"))
// 权限检查
if !m.Cmds("aaa.work", "right", "remote", arg[0]) {
m.Echo("no right %s %s", "remote", arg[0])
return
}
}
// 执行命令
m.Cmdm(arg)
}
return
}},
if arg[0] == "check" { // 数字验签
m.Cmd(arg)
"share": &ctx.Command{Name: "share [serve.route] role client.route...", Help: "共享权限", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmd("aaa.auth", "apply").Table(func(node map[string]string) {
m.Cmd("aaa.auth", node["key"], "session", "apply").Table(func(sess map[string]string) {
m.Cmd("aaa.auth", sess["key"], "username").Table(func(user map[string]string) {
m.Add("append", "time", sess["create_time"])
m.Add("append", "user", user["meta"])
m.Add("append", "node", node["meta"])
})
})
})
m.Table()
return
}
} else if m.Options("remote_code") { // 远程调用
m.Cmd("action", arg)
// 本地用户
if len(arg) == 2 {
m.Option("user.route", arg[1])
m.Cmd("ssh.remote", "", "share", arg[1:])
return
}
// 远程用户
m.Option("user.sign", "yes")
m.Cmd("ssh.remote", arg[0], "sync", "share", arg[1:])
return
}},
"proxy": &ctx.Command{Name: "proxy [proxy.route]", Help: "代理节点", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmdy("aaa.auth", "proxy")
return
}
if !m.Cmds("aaa.auth", "proxy", arg[0], "session") {
m.Cmdy("aaa.sess", "proxy", "proxy", arg[0])
}
return
}},
"login": &ctx.Command{Name: "login client.route", Help: "用户节点", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmd("aaa.auth", "login")
return
}
if !m.Cmds("ssh.remote", arg[0], "login") {
m.Echo("error: ").Echo("login failure")
return
}
sess := m.Cmd("aaa.auth", "username", m.Option("username"), "session", "login").Append("key")
if sess == "" {
sess = m.Cmdx("aaa.sess", "login", "username", m.Option("username"))
}
m.Cmd("aaa.auth", sess, "login", arg[0])
m.Echo(sess)
return
}},
"sh": &ctx.Command{Name: "sh [[node] name] cmd...", Help: "发送命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmdy("ssh.remote")
return
}
if arg[0] == "sub" {
m.Confm("node", func(name string, node map[string]interface{}) {
if node["type"] == "master" {
return
}
msg := m.Cmd("ssh.remote", name, arg[1:])
if len(msg.Meta["append"]) > 0 && !msg.Has("node") {
line := len(msg.Meta[msg.Meta["append"][0]])
for i := 0; i < line; i++ {
msg.Add("append", "node", m.Conf("runtime", "node.route")+"."+name)
}
msg.Set("result").Table()
}
m.CopyFuck(msg, "append")
m.CopyFuck(msg, "result")
return
})
return
}
if arg[0] == "node" {
m.Conf("current", arg[1])
arg = arg[2:]
} else if m.Confm("node", arg[0]) != nil {
m.Conf("current", arg[0])
arg = arg[1:]
} else {
m.Confm("node", func(name string, node map[string]interface{}) bool {
if strings.Contains(name, arg[0]) {
m.Conf("current", name)
arg = arg[1:]
return true
}
return false
})
}
msg := m.Cmd("ssh.remote", m.Conf("current"), arg)
m.Copy(msg, "append")
m.Copy(msg, "result")
return
}},
"cp": &ctx.Command{Name: "cp [[node] name] filename", Help: "发送文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Echo(m.Conf("current"))
return
}
if arg[0] == "node" {
m.Conf("current", arg[1])
arg = arg[2:]
} else if m.Confm("node", arg[0]) != nil {
m.Conf("current", arg[0])
arg = arg[1:]
}
if arg[0] == "save" {
buf, e := base64.StdEncoding.DecodeString(m.Option("filebuf"))
m.Assert(e)
f, e := os.OpenFile(path.Join("tmp", m.Option("filename")), os.O_RDWR|os.O_CREATE, 0666)
f.WriteAt(buf, int64(m.Optioni("filepos")))
return e
}
p := m.Cmdx("nfs.path", arg[0])
f, e := os.Open(p)
m.Assert(e)
s, e := f.Stat()
m.Assert(e)
buf := make([]byte, 1024)
for i := int64(0); i < s.Size(); i += 1024 {
n, _ := f.ReadAt(buf, i)
if n == 0 {
break
} else { // 本地调用
m.Cmdm(arg)
}
buf = buf[:n]
msg := m.Spawn()
msg.Option("filename", arg[0])
msg.Option("filesize", s.Size())
msg.Option("filepos", i)
msg.Option("filebuf", base64.StdEncoding.EncodeToString(buf))
msg.Cmd("remote", m.Conf("current"), "cp", "save", arg[0])
}
return
}},

View File

@ -1,29 +0,0 @@
package tcp
import (
"context"
"flag"
"testing"
"time"
)
func TestOpen(t *testing.T) {
flag.Parse()
args := flag.Args()
if len(args) < 1 {
t.Fatal("usages: -args address")
}
address := ":9393"
address = args[0]
//mysql -u root -p;
//create database book;
//grant all on book.* to user identified by 'word'
ctx.Start()
m := ctx.Pulse.Spawn(Index)
m.Meta = nil
Index.Cmd(m, "listen", address)
}

View File

@ -643,6 +643,10 @@ func Hash(arg ...interface{}) (string, []string) {
h := md5.Sum([]byte(strings.Join(args, "")))
return hex.EncodeToString(h[:]), args
}
func Hashs(arg ...interface{}) string {
h, _ := Hash(arg...)
return h
}
func Block(root interface{}, args ...interface{}) interface{} {

View File

@ -373,6 +373,12 @@ chat模块提供了信息管理。
### 通信框架
#### 节点路由
#### 节点认证
- text.hash
- node.sign
- user.sign
- work.name
#### 节点服务
### 存储引擎
#### 配置