1
0
forked from x/icebergs
This commit is contained in:
shaoying 2020-01-12 15:35:12 +08:00
parent 5783c5f09a
commit f3b78ae6c5
26 changed files with 382 additions and 268 deletions

View File

@ -2,9 +2,24 @@
icebergs是一个后端框架通过模块化、集群化实现资源的无限的扩展与自由的组合。
使用icebergs可以将各种模块或项目集成到一起快速开发出集中式的服务器。
使用icebergs可以将各种设备自由的组合在一起快速搭建起分布式的服务器。
所以通过icebergs开发出来的模块无需任何多余代码就可以独立运行可以成为系统命令可以远程调用可以成为前端插件可以成为小程序页面。
## 项目开发
开发环境需要安装gitgolang
一键创建项目
```
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

View File

@ -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)

View File

@ -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)

View File

@ -116,8 +116,15 @@ var Index = &ice.Context{Name: "ctx", Help: "配置模块",
}
}
default:
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])))
}
}
}},
},
}

View File

@ -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])))
}
}},
},

View File

@ -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:]...)
}},
},
}

View File

@ -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")}
}

View File

@ -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":

View File

@ -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))

View File

@ -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:]

View File

@ -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 "取消":

View File

@ -1,2 +0,0 @@
all:
go build -o bin/ice.bin main.go && chmod u+x bin/ice.bin && ./ice.sh restart

View File

@ -1,62 +0,0 @@
#! /bin/sh
ice_sh=${ice_sh:="ice.sh"}
prepare() {
[ -f main.go ] || cat >> main.go <<END
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())
}
END
[ -f go.mod ] || go mod init ${PWD##**/}
[ -f ${ice_sh} ] || cat >> ${ice_sh} <<END
#! /bin/sh
export PATH=\${PWD}/bin:\${PWD}:\$PATH
prepare() {
which ice.bin && return
curl -s https://shylinux.com/publish/ice.bin -o bin/ice.bin
}
start() {
prepare && while true; do
date && ice.bin \$@ 2>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 <<END
all:
go build -o bin/ice.bin main.go && chmod u+x bin/ice.bin && ./${ice_sh} restart
END
}
build() {
[ "$1" != "" ] && mdkir $1 && cd $1
prepare && go build -o bin/ice.bin main.go && chmod u+x bin/ice.bin && ./${ice_sh}
}
cmd=$1 && shift
[ -z "$cmd" ] && cmd=build
$cmd $*

View File

@ -1,13 +0,0 @@
module github.com/shylinux/icebergs/demo
go 1.13
require (
github.com/shylinux/icebergs v0.0.0-20191212145348-fe6226481eaa
github.com/shylinux/toolkits v0.0.0-20191225132906-3c11db083b5b
)
replace (
github.com/shylinux/icebergs => ../
github.com/shylinux/toolkits => ../../toolkits
)

View File

@ -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())
}

View File

@ -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"}}

View File

@ -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")
}},
},
}

View File

@ -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"))
}
})

View File

@ -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"
)

View File

@ -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" {

3
miss/Makefile Normal file
View File

@ -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

View File

@ -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"}}

View File

@ -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
)

View File

@ -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())
}

View File

@ -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 <<END
[ -f ${readme} ] || cat >> ${readme} <<END
hello ice world
END
[ -d src ] || mkdir src
[ -f ${main_go} ] || cat >> ${main_go} <<END
package main
import (
@ -16,24 +29,32 @@ func main() {
}
END
[ -f go.mod ] || go mod init ${PWD##**/}
[ -f src/go.mod ] || cd src && go mod init ${ice_mod} && cd ..
[ -f Makefile ] || cat >> Makefile <<END
all:
@echo && date
go build -o ice.bin main.go && chmod u+x ice.bin && ./ice.sh restart
go build -o ${ice_bin} ${main_go} && chmod u+x ${ice_bin} && ./${ice_sh} restart
END
[ -f ice.sh ] || cat >> ice.sh <<END
[ -d etc ] || mkdir etc
[ -f ${init_shy} ] || cat >> ${init_shy} <<END
END
[ -f ${exit_shy} ] || cat >> "${exit_shy}" <<END
END
[ -d bin ] || mkdir bin
[ -f ${ice_sh} ] || cat >> ${ice_sh} <<END
#! /bin/sh
export PATH=\${PWD}:\$PATH
export PATH=\${PWD}:\${PWD}/bin:\$PATH
export ctx_pid=\${ctx_pid:=var/run/ice.pid}
export ctx_log=\${ctx_log:=boot.log}
export ctx_log=\${ctx_log:=bin/boot.log}
prepare() {
[ -e ice.sh ] || curl \$ctx_dev/publish/ice.sh -o ice.sh && chmod u+x ice.sh
[ -e ice.bin ] && chmod u+x ice.bin && return
[ -d etc ] || mkdir bin
[ -e ${ice_sh} ] || curl \$ctx_dev/publish/ice.sh -o ${ice_sh} && chmod u+x ${ice_sh}
[ -e ${ice_bin} ] && chmod u+x ${ice_bin} && return
bin="ice"
case \`uname -s\` in
@ -46,11 +67,11 @@ prepare() {
i686) bin=\${bin}.386 ;;
arm*) bin=\${bin}.arm ;;
esac
curl \$ctx_dev/publish/\${bin} -o ice.bin && chmod u+x ice.bin
curl \$ctx_dev/publish/\${bin} -o ${ice_bin} && chmod u+x ${ice_bin}
}
start() {
trap HUP hup && while true; do
date && ice.bin \$@ 2>\$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() {

43
type.go
View File

@ -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}