From f3b78ae6c54f9e4b84ae268485f6c3582a51bedb Mon Sep 17 00:00:00 2001 From: shaoying Date: Sun, 12 Jan 2020 15:35:12 +0800 Subject: [PATCH] opt miss --- README.md | 17 +++++++- base.go | 8 ++-- base/aaa/aaa.go | 10 +++++ base/ctx/ctx.go | 9 +++- base/mdb/mdb.go | 14 +++++-- base/ssh/ssh.go | 13 +++++- base/web/web.go | 23 ++++++++-- core/chat/chat.go | 14 +++++++ core/code/code.go | 8 ++-- core/mall/mall.go | 13 +++--- core/team/team.go | 34 ++++++++++++--- demo/Makefile | 2 - demo/build.sh | 62 --------------------------- demo/go.mod | 13 ------ demo/main.go | 12 ------ demo/usr/local/wiki/miss.md | 53 ----------------------- misc/docker/docker.go | 58 ++++++++++++++++++------- misc/git/git.go | 82 +++++++++++++++++++++++++++++++++++- misc/shy.go | 1 + misc/tmux/tmux.go | 5 ++- miss/Makefile | 3 ++ miss/{ice.md => README.md} | 84 ++++++++++++++++++------------------- miss/go.mod | 10 ----- miss/main.go | 14 ------- build.sh => template.sh | 45 ++++++++++++++------ type.go | 43 ++++++++++++++++++- 26 files changed, 382 insertions(+), 268 deletions(-) delete mode 100644 demo/Makefile delete mode 100755 demo/build.sh delete mode 100644 demo/go.mod delete mode 100644 demo/main.go delete mode 100644 demo/usr/local/wiki/miss.md create mode 100644 miss/Makefile rename miss/{ice.md => README.md} (51%) delete mode 100644 miss/go.mod delete mode 100644 miss/main.go rename build.sh => template.sh (61%) diff --git a/README.md b/README.md index 7af15020..fadf1f43 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,24 @@ icebergs是一个后端框架,通过模块化、集群化实现资源的无限的扩展与自由的组合。 +使用icebergs可以将各种模块或项目集成到一起,快速开发出集中式的服务器。 + +使用icebergs可以将各种设备自由的组合在一起,快速搭建起分布式的服务器。 + +所以通过icebergs开发出来的模块,无需任何多余代码,就可以独立运行,可以成为系统命令,可以远程调用,可以成为前端插件,可以成为小程序页面。 + +## 项目开发 +开发环境,需要安装git,golang + 一键创建项目 ``` -mkdir miss; cd miss && curl -s https://shylinux.com/publish/build.sh | sh +mkdir miss; cd miss && curl -s https://shylinux.com/publish/template.sh | sh +``` + +运行环境,如需前端页面访问服务,需要安装git +一键复制项目 +``` +export ctx_dev=http://127.0.0.1:9020 && curl -s $ctx_dev/publish/ice.sh ``` ## 1 原型 type.go diff --git a/base.go b/base.go index 9163fb56..5887c6f0 100644 --- a/base.go +++ b/base.go @@ -88,15 +88,17 @@ var Index = &Context{Name: "ice", Help: "冰山模块", }}, "init": {Name: "init", Help: "hello", Hand: func(m *Message, c *Context, cmd string, arg ...string) { m.root.Cost("_init") - m.Start("log", arg...) - m.Start("gdb", arg...) - m.Start("ssh", arg...) + m.Start("log") + m.Start("gdb") + m.Start("ssh") + m.Cmd("ssh.scan", "init.shy", "启动配置", "etc/init.shy") m.Cmd(arg) }}, "help": {Name: "help", Help: "帮助", Hand: func(m *Message, c *Context, cmd string, arg ...string) { m.Echo(strings.Join(kit.Simple(m.Confv("help", "index")), "\n")) }}, "exit": {Name: "exit", Help: "hello", Hand: func(m *Message, c *Context, cmd string, arg ...string) { + m.Cmd("ssh.scan", "exit.shy", "退出配置", "etc/exit.shy") f := m.root.target.server.(*Frame) f.code = kit.Int(kit.Select("0", arg, 0)) m.root.Cmd(ICE_EXIT) diff --git a/base/aaa/aaa.go b/base/aaa/aaa.go index 4d938456..d55610ea 100644 --- a/base/aaa/aaa.go +++ b/base/aaa/aaa.go @@ -87,6 +87,16 @@ var Index = &ice.Context{Name: "aaa", Help: "认证模块", }}, ice.AAA_USER: {Name: "user", Help: "用户", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { switch arg[0] { + case "first": + if m.Richs(ice.AAA_USER, nil, "%", nil) == nil { + m.Rich(ice.AAA_USER, nil, kit.Dict("username", arg[1], + "usernode", m.Conf(ice.CLI_RUNTIME, "boot.hostname"), + )) + user := m.Richs(ice.AAA_USER, nil, arg[1], nil) + m.Info("create user: %s %s", arg[1], kit.Format(user)) + m.Event(ice.USER_CREATE, arg[1]) + } + case "login": // 用户认证 user := m.Richs(ice.AAA_USER, nil, arg[1], nil) diff --git a/base/ctx/ctx.go b/base/ctx/ctx.go index c791ebc8..4f4d69d9 100644 --- a/base/ctx/ctx.go +++ b/base/ctx/ctx.go @@ -116,7 +116,14 @@ var Index = &ice.Context{Name: "ctx", Help: "配置模块", } } default: - m.Echo(kit.Formats(m.Confv(arg[0]))) + if len(arg) > 2 { + m.Conf(arg[0], arg[1], arg[2]) + } + if len(arg) > 1 { + m.Echo(m.Conf(arg[0], arg[1])) + } else { + m.Echo(kit.Formats(m.Confv(arg[0]))) + } } }}, }, diff --git a/base/mdb/mdb.go b/base/mdb/mdb.go index 5871e595..7310a992 100644 --- a/base/mdb/mdb.go +++ b/base/mdb/mdb.go @@ -7,6 +7,7 @@ import ( "bytes" "encoding/csv" "encoding/json" + "os" "sort" "strings" ) @@ -54,6 +55,11 @@ var Index = &ice.Context{Name: "mdb", Help: "数据模块", case kit.MDB_LIST: buf := bytes.NewBufferString(msg.Append("text")) r := csv.NewReader(buf) + if msg.Append("file") != "" { + if f, e := os.Open(msg.Append("file")); m.Assert(e) { + r = csv.NewReader(f) + } + } head, _ := r.Read() for { @@ -79,7 +85,7 @@ var Index = &ice.Context{Name: "mdb", Help: "数据模块", } } }}, - ice.MDB_EXPORT: {Name: "export", Help: "导出数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + ice.MDB_EXPORT: {Name: "export conf key list|hash", Help: "导出数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { name := kit.Select(kit.Select(arg[0], arg[0]+":"+arg[1], arg[1] != ""), arg, 3) switch arg[2] { @@ -89,7 +95,7 @@ var Index = &ice.Context{Name: "mdb", Help: "数据模块", buf := bytes.NewBuffer(make([]byte, 0, 1024)) w := csv.NewWriter(buf) head := []string{} - m.Confm(arg[0], arg[1], func(index int, value map[string]interface{}) { + m.Grows(arg[0], arg[1], "", "", func(index int, value map[string]interface{}) { if index == 0 { // 输出表头 for k := range value { @@ -108,10 +114,10 @@ var Index = &ice.Context{Name: "mdb", Help: "数据模块", }) w.Flush() - m.Cmd(ice.WEB_STORY, "add", "csv", name, string(buf.Bytes())) + m.Cmdy(ice.WEB_STORY, "add", "csv", name, string(buf.Bytes())) case kit.MDB_HASH: - m.Cmd(ice.WEB_STORY, "add", "json", name, kit.Formats(m.Confv(arg[0], arg[1]))) + m.Cmdy(ice.WEB_STORY, "add", "json", name, kit.Formats(m.Confv(arg[0], arg[1]))) } }}, }, diff --git a/base/ssh/ssh.go b/base/ssh/ssh.go index eebac831..57cd30e8 100644 --- a/base/ssh/ssh.go +++ b/base/ssh/ssh.go @@ -40,10 +40,18 @@ func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { } func (f *Frame) Start(m *ice.Message, arg ...string) bool { switch kit.Select("stdio", arg, 0) { - default: + case "stdio": f.in = os.Stdin f.out = os.Stdout m.Cap(ice.CTX_STREAM, "stdio") + default: + if n, e := os.Open(arg[0]); m.Warn(e != nil, "%s", e) { + return true + } else { + f.in = n + f.out = os.Stderr + m.Cap(ice.CTX_STREAM, arg[0]) + } } f.count = 0 @@ -105,6 +113,9 @@ var Index = &ice.Context{Name: "ssh", Help: "终端模块", m.Done() } }}, + "scan": {Name: "scan", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Starts(arg[0], arg[1], arg[2:]...) + }}, }, } diff --git a/base/web/web.go b/base/web/web.go index 4f6330d4..24eb82d4 100644 --- a/base/web/web.go +++ b/base/web/web.go @@ -828,7 +828,8 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", m.Sort("status") }}, - ice.WEB_FAVOR: {Name: "favor", Help: "收藏夹", Meta: kit.Dict("remote", "you", "exports", []string{"hot", "favor"}, "detail", []string{"执行", "编辑", "收录", "下载"}), List: kit.List( + ice.WEB_FAVOR: {Name: "favor", Help: "收藏夹", Meta: kit.Dict("remote", "you", "exports", []string{"hot", "favor"}, + "detail", []string{"执行", "编辑", "收录", "导出", "下载"}), List: kit.List( kit.MDB_INPUT, "text", "name", "hot", "action", "auto", kit.MDB_INPUT, "text", "name", "id", "action", "auto", kit.MDB_INPUT, "button", "value", "查看", "action", "auto", @@ -858,6 +859,8 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", case "执行": m.Event(ice.FAVOR_START, m.Option("you"), kit.Select(m.Option("hot"), arg[3], arg[2] == "favor")) arg = arg[:0] + case "导出": + arg = []string{"export", m.Option("hot")} } } @@ -876,8 +879,9 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", if len(arg) == 1 { m.Cmdy(ice.MDB_EXPORT, ice.WEB_FAVOR, kit.MDB_HASH, kit.MDB_HASH, "favor.json") } else { + m.Option("cache.limit", "1000") m.Richs(ice.WEB_FAVOR, nil, arg[1], func(key string, value map[string]interface{}) { - m.Cmdy(ice.MDB_EXPORT, ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, key, kit.MDB_LIST), kit.MDB_LIST, arg[1]+".csv") + m.Cmdy(ice.MDB_EXPORT, ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, key), kit.MDB_LIST, arg[1]+".csv") }) } return @@ -1028,7 +1032,8 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", m.Push("data", h) } }}, - ice.WEB_STORY: {Name: "story", Help: "故事会", Meta: kit.Dict("remote", "you", "exports", []string{"top", "story"}, "detail", []string{"归档", "共享", "下载"}), List: kit.List( + ice.WEB_STORY: {Name: "story", Help: "故事会", Meta: kit.Dict("remote", "you", "exports", []string{"top", "story"}, + "detail", []string{"归档", "共享", "导出", "下载"}), List: kit.List( kit.MDB_INPUT, "text", "name", "top", "action", "auto", kit.MDB_INPUT, "text", "name", "list", "action", "auto", kit.MDB_INPUT, "button", "value", "查看", "action", "auto", @@ -1048,6 +1053,11 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", msg.Append("story"), arg[3], "pod", pod, "data", arg[3]) return } + case "导出": + switch arg[2] { + case "story", "list": + arg = []string{ice.STORY_WATCH, arg[3], m.Option("story")} + } } } @@ -1177,6 +1187,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", case ice.STORY_WATCH: msg := m.Cmd(ice.WEB_STORY, "index", arg[1]) name := kit.Select(arg[1], arg, 2) + os.Remove(kit.Keys(name, "bak")) os.Rename(name, kit.Keys(name, "bak")) if msg.Append("file") != "" { os.Link(msg.Append("file"), name) @@ -1211,7 +1222,11 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", } // 保存数据 - if m.Richs(ice.WEB_CACHE, nil, kit.Select("", arg, 3), nil) == nil { + if m.Richs(ice.WEB_CACHE, nil, kit.Select("", arg, 3), func(key string, value map[string]interface{}) { + if len(arg) > 3 { + arg[3] = key + } + }) == nil { m.Cmdy(ice.WEB_CACHE, arg) arg = []string{arg[0], m.Append("type"), m.Append("name"), m.Append("data")} } diff --git a/core/chat/chat.go b/core/chat/chat.go index f8847ebe..56223a9b 100644 --- a/core/chat/chat.go +++ b/core/chat/chat.go @@ -35,6 +35,17 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", m.Cmd(ice.WEB_FAVOR, "river.root", "field", "favor") m.Cmd(ice.WEB_FAVOR, "river.root", "field", "story") m.Cmd(ice.WEB_FAVOR, "river.root", "field", "share") + + m.Cmd(ice.WEB_FAVOR, "river.root", "storm", "misc") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "buffer", "cli.tmux") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "session", "cli.tmux") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "image", "cli.docker") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "container", "cli.docker") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "command", "cli.docker") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "repos", "cli.git") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "total", "cli.git") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "branch", "cli.git") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "status", "cli.git") } // 用户权限 @@ -46,6 +57,8 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", m.Cmd(ice.AAA_ROLE, "white", ice.ROLE_VOID, "enable", "/action") m.Cmd(ice.AAA_ROLE, "white", ice.ROLE_VOID, "enable", "dream") m.Cmd(ice.AAA_ROLE, "black", ice.ROLE_VOID, "enable", "dream.停止") + + m.Cmd(ice.AAA_USER, "first", m.Conf(ice.CLI_RUNTIME, "boot.username")) } }}, @@ -95,6 +108,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", m.Option(ice.MSG_USERROLE, m.Cmdx(ice.AAA_ROLE, "check", value["username"])) storm, river := "", m.Option(ice.MSG_RIVER, m.Cmdx("/ocean", "spawn", kit.Select(arg[1], value["nickname"])+"@"+m.Conf(ice.CLI_RUNTIME, "boot.hostname"), m.Option(ice.MSG_USERNAME))) m.Richs(ice.WEB_FAVOR, nil, kit.Keys("river", m.Option(ice.MSG_USERROLE)), func(key string, value map[string]interface{}) { + m.Option("cache.limit", "100") m.Grows(ice.WEB_FAVOR, kit.Keys("hash", key), "", "", func(index int, value map[string]interface{}) { switch value["type"] { case "storm": diff --git a/core/code/code.go b/core/code/code.go index 53b658b3..864af01b 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -37,8 +37,8 @@ var Index = &ice.Context{Name: "code", Help: "编程中心", kit.MDB_HASH, kit.Dict( "system", kit.Dict( kit.MDB_LIST, kit.List( - kit.MDB_INPUT, "bin", "file", "ice.sh", "path", "ice.sh", - kit.MDB_INPUT, "bin", "file", "ice.bin", "path", "ice.bin", + kit.MDB_INPUT, "bin", "file", "ice.sh", "path", "bin/ice.sh", + kit.MDB_INPUT, "bin", "file", "ice.bin", "path", "bin/ice.bin", ), ), ), @@ -48,7 +48,7 @@ var Index = &ice.Context{Name: "code", Help: "编程中心", ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Cmd(ice.CTX_CONFIG, "load", "code.json") m.Watch(ice.SYSTEM_INIT, "compile", "linux") - m.Watch(ice.SYSTEM_INIT, "publish", "ice.sh") + m.Watch(ice.SYSTEM_INIT, "publish", "bin/ice.sh") }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Cmd(ice.CTX_CONFIG, "save", "code.json", "web.code.login") @@ -62,7 +62,7 @@ var Index = &ice.Context{Name: "code", Help: "编程中心", } // 编译目标 - main := kit.Select("main.go", arg, 2) + main := kit.Select("src/main.go", arg, 2) arch := kit.Select(m.Conf(ice.CLI_RUNTIME, "host.GOARCH"), arg, 1) goos := kit.Select(m.Conf(ice.CLI_RUNTIME, "host.GOOS"), arg, 0) file := path.Join(m.Conf("compile", "meta.path"), kit.Keys("ice", goos, arch)) diff --git a/core/mall/mall.go b/core/mall/mall.go index fe4fdf31..ca3d5897 100644 --- a/core/mall/mall.go +++ b/core/mall/mall.go @@ -22,12 +22,6 @@ var Index = &ice.Context{Name: "mall", Help: "贸易中心", if m.Richs(ice.WEB_SPIDE, nil, "12306", nil) == nil { m.Cmd(ice.WEB_SPIDE, "add", "12306", "https://kyfw.12306.cn") } - if !m.Confs("railway", "meta.site") { - list := strings.Split(strings.TrimPrefix(m.Cmdx(ice.WEB_SPIDE, "12306", "raw", "GET", "/otn/resources/js/framework/station_name.js?station_version=1.9090"), "var statuion_names ='"), "|") - for i := 0; i < len(list)-5; i += 5 { - m.Conf("railway", kit.Keys("meta.site", list[i+1]), list[i+2]) - } - } }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Cmd(ice.CTX_CONFIG, "save", "mall.json", "web.mall.railway") @@ -57,6 +51,13 @@ var Index = &ice.Context{Name: "mall", Help: "贸易中心", kit.MDB_INPUT, "text", "name", "to", "value", "曲阜", kit.MDB_INPUT, "button", "name", "查询", ), Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + if !m.Confs("railway", "meta.site") { + list := strings.Split(strings.TrimPrefix(m.Cmdx(ice.WEB_SPIDE, "12306", "raw", "GET", "/otn/resources/js/framework/station_name.js?station_version=1.9090"), "var statuion_names ='"), "|") + for i := 0; i < len(list)-5; i += 5 { + m.Conf("railway", kit.Keys("meta.site", list[i+1]), list[i+2]) + } + } + date := time.Now().Add(time.Hour * 24).Format("2006-01-02") if len(arg) > 0 { date, arg = arg[0], arg[1:] diff --git a/core/team/team.go b/core/team/team.go index 5ca0d0ff..b3452baa 100644 --- a/core/team/team.go +++ b/core/team/team.go @@ -32,8 +32,10 @@ var Index = &ice.Context{Name: "team", Help: "团队中心", m.Cmd(ice.CTX_CONFIG, "save", "team.json", "web.team.miss") }}, - ice.APP_MISS: {Name: "miss", Help: "任务", Meta: kit.Dict( - "remote", "you", + ice.APP_MISS: {Name: "miss", Help: "任务", Meta: kit.Dict("remote", "you"), List: kit.List( + kit.MDB_INPUT, "text", "name", "id", + kit.MDB_INPUT, "button", "name", "执行", + kit.MDB_INPUT, "button", "name", "返回", "cb", "Last", ), Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { hot := kit.Select(ice.FAVOR_MISS, m.Option("hot")) if len(arg) > 1 { @@ -59,11 +61,20 @@ var Index = &ice.Context{Name: "team", Help: "团队中心", }) return } + if len(arg) == 1 { + // 任务详情 + m.Richs(ice.WEB_FAVOR, nil, hot, func(key string, value map[string]interface{}) { + m.Grows(ice.WEB_FAVOR, kit.Keys("hash", key), "id", arg[0], func(index int, value map[string]interface{}) { + m.Push("detail", value) + }) + }) + return + } // 添加任务 m.Cmdy(ice.WEB_FAVOR, hot, ice.TYPE_DRIVE, arg[0], arg[1], "begin_time", m.Time(), "close_time", m.Time(), - "status", kit.Select("准备中", arg, 3), + "status", kit.Select("准备中", arg, 2), ) }}, "date": {Name: "date", Help: "日历", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { @@ -109,11 +120,20 @@ var Index = &ice.Context{Name: "team", Help: "团队中心", } }}, "stat": {Name: "stat", Help: "统计", Meta: kit.Dict( + "display", "demo.wasm", // "display", "github.com/shylinux/icebergs/core/team/stat", ), Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - m.Push("weekly", 10) - m.Push("month", 100) - m.Push("year", 1000) + hot := kit.Select(ice.FAVOR_MISS, m.Option("hot")) + stat := map[string]int{} + m.Option("cache.limit", "1000") + m.Richs(ice.WEB_FAVOR, nil, hot, func(key string, value map[string]interface{}) { + m.Grows(ice.WEB_FAVOR, kit.Keys("hash", key), "", "", func(index int, value map[string]interface{}) { + stat[kit.Format(kit.Value(value, "extra.status"))] += 1 + }) + }) + for k, v := range stat { + m.Push(k, v) + } }}, "progress": {Name: "progress", Help: "进度", Meta: kit.Dict( "remote", "you", @@ -135,11 +155,13 @@ var Index = &ice.Context{Name: "team", Help: "团队中心", } if next := m.Conf(ice.APP_MISS, kit.Keys("meta.fsm", value["status"], "next")); next != "" { value["status"] = next + kit.Value(value, "change.-2", kit.Dict("time", m.Time(), "status", next)) } case "回退": if prev := m.Conf(ice.APP_MISS, kit.Keys("meta.fsm", value["status"], "prev")); prev != "" { value["status"] = prev + kit.Value(value, "change.-2", kit.Dict("time", m.Time(), "status", prev)) } case "取消": diff --git a/demo/Makefile b/demo/Makefile deleted file mode 100644 index 0c095b2e..00000000 --- a/demo/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -all: - go build -o bin/ice.bin main.go && chmod u+x bin/ice.bin && ./ice.sh restart diff --git a/demo/build.sh b/demo/build.sh deleted file mode 100755 index 83eb775b..00000000 --- a/demo/build.sh +++ /dev/null @@ -1,62 +0,0 @@ -#! /bin/sh - -ice_sh=${ice_sh:="ice.sh"} - -prepare() { - [ -f main.go ] || cat >> main.go <> ${ice_sh} <boot.log && echo -e "\n\nrestarting..." || break - done -} -restart() { - kill -2 \`cat var/run/shy.pid\` -} -shutdown() { - kill -3 \`cat var/run/shy.pid\` -} - -cmd=\$1 && shift -[ -z "\$cmd" ] && cmd=start -\$cmd \$* -END - chmod u+x ${ice_sh} - - [ -f Makefile ] || cat >> Makefile < ../ - github.com/shylinux/toolkits => ../../toolkits -) diff --git a/demo/main.go b/demo/main.go deleted file mode 100644 index b9de0a2d..00000000 --- a/demo/main.go +++ /dev/null @@ -1,12 +0,0 @@ -package main - -import ( - "github.com/shylinux/icebergs" - _ "github.com/shylinux/icebergs/base" - _ "github.com/shylinux/icebergs/core" - _ "github.com/shylinux/icebergs/misc" -) - -func main() { - println(ice.Run()) -} diff --git a/demo/usr/local/wiki/miss.md b/demo/usr/local/wiki/miss.md deleted file mode 100644 index 37f8c91b..00000000 --- a/demo/usr/local/wiki/miss.md +++ /dev/null @@ -1,53 +0,0 @@ -# {{title "hello world"}} - -{{shell "开机时长" "" "uptime"}} - -{{title "premenu"}} - -## {{chapter "项目总览"}} -{{order "总览" ` -volcano iceberg -context toolkit -preload appframe -`}} - -{{table "总览" ` -volcano iceberg -context toolkit -preload appframe -`}} - -## {{chapter "项目详情"}} -{{chain "详情" ` -context - volcanos - proto.js - frame.js bg blue - Page - Pane - Plugin - Inputs - Output - order.js - icebergs bg blue - type.go - base.go bg red - code - wiki - chat - team - mall - conf.go - toolkits - type.go - core.go bg blue - Split - Parse - Value - Fetch - Favor - misc.go -`}} - -{{title "endmenu"}} - diff --git a/misc/docker/docker.go b/misc/docker/docker.go index 717b7d0d..751fc3f0 100644 --- a/misc/docker/docker.go +++ b/misc/docker/docker.go @@ -16,43 +16,71 @@ var Index = &ice.Context{Name: "docker", Help: "容器管理", ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, - "docker": {Name: "docker", Help: "docker", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Echo("hello world") - }}, - "image": {Name: "image", Help: "镜像管理", Meta: kit.Dict( - "detail", []string{"运行", "清理", "删除"}, - ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + "image": {Name: "image", Help: "镜像管理", Meta: kit.Dict("detail", []string{"运行", "清理", "删除"}), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { prefix := []string{ice.CLI_SYSTEM, "docker", "image"} if len(arg) > 2 { switch arg[1] { case "运行": - m.Cmdy(prefix[:2], "run", "-dt", m.Option("REPOSITORY")+":"+m.Option("TAG")) - m.Set("append") + m.Cmdy(prefix[:2], "run", "-dt", m.Option("REPOSITORY")+":"+m.Option("TAG")).Set("append") return case "清理": - m.Cmd(prefix, "prune", "-f") + m.Cmdy(prefix, "prune", "-f").Set("append") + return case "delete": - switch arg[2] { - case "NAMES": - m.Cmd(prefix, "rename", arg[4], arg[3]) - } + m.Cmdy(prefix, "rm", m.Option("IMAGE_ID")).Set("append") + return } } + if len(arg) > 0 { + // 下载镜像 + m.Cmdy(prefix, "pull", arg[0]+":"+kit.Select("latest", arg, 1)).Set("append") + return + } + // 镜像列表 m.Split(strings.Replace(m.Cmdx(prefix, "ls"), "IMAGE ID", "IMAGE_ID", 1), "index", " ", "\n") + m.Sort("REPOSITORY") }}, - "container": {Name: "container", Help: "容器管理", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + "container": {Name: "container", Help: "容器管理", Meta: kit.Dict( + "exports", []string{"CONTAINER_ID", "CONTAINER_ID"}, + "detail", []string{"进入", "启动", "停止", "重启", "清理", "编辑", "删除"}), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { prefix := []string{ice.CLI_SYSTEM, "docker", "container"} if len(arg) > 2 { switch arg[1] { + case "进入": + m.Cmdy(ice.CLI_SYSTEM, "tmux", "new-window", "-t", "", "-n", m.Option("NAMES"), + "-PF", "#{session_name}:#{window_name}.1", "docker exec -it "+m.Option("NAMES")+" sh").Set("append") + return + case "停止": + m.Cmd(prefix, "stop", m.Option("CONTAINER_ID")) + case "启动": + m.Cmd(prefix, "start", m.Option("CONTAINER_ID")) + case "重启": + m.Cmd(prefix, "restart", m.Option("CONTAINER_ID")) + case "清理": + m.Cmd(prefix, "prune", "-f") case "modify": switch arg[2] { case "NAMES": m.Cmd(prefix, "rename", arg[4], arg[3]) } + case "delete": + m.Cmdy(prefix, "rm", m.Option("CONTAINER_ID")).Set("append") + return } } - m.Split(strings.Replace(m.Cmdx(prefix, "ls"), "CONTAINER ID", "CONTAINER_ID", 1), "index", " ", "\n") + + // 容器列表 + m.Split(strings.Replace(m.Cmdx(prefix, "ls", "-a"), "CONTAINER ID", "CONTAINER_ID", 1), "index", " ", "\n") + m.Sort("NAMES") + }}, + "command": {Name: "command", Help: "命令", List: kit.List( + kit.MDB_INPUT, "text", "name", "CONTAINER_ID", "imports", "CONTAINER_ID", + kit.MDB_INPUT, "text", "name", "command", + kit.MDB_INPUT, "button", "name", "执行", + ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + prefix := []string{ice.CLI_SYSTEM, "docker", "container"} + m.Cmdy(prefix, "exec", arg[0], arg[1:]).Set("append") }}, }, } diff --git a/misc/git/git.go b/misc/git/git.go index 407792c0..e5eb9bc3 100644 --- a/misc/git/git.go +++ b/misc/git/git.go @@ -5,6 +5,7 @@ import ( "github.com/shylinux/icebergs/base/cli" "github.com/shylinux/toolkits" "os" + "path" "strings" "time" ) @@ -21,14 +22,93 @@ var Index = &ice.Context{Name: "git", Help: "代码管理", "name", "volcanos", "path", "usr/volcanos", "branch", "master", "remote", "https://github.com/shylinux/volcanos", )) + m.Rich("repos", nil, kit.Data( + "name", "icebergs", "path", "../../icebergs", "branch", "master", + "remote", "https://github.com/shylinux/icebergs", + )) + m.Rich("repos", nil, kit.Data( + "name", "toolkits", "path", "../../toolkits", "branch", "master", + "remote", "https://github.com/shylinux/toolkits", + )) + m.Rich("repos", nil, kit.Data( + "name", "contexts", "path", "../../contexts", "branch", "master", + "remote", "https://github.com/shylinux/context", + )) + m.Cmd("nfs.dir", m.Conf(ice.WEB_DREAM, "meta.path"), "name path").Table(func(index int, value map[string]string, head []string) { + if s, e := os.Stat(path.Join(value["path"], ".git")); e == nil && s.IsDir() { + m.Rich("repos", nil, kit.Data( + "name", value["name"], "path", value["path"], "branch", "master", + "remote", m.Cmdx(ice.CLI_SYSTEM, "git", "remote", "get-url", "origin"), + )) + } + }) m.Watch(ice.SYSTEM_INIT, "cli.git.check", "volcanos") }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { }}, + "repos": {Name: "repos", Help: "仓库", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Richs("repos", nil, "*", func(key string, value map[string]interface{}) { + m.Push(key, value["meta"], []string{"time", "name", "branch", "path", "remote"}) + }) + m.Sort("name") + }}, + "branch": {Name: "branch", Help: "分支", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + prefix := []string{ice.CLI_SYSTEM, "git", "branch"} + m.Richs("repos", nil, kit.Select("*", arg, 0), func(key string, value map[string]interface{}) { + m.Option("cmd_dir", kit.Value(value, "meta.path")) + for _, v := range strings.Split(m.Cmdx(prefix, "-v"), "\n") { + if len(v) > 0 { + m.Push("repos", kit.Value(value, "meta.name")) + m.Push("tags", v[:2]) + vs := strings.SplitN(strings.TrimSpace(v[2:]), " ", 2) + m.Push("branch", vs[0]) + vs = strings.SplitN(strings.TrimSpace(vs[1]), " ", 2) + m.Push("hash", vs[0]) + m.Push("note", strings.TrimSpace(vs[1])) + } + } + }) + m.Sort("repos") + }}, + "status": {Name: "status", Help: "状态", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + prefix := []string{ice.CLI_SYSTEM, "git", "status"} + m.Richs("repos", nil, kit.Select("*", arg, 0), func(key string, value map[string]interface{}) { + m.Option("cmd_dir", kit.Value(value, "meta.path")) + for _, v := range strings.Split(strings.TrimSpace(m.Cmdx(prefix, "-sb")), "\n") { + vs := strings.SplitN(strings.TrimSpace(v), " ", 2) + m.Push("repos", kit.Value(value, "meta.name")) + m.Push("tags", vs[0]) + m.Push("file", vs[1]) + } + }) + }}, + "total": {Name: "total", Help: "统计", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + days := 0 + commit, adds, dels, rest := 0, 0, 0, 0 + m.Richs("repos", nil, kit.Select("*", arg, 0), func(key string, value map[string]interface{}) { + m.Push("repos", kit.Value(value, "meta.name")) + m.Copy(m.Cmd("sum", "total", kit.Value(value, "meta.path"), "10000").Table(func(index int, value map[string]string, head []string) { + if kit.Int(value["days"]) > days { + days = kit.Int(value["days"]) + } + commit += kit.Int(value["commit"]) + adds += kit.Int(value["adds"]) + dels += kit.Int(value["dels"]) + rest += kit.Int(value["rest"]) + })) + }) + m.Push("repos", "total") + m.Push("days", days) + m.Push("commit", commit) + m.Push("adds", adds) + m.Push("dels", dels) + m.Push("rest", rest) + m.Sort("commit", "int_r") + }}, "check": {Name: "check", Help: "检查", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Richs("repos", nil, arg[0], func(key string, value map[string]interface{}) { if _, e := os.Stat(kit.Format(kit.Value(value, "meta.path"))); e != nil && os.IsNotExist(e) { - m.Cmd("cli.system", "git", "clone", kit.Value(value, "meta.remote"), + m.Cmd(ice.CLI_SYSTEM, "git", "clone", kit.Value(value, "meta.remote"), "-b", kit.Value(value, "meta.branch"), kit.Value(value, "meta.path")) } }) diff --git a/misc/shy.go b/misc/shy.go index 848564d8..07533dcd 100644 --- a/misc/shy.go +++ b/misc/shy.go @@ -1,6 +1,7 @@ package misc import ( + _ "github.com/shylinux/icebergs/misc/docker" _ "github.com/shylinux/icebergs/misc/git" _ "github.com/shylinux/icebergs/misc/tmux" ) diff --git a/misc/tmux/tmux.go b/misc/tmux/tmux.go index 2dc8ee02..cdaa03e7 100644 --- a/misc/tmux/tmux.go +++ b/misc/tmux/tmux.go @@ -244,7 +244,10 @@ var Index = &ice.Context{Name: "tmux", Help: "终端管理", } m.Option("cmd_env", "TMUX", "") - m.Option("cmd_dir", path.Join(m.Conf(ice.WEB_DREAM, "meta.path"), arg[0])) + p := path.Join(m.Conf(ice.WEB_DREAM, "meta.path"), arg[0]) + if s, e := os.Stat(p); e == nil && s.IsDir() { + m.Option("cmd_dir", p) + } // 创建会话 if m.Cmd(prefix, "has-session", "-t", arg[0]).Append("code") != "0" { diff --git a/miss/Makefile b/miss/Makefile new file mode 100644 index 00000000..5caee8da --- /dev/null +++ b/miss/Makefile @@ -0,0 +1,3 @@ +all: + @echo && date + go build -o bin/ice.bin src/main.go && chmod u+x bin/ice.bin && ./bin/ice.sh restart diff --git a/miss/ice.md b/miss/README.md similarity index 51% rename from miss/ice.md rename to miss/README.md index d7639ed0..ca854c60 100644 --- a/miss/ice.md +++ b/miss/README.md @@ -1,5 +1,5 @@ -# {{title "ICEBERGS"}} -icebergs是一个后端框架,通过模块化、集群化实现资源的无限的扩展与自由的组合。 +{{title "ICEBERGS"}} +{{brief `icebergs是一个后端框架,通过模块化、集群化实现资源的无限的扩展与自由的组合。`}} {{chain "icebergs" ` icebergs @@ -41,85 +41,85 @@ icebergs file ` "" "" 16}} -一键创建项目 -``` -mkdir miss; cd miss && curl -s https://shylinux.com/publish/build.sh | sh -``` -一键启动项目 -``` -mkdir miss; cd miss && curl -s https://shylinux.com/publish/ice.sh | sh -``` +{{shell "一键创建项目" "usr" "install" `mkdir miss; cd miss && curl -s https://shylinux.com/publish/build.sh | sh`}} -## {{chapter "配置模块 base/ctx"}} +{{shell "一键启动项目" "usr" "install" `mkdir miss; cd miss && curl -s https://shylinux.com/publish/ice.sh | sh`}} -## {{chapter "命令模块 base/cli"}} +{{chapter "配置模块 base/ctx"}} +{{chapter "命令模块 base/cli"}} cli模块用于与系统进行交互。 -- 系统信息 ice.CLI_RUNTIME -- 系统命令 ice.CLI_SYSTEM +{{order "命令" ` +系统信息 ice.CLI_RUNTIME +系统命令 ice.CLI_SYSTEM +`}} -## {{chapter "通信模块 base/tcp"}} +{{chapter "通信模块 base/tcp"}} tcp模块用于管理网络的读写 -## {{chapter "存储模块 base/nfs"}} +{{chapter "存储模块 base/nfs"}} nfs模块用于管理文件的读写。 -## {{chapter "终端模块 base/ssh"}} +{{chapter "终端模块 base/ssh"}} ssh模块用于与终端交互。 -## {{chapter "数据模块 base/mdb"}} +{{chapter "数据模块 base/mdb"}} mdb模块用于管理数据的读写。 -## {{chapter "词法模块 base/lex"}} +{{chapter "词法模块 base/lex"}} -## {{chapter "语法模块 base/yac"}} +{{chapter "语法模块 base/yac"}} -## {{chapter "日志模块 base/log"}} +{{chapter "日志模块 base/log"}} log模块负责输出日志。 -## {{chapter "事件模块 base/gdb"}} +{{chapter "事件模块 base/gdb"}} gdb模块会根据各种触发条件,择机执行各种命令。 -- 信号器 ice.SIGNAL -- 定时器 ice.TIMER -- 触发器 ice.EVENT +{{order "命令" ` +信号器 ice.SIGNAL +定时器 ice.TIMER +触发器 ice.EVENT +`}} -## {{chapter "认证模块 base/aaa"}} +{{chapter "认证模块 base/aaa"}} aaa模块用于各种权限管理与身份认证。 -- 角色 ice.AAA_ROLE -- 用户 ice.AAA_USER -- 会话 ice.AAA_SESS +{{order "命令" ` +角色 ice.AAA_ROLE +用户 ice.AAA_USER +会话 ice.AAA_SESS +`}} -## {{chapter "网络模块 base/web"}} +{{chapter "网络模块 base/web"}} web模块用于组织网络节点,与生成前端网页, -### {{section "网络爬虫 ice.WEB_SPIDE"}} +{{section "网络爬虫 ice.WEB_SPIDE"}} WEB_SPIDE功能,用于发送网络请求获取相关数据。 -### {{section "网络服务 ice.WEB_SERVE"}} +{{section "网络服务 ice.WEB_SERVE"}} WEB_SERVE功能,用于启动网络服务器接收网络请求。 -### {{section "网络节点 ice.WEB_SPACE"}} +{{section "网络节点 ice.WEB_SPACE"}} WEB_SPACE功能,用于与相连网络节点进行通信。 -### {{section "网络任务 ice.WEB_DREAM"}} +{{section "网络任务 ice.WEB_DREAM"}} WEB_DREAM功能,用于启动本地节点,管理各种任务的相关资源。 -### {{section "网络收藏 ice.WEB_FAVOR"}} +{{section "网络收藏 ice.WEB_FAVOR"}} WEB_FAVOR功能,用于收藏各种实时数据,进行分类管理。 -### {{section "网络缓存 ice.WEB_CACHE"}} +{{section "网络缓存 ice.WEB_CACHE"}} WEB_CACHE功能,用于管理缓存数据,自动存储与传输。 -### {{section "网络存储 ice.WEB_STORY"}} +{{section "网络存储 ice.WEB_STORY"}} WEB_STORY功能,用于记录数据的历史变化,可以查看任意历史版本。 -### {{section "网络共享 ice.WEB_SHARE"}} +{{section "网络共享 ice.WEB_SHARE"}} WEB_SHARE功能,用于数据与应用的共享,可以查到所有数据流通记录。 -### {{section "网络路由 ice.WEB_ROUTE"}} -### {{section "网络代理 ice.WEB_PROXY"}} -### {{section "网络分组 ice.WEB_GROUP"}} -### {{section "网络标签 ice.WEB_LABEL"}} +{{section "网络路由 ice.WEB_ROUTE"}} +{{section "网络代理 ice.WEB_PROXY"}} +{{section "网络分组 ice.WEB_GROUP"}} +{{section "网络标签 ice.WEB_LABEL"}} diff --git a/miss/go.mod b/miss/go.mod deleted file mode 100644 index f6808bb5..00000000 --- a/miss/go.mod +++ /dev/null @@ -1,10 +0,0 @@ -module miss - -go 1.13 - -require github.com/shylinux/icebergs v0.1.0 - -replace ( - github.com/shylinux/icebergs => ../ - github.com/shylinux/toolkits => ../../toolkits -) diff --git a/miss/main.go b/miss/main.go deleted file mode 100644 index a61fb87f..00000000 --- a/miss/main.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import ( - "github.com/shylinux/icebergs" - _ "github.com/shylinux/icebergs/base" - _ "github.com/shylinux/icebergs/core" - _ "github.com/shylinux/icebergs/misc" - - _ "github.com/shylinux/icebergs/misc/docker" -) - -func main() { - println(ice.Run()) -} diff --git a/build.sh b/template.sh similarity index 61% rename from build.sh rename to template.sh index 08ba9d2b..ea1e528c 100755 --- a/build.sh +++ b/template.sh @@ -1,7 +1,20 @@ #! /bin/sh +ice_sh="bin/ice.sh" +ice_bin="bin/ice.bin" +ice_mod="${PWD##**/}" +init_shy="etc/init.shy" +exit_shy="etc/exit.shy" +main_go="src/main.go" +readme="README.md" + prepare() { - [ -f main.go ] || cat >> main.go <> ${readme} <> ${main_go} <> Makefile <> ice.sh <> ${init_shy} <> "${exit_shy}" <> ${ice_sh} <\$ctx_log && echo -e "\n\nrestarting..." || break + date && ./${ice_bin} \$@ 2>\$ctx_log && echo -e "\n\nrestarting..." || break done } serve() { @@ -66,12 +87,12 @@ shutdown() { cmd=\$1 && [ -n "\$cmd" ] && shift || cmd=serve \$cmd \$* END - chmod u+x ice.sh + chmod u+x ${ice_sh} } build() { miss=./ && [ "$1" != "" ] && miss=$1 && shift && mkdir $miss - cd $miss && prepare && go build -o ice.bin main.go && chmod u+x ice.bin && ./ice.sh start serve dev + cd $miss && prepare && go build -o ${ice_bin} ${main_go} && chmod u+x ${ice_bin} && ./${ice_sh} start serve dev } tutor() { diff --git a/type.go b/type.go index 6c4dcbf0..e7507292 100644 --- a/type.go +++ b/type.go @@ -100,6 +100,16 @@ func (c *Context) Register(s *Context, x Server) *Context { return s } +func (c *Context) Spawn(m *Message, name string, help string, arg ...string) *Context { + s := &Context{Name: name, Help: help, Caches: map[string]*Cache{}} + if m.target.Server != nil { + c.Register(s, m.target.server.Spawn(m, s, arg...)) + } else { + c.Register(s, nil) + } + m.target = s + return s +} func (c *Context) Begin(m *Message, arg ...string) *Context { c.Caches[CTX_STATUS] = &Cache{Name: CTX_STATUS, Value: ""} c.Caches[CTX_STREAM] = &Cache{Name: CTX_STREAM, Value: ""} @@ -357,6 +367,7 @@ func (m *Message) Copy(msg *Message) *Message { } func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Message { switch value := value.(type) { + case map[string]string: case map[string]interface{}: if key == "detail" { value = kit.KeyValue(map[string]interface{}{}, "", value) @@ -555,8 +566,30 @@ func (m *Message) Render(str string, arg ...interface{}) *Message { return m } func (m *Message) Split(str string, field string, space string, enter string) *Message { + indexs := []int{} fields := kit.Split(field, space) - for _, l := range kit.Split(str, enter) { + for i, l := range kit.Split(str, enter) { + if i == 0 && (field == "" || field == "index") { + fields = kit.Split(l, space) + if field == "index" { + for _, v := range fields { + indexs = append(indexs, strings.Index(l, v)) + } + } + continue + } + + if len(indexs) > 0 { + for i, v := range indexs { + if i == len(indexs)-1 { + m.Push(kit.Select("some", fields, i), l[v:]) + } else { + m.Push(kit.Select("some", fields, i), l[v:indexs[i+1]]) + } + } + continue + } + for i, v := range kit.Split(l, space) { m.Push(kit.Select("some", fields, i), v) } @@ -762,6 +795,10 @@ func (m *Message) Start(key string, arg ...string) *Message { }) return m } +func (m *Message) Starts(name string, help string, arg ...string) *Message { + m.target.Spawn(m, name, help, arg...).Begin(m, arg...).Start(m, arg...) + return m +} func (m *Message) Call(sync bool, cb func(*Message) *Message) *Message { if sync { wait := make(chan bool) @@ -779,6 +816,10 @@ func (m *Message) Back(sub *Message) *Message { } return m } +func (m *Message) Sleep(arg string) *Message { + time.Sleep(kit.Duration(arg)) + return m +} func (m *Message) Travel(cb interface{}) *Message { list := []*Context{m.target}