From b3aaae590f3385f28a5e6dfec65a3624d14ddf90 Mon Sep 17 00:00:00 2001 From: shy Date: Thu, 28 Dec 2023 23:15:59 +0800 Subject: [PATCH] add status.source --- base/cli/runtime.go | 11 +++++++ base/ctx/command.go | 1 + base/mdb/lock.go | 4 ++- base/web/dream.go | 3 +- base/web/render.go | 11 ++----- base/web/spide.go | 14 ++++++--- core/chat/footer.go | 23 ++++++++++----- core/chat/pod.go | 4 +-- core/chat/storm.go | 6 ++-- info.go | 21 +++++++++++++ misc/ssh/relay/relay.go | 65 ++++++++++++++++++++--------------------- misc/ssh/relay/trans.go | 5 ++-- option.go | 2 +- 13 files changed, 105 insertions(+), 65 deletions(-) diff --git a/base/cli/runtime.go b/base/cli/runtime.go index 3cfc43cf..b819aedf 100644 --- a/base/cli/runtime.go +++ b/base/cli/runtime.go @@ -292,3 +292,14 @@ func NodeInfo(m *ice.Message, arg ...string) { ice.Info.NodeType = mdb.Conf(m, RUNTIME, kit.Keys(NODE, mdb.TYPE), kit.Select(ice.Info.NodeType, arg, 1)) } func IsWindows() bool { return runtime.GOOS == WINDOWS } +func ParseMake(str string) []string { + res := kit.UnMarshal(str) + data := kit.Value(res, MAKE) + return kit.Simple( + nfs.MODULE, kit.Value(data, nfs.MODULE), nfs.VERSION, kit.Join(kit.TrimArg(kit.Simple( + kit.Value(data, nfs.VERSION), kit.Value(data, "forword"), kit.Cut(kit.Format(kit.Value(data, mdb.HASH)), 6), + )...), "-"), + nfs.COMMIT, kit.Value(data, "when"), "compile", kit.Value(data, mdb.TIME), BOOT, kit.Value(res, "boot.time"), + ice.SPACE, kit.Value(res, "node.name"), + ) +} diff --git a/base/ctx/command.go b/base/ctx/command.go index 88c788a0..541a9682 100644 --- a/base/ctx/command.go +++ b/base/ctx/command.go @@ -24,6 +24,7 @@ func _command_list(m *ice.Message, name string) *ice.Message { m.Push(mdb.META, kit.Format(cmd.Meta)) m.Push(mdb.LIST, kit.Format(cmd.List)) m.Push("_help", GetCmdHelp(m, name)) + m.Push("_fileline", kit.MergeURL(FileURI(kit.Split(cmd.FileLine(), ":")[0]), ice.POD, m.Option(ice.MSG_USERPOD))) }) return m } diff --git a/base/mdb/lock.go b/base/mdb/lock.go index 5736ff7d..88fc7c2d 100644 --- a/base/mdb/lock.go +++ b/base/mdb/lock.go @@ -24,7 +24,9 @@ func getLock(m configMessage, arg ...string) *task.Lock { kit.If(!ok, func() { l = &task.Lock{}; _locks[key] = l }) return l } -func Lock(m configMessage, arg ...string) func() { return getLock(m, arg...).Lock() } +func Lock(m configMessage, arg ...string) func() { + return getLock(m, arg...).Lock() +} func RLock(m configMessage, arg ...string) func() { return getLock(m, arg...).RLock() } func Config(m configMessage, key string, arg ...Any) string { diff --git a/base/web/dream.go b/base/web/dream.go index a7bb63e9..1fee6a87 100644 --- a/base/web/dream.go +++ b/base/web/dream.go @@ -56,9 +56,10 @@ func _dream_start(m *ice.Message, name string) { if m.Warn(name == "", ice.ErrNotValid, mdb.NAME) { return } + defer mdb.Lock(m, m.PrefixKey(), cli.START, name)() defer m.ProcessOpen(m.MergePod(m.Option(mdb.NAME, name))) p := path.Join(ice.USR_LOCAL_WORK, name) - if p := path.Join(p, ice.Info.PidPath); nfs.Exists(m, p) { + if p := path.Join(p, ice.Info.PidPath); nfs.Exists(m, p) && nfs.Exists(m, "/proc/") { if pid := m.Cmdx(nfs.CAT, p, kit.Dict(ice.MSG_USERROLE, aaa.TECH)); pid != "" && nfs.Exists(m, "/proc/"+pid) { m.Info("already exists %v", pid) return diff --git a/base/web/render.go b/base/web/render.go index 1df16ebc..d2242d2d 100644 --- a/base/web/render.go +++ b/base/web/render.go @@ -134,16 +134,11 @@ func RenderCmds(m *ice.Message, cmds ...ice.Any) { RenderMain(m.Options(ctx.CMDS, kit.Format(cmds))) } func RenderPodCmd(m *ice.Message, pod, cmd string, arg ...ice.Any) { - msg := m.Cmd(Space(m, pod), ctx.COMMAND, kit.Select(m.PrefixKey(), cmd)) - if msg.Length() == 0 { + if msg := m.Cmd(Space(m, pod), ctx.COMMAND, kit.Select(m.PrefixKey(), cmd)); msg.Length() == 0 { RenderResult(m, kit.Format("not found command %s", cmd)) - return + } else { + RenderCmds(m, kit.Dict(msg.AppendSimple(), ctx.ARGS, kit.Simple(arg), ctx.DISPLAY, m.Option(ice.MSG_DISPLAY))) } - RenderCmds(m, kit.Dict(msg.AppendSimple(mdb.NAME, mdb.HELP), - ctx.INDEX, msg.Append(ctx.INDEX), ctx.ARGS, kit.Simple(arg), ctx.DISPLAY, m.Option(ice.MSG_DISPLAY), - mdb.LIST, kit.UnMarshal(msg.Append(mdb.LIST)), mdb.META, kit.UnMarshal(msg.Append(mdb.META)), - "_help", msg.Append("_help"), - )) } func RenderCmd(m *ice.Message, cmd string, arg ...ice.Any) { RenderPodCmd(m, "", cmd, arg...) diff --git a/base/web/spide.go b/base/web/spide.go index 2cd4203a..40502162 100644 --- a/base/web/spide.go +++ b/base/web/spide.go @@ -362,14 +362,20 @@ func init() { }) } -func HostPort(m *ice.Message, host, port string) string { +func HostPort(m *ice.Message, host, port string, arg ...string) string { + p := "" + if len(arg) > 0 { + kit.If(kit.Select("", arg, 0), func(pod string) { p += "/pod/" + pod }) + kit.If(kit.Select("", arg, 1), func(cmd string) { p += "/cmd/" + cmd }) + kit.If(p, func() { p = "/chat" + p }) + } kit.If(host == "", func() { host = kit.ParseURL(UserHost(m)).Hostname() }) if port == tcp.PORT_443 { - return kit.Format("https://%s", host) + return kit.Format("https://%s", host) + p } else if port == tcp.PORT_80 || port == "" { - return kit.Format("http://%s", host) + return kit.Format("http://%s", host) + p } else { - return kit.Format("http://%s:%s", host, port) + return kit.Format("http://%s:%s", host, port) + p } } func PublicIP(m *ice.Message) ice.Any { diff --git a/core/chat/footer.go b/core/chat/footer.go index 5dfca0fd..7d38cce6 100644 --- a/core/chat/footer.go +++ b/core/chat/footer.go @@ -2,6 +2,7 @@ package chat import ( ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" @@ -11,20 +12,28 @@ import ( const FOOTER = "footer" +func _footer_plugin(m *ice.Message, cmd string, args ice.Any, arg ...string) { + if p := m.Option(ice.POD); p != "" && arg[0] != cli.RUN { + defer m.Push(web.SPACE, p) + } + if !web.PodCmd(m, ice.POD, kit.Simple(m.ActionKey(), arg)...) { + ctx.ProcessField(m, cmd, args, arg...) + } +} func init() { Index.MergeCommands(ice.Commands{ FOOTER: {Help: "状态栏", Actions: ice.MergeActions(ice.Actions{ ice.HELP: {Hand: func(m *ice.Message, arg ...string) { - if !web.PodCmd(m, ice.POD, kit.Simple(m.ActionKey(), arg)...) { - ctx.ProcessField(m, web.WIKI_WORD, ctx.GetCmdHelp(m, arg[0]), arg...) - } + _footer_plugin(m, web.WIKI_WORD, ctx.GetCmdHelp(m, arg[0]), arg...) }}, nfs.SOURCE: {Hand: func(m *ice.Message, arg ...string) { - if !web.PodCmd(m, ice.POD, kit.Simple(m.ActionKey(), arg)...) { - ctx.ProcessField(m, web.CODE_INNER, func() []string { return nfs.SplitPath(m, ctx.GetCmdFile(m, arg[0])) }, arg...) - } + _footer_plugin(m, web.CODE_VIMER, func() []string { + return nfs.SplitPath(m, ctx.GetCmdFile(m, arg[0])) + }, arg...) + }}, + ctx.CONFIG: {Hand: func(m *ice.Message, arg ...string) { + _footer_plugin(m, ctx.CONFIG, arg, arg...) }}, - ctx.CONFIG: {Hand: func(m *ice.Message, arg ...string) { ctx.ProcessField(m, ctx.CONFIG, arg, arg...) }}, }, web.ApiWhiteAction()), Hand: func(m *ice.Message, arg ...string) { m.Result(kit.Select(ice.Info.Make.Email, mdb.Config(m, TITLE))) }}, diff --git a/core/chat/pod.go b/core/chat/pod.go index baf11a02..b8963f2a 100644 --- a/core/chat/pod.go +++ b/core/chat/pod.go @@ -29,8 +29,8 @@ func init() { if m.Cmd(web.SPACE, arg[0]).Length() == 0 && nfs.Exists(m, path.Join(ice.USR_LOCAL_WORK, arg[0])) { m.Cmd(web.DREAM, cli.START, kit.Dict(mdb.NAME, arg[0])) } - if len(arg) == 1 { - m.Cmdy(web.SPACE, arg[0], web.SPACE, ice.MAIN, kit.Dict(ice.MSG_USERPOD, arg[0])) + if m.Option(ice.MSG_USERPOD, arg[0]); len(arg) == 1 { + m.Cmdy(web.SPACE, arg[0], web.SPACE, ice.MAIN) } else if arg[1] == CMD { web.RenderPodCmd(m, arg[0], arg[2], arg[3:]) } diff --git a/core/chat/storm.go b/core/chat/storm.go index e1e8b60d..c7d7462b 100644 --- a/core/chat/storm.go +++ b/core/chat/storm.go @@ -38,8 +38,7 @@ func init() { }}, }, Hand: func(m *ice.Message, arg ...string) { if m.Option(ice.MSG_STORM) == "" { - m.Cmdy(mdb.SELECT, RIVER, _river_key(m), mdb.HASH, ice.OptionFields("time,hash,icon,name,text,count")) - m.Action(mdb.CREATE) + m.Cmdy(mdb.SELECT, RIVER, _river_key(m), mdb.HASH, ice.OptionFields("time,hash,icon,name,text,count")).Action(mdb.CREATE) } else if len(arg) == 0 || kit.Int(arg[0]) > 0 { m.Cmdy(mdb.SELECT, RIVER, _storm_key(m), mdb.LIST, mdb.ID, arg, ice.OptionFields("time,id,space,icon,index,args,style,display,deleted")).SortInt(mdb.ID) m.Table(func(value ice.Maps) { @@ -49,8 +48,7 @@ func init() { m.Push(mdb.META, msg.Append(mdb.META)) m.Push(mdb.LIST, msg.Append(mdb.LIST)) m.Push("_help", msg.Append("_help")) - }) - m.Action(mdb.INSERT) + }).Action(mdb.INSERT) } else if aaa.Right(m, arg) { m.Push(ctx.INDEX, arg[0]) } diff --git a/info.go b/info.go index 00f05998..1a114f0e 100644 --- a/info.go +++ b/info.go @@ -3,6 +3,7 @@ package ice import ( "io" "os" + "path" "reflect" "strings" @@ -293,3 +294,23 @@ func Module(prefix string, arg ...Any) { return m } } +func FileURI(dir string) string { + if dir == "" { + return "" + } else if strings.Contains(dir, "/pkg/mod/") { + dir = strings.Split(dir, "/pkg/mod/")[1] + } else if Info.Make.Path != "" && strings.HasPrefix(dir, Info.Make.Path) { + dir = strings.TrimPrefix(dir, Info.Make.Path) + } else if strings.HasPrefix(dir, kit.Path("")+PS) { + dir = strings.TrimPrefix(dir, kit.Path("")+PS) + } else if strings.HasPrefix(dir, ISH_PLUGED) { + dir = strings.TrimPrefix(dir, ISH_PLUGED) + } else if kit.HasPrefix(dir, PS, HTTP) { + return dir + } + if strings.HasPrefix(dir, USR_VOLCANOS) { + return strings.TrimPrefix(dir, USR) + } else { + return path.Join(PS, REQUIRE, dir) + } +} diff --git a/misc/ssh/relay/relay.go b/misc/ssh/relay/relay.go index 787377be..a83ee9c5 100644 --- a/misc/ssh/relay/relay.go +++ b/misc/ssh/relay/relay.go @@ -62,18 +62,22 @@ type relay struct { short string `data:"machine"` field string `data:"time,machine,username,password,host,port,portal,module,version,commit,compile,boot,package,shell,kernel,arch,ncpu,vcpu,mhz,mem,disk,network,listen,socket,proc,vendor"` statsTables string `name:"statsTables" event:"stats.tables"` - create string `name:"create machine* username* password host* port*=22 portal vendor"` + create string `name:"create machine* username* password host* port*=22"` pubkey string `name:"pubkey" help:"公钥" icon:"bi bi-person-vcard"` version string `name:"version" help:"版本"` stats string `name:"stats machine" help:"采集" icon:"bi bi-pc-display"` dream string `name:"dream" help:"空间" icon:"bi bi-grid-3x3-gap"` forEach string `name:"forEach machine cmd*:textarea=pwd" help:"遍历" icon:"bi bi-card-list"` forFlow string `name:"forFlow machine cmd*:textarea=pwd" help:"流程" icon:"bi bi-terminal"` + publish string `name:"publish" help:"发布"` list string `name:"list machine auto" help:"代理" icon:"relay.png"` pushbin string `name:"pushbin" help:"部署"` adminCmd string `name:"adminCmd cmd" help:"命令"` } +func (s relay) StatsTables(m *ice.Message, arg ...string) { + web.PushStats(m.Message, "", mdb.HashSelects(m.Spawn().Message).Length(), "", "服务器数量") +} func (s relay) Init(m *ice.Message, arg ...string) { s.Hash.Init(m).TransInput(MACHINE, "机器", PACKAGE, "软件包", SHELL, "命令行", KERNEL, "内核", ARCH, "架构", @@ -85,9 +89,6 @@ func (s relay) Init(m *ice.Message, arg ...string) { msg := m.Spawn(ice.Maps{ice.MSG_FIELDS: ""}) m.GoSleep3s(func() { s.Hash.List(msg).Table(func(value ice.Maps) { s.xterm(m.Spawn(value)) }) }) } -func (s relay) StatsTables(m *ice.Message, arg ...string) { - web.PushStats(m.Message, "", mdb.HashSelects(m.Spawn().Message).Length(), "", "服务器数量") -} func (s relay) Inputs(m *ice.Message, arg ...string) { switch s.Hash.Inputs(m, arg...); arg[0] { case MACHINE: @@ -104,22 +105,6 @@ func (s relay) Inputs(m *ice.Message, arg ...string) { m.Push(arg[0], tcp.PORT_443, tcp.PORT_80, tcp.PORT_9020) } } -func (s relay) Compile(m *ice.Message) { - m.Cmdy(code.COMPILE, SRC_RELAY_GO, path.Join(ice.USR_PUBLISH, RELAY)).ProcessInner() -} -func (s relay) Publish(m *ice.Message, arg ...string) { - if m.Option(MACHINE) == "" { - s.Hash.ForEach(m, "", func(msg *ice.Message) { s.Publish(msg) }) - m.Cmdy(nfs.DIR, ice.USR_PUBLISH).Set(ctx.ACTION) - return - } - kit.If(!nfs.Exists(m, path.Join(ice.USR_PUBLISH, RELAY)), func() { s.Compile(m) }) - os.Symlink(RELAY, ice.USR_PUBLISH+m.Option(MACHINE)) - m.Cmd(nfs.SAVE, kit.HomePath(".ssh/"+m.Option(MACHINE)+".json"), kit.Formats(kit.Dict(m.OptionSimple("username,password,host,port")))+ice.NL) -} -func (s relay) Pubkey(m *ice.Message, arg ...string) { - m.EchoScript(m.Cmdx(nfs.CAT, kit.HomePath(ssh.ID_RSA_PUB))).ProcessInner() -} func (s relay) Stats(m *ice.Message) { cmds := []string{ PACKAGE, `if yum -h &>/dev/null; then echo yum; elif apk version &>/dev/null; then echo apk; elif apt -h &>/dev/null; then echo apt; fi`, @@ -166,6 +151,10 @@ func (s relay) Stats(m *ice.Message) { }) } func (s relay) Dream(m *ice.Message) { + if m.Option(web.PORTAL) != "" { + m.ProcessOpen(web.HostPort(m.Message, m.Option(tcp.HOST), m.Option(web.PORTAL), "", web.DREAM)) + return + } fields := "time,machine,host,space,type,status,module,version,commit,compile,boot,link" s.foreach(m, func(msg *ice.Message, cmd []string) { m.Push("", kit.Dict(msg.OptionSimple(fields), mdb.TYPE, web.SERVER, mdb.STATUS, web.ONLINE, web.SPACE, ice.CONTEXTS, web.LINK, web.HostPort(m.Message, msg.Option(tcp.HOST), msg.Option(web.PORTAL))), kit.Split(fields)) @@ -176,7 +165,7 @@ func (s relay) Dream(m *ice.Message) { case "": _msg.Push(web.LINK, "") default: - _msg.Push(web.LINK, kit.Format("%s/chat/pod/%s", web.HostPort(m.Message, msg.Option(tcp.HOST), msg.Option(web.PORTAL)), value[web.SPACE])) + _msg.Push(web.LINK, web.HostPort(m.Message, msg.Option(tcp.HOST), msg.Option(web.PORTAL), value[web.SPACE])) } }).Cut(fields)) }) @@ -206,15 +195,31 @@ func (s relay) ForEach(m *ice.Message, arg ...string) *ice.Message { } func (s relay) ForFlow(m *ice.Message) { s.foreach(m, func(msg *ice.Message, cmd []string) { - ssh.PushShell(msg.Message, cmd, func(res string) { web.PushNoticeGrow(m.Options(ctx.DISPLAY, web.PLUGIN_XTERM), res) }) + ssh.PushShell(msg.Message, cmd, func(res string) { web.PushNoticeGrow(m.Options(ctx.DISPLAY, web.PLUGIN_XTERM).Message, res) }) }) } +func (s relay) Compile(m *ice.Message) { + m.Cmdy(code.COMPILE, SRC_RELAY_GO, path.Join(ice.USR_PUBLISH, RELAY)).ProcessInner() +} +func (s relay) Publish(m *ice.Message, arg ...string) { + if m.Option(MACHINE) == "" { + s.Hash.ForEach(m, "", func(msg *ice.Message) { s.Publish(msg) }) + m.Cmdy(nfs.DIR, ice.USR_PUBLISH).Set(ctx.ACTION) + return + } + kit.If(!nfs.Exists(m, path.Join(ice.USR_PUBLISH, RELAY)), func() { s.Compile(m) }) + os.Symlink(RELAY, ice.USR_PUBLISH+m.Option(MACHINE)) + m.Cmd(nfs.SAVE, kit.HomePath(".ssh/"+m.Option(MACHINE)+".json"), kit.Formats(kit.Dict(m.OptionSimple("username,password,host,port")))+ice.NL) +} +func (s relay) Pubkey(m *ice.Message, arg ...string) { + m.EchoScript(m.Cmdx(nfs.CAT, kit.HomePath(ssh.ID_RSA_PUB))).ProcessInner() +} func (s relay) List(m *ice.Message, arg ...string) *ice.Message { if s.Hash.List(m, arg...); len(arg) == 0 { if m.Length() == 0 { - m.Action(s.Create, s.Compile, s.Publish, s.Pubkey) + m.Action(s.Create) } else { - m.Action(s.Create, s.Upgrade, s.Version, s.Stats, s.Dream, s.ForEach, s.ForFlow, s.Compile, s.Publish, s.Pubkey) + m.Action(s.Create, s.Upgrade, s.Version, s.Stats, s.Dream) } } stats := map[string]int{} @@ -234,15 +239,8 @@ func (s relay) List(m *ice.Message, arg ...string) *ice.Message { m.Push(web.LINK, "").PushButton(s.Xterm, s.AdminCmd, s.Pushbin, s.Install, s.Remove) return } - m.PushButton(s.Admin, s.Vimer, s.Repos, s.Xterm, s.AdminCmd, s.Pushbin, s.Upgrade, s.Remove) - switch value[web.PORTAL] { - case tcp.PORT_443: - m.Push(web.LINK, kit.Format("https://%s", value[tcp.HOST])) - case tcp.PORT_80: - m.Push(web.LINK, kit.Format("http://%s", value[tcp.HOST])) - default: - m.Push(web.LINK, kit.Format("http://%s:%s", value[tcp.HOST], value[web.PORTAL])) - } + m.Push(web.LINK, web.HostPort(m.Message, value[tcp.HOST], value[web.PORTAL])) + m.PushButton(s.Admin, s.Dream, s.Xterm, s.Vimer, s.AdminCmd, s.Pushbin, s.Upgrade, s.Remove) kit.If(len(arg) > 0, func() { m.PushQRCode(cli.QRCODE, m.Append(web.LINK)) }) }) _stats := kit.Dict(MEM, kit.FmtSize(stats[MEM_FREE], stats[MEM_TOTAL]), DISK, kit.FmtSize(stats[DISK_USED], stats[DISK_TOTAL])) @@ -287,7 +285,6 @@ func (s relay) Pushbin(m *ice.Message, arg ...string) { func (s relay) AdminCmd(m *ice.Message, arg ...string) { s.shell(m, s.admins(m, m.Option(ice.CMD)), arg...) } - func (s relay) Xterm(m *ice.Message, arg ...string) { s.Code.Xterm(m, m.Option(MACHINE), arg...) } func (s relay) Repos(m *ice.Message, arg ...string) { s.iframeCmd(m, web.CODE_GIT_STATUS, arg...) } func (s relay) Vimer(m *ice.Message, arg ...string) { s.iframeCmd(m, web.CODE_VIMER, arg...) } diff --git a/misc/ssh/relay/trans.go b/misc/ssh/relay/trans.go index d9f09374..64b96a60 100644 --- a/misc/ssh/relay/trans.go +++ b/misc/ssh/relay/trans.go @@ -79,9 +79,8 @@ func (s trans) Trash(m *ice.Message, arg ...string) { func init() { ice.Cmd(SSH_TRANS, trans{}) } func (s trans) open(m *ice.Message, cb func(*ssh.FileSystem), arg ...string) { - ssh.Open(m.Options(m.Cmd(SSH_RELAY, kit.Select(m.Option(MACHINE), arg, 0)).AppendSimple()), func(fs *ssh.FileSystem) { - defer m.Options(ice.MSG_FILES, nil) - m.Options(ice.MSG_FILES, fs) + ssh.Open(m.Options(m.Cmd(SSH_RELAY, kit.Select(m.Option(MACHINE), arg, 0)).AppendSimple()).Message, func(fs *ssh.FileSystem) { + defer m.Options(ice.MSG_FILES, fs).Options(ice.MSG_FILES, nil) cb(fs) }) } diff --git a/option.go b/option.go index 69c2df1f..36c0e2fb 100644 --- a/option.go +++ b/option.go @@ -80,8 +80,8 @@ func (m *Message) Status(arg ...Any) *Message { } func (m *Message) StatusTime(arg ...Any) *Message { args := []string{} - kit.If(m.Option(MSG_DEBUG) == TRUE, func() { args = append(args, SIZE, "") }) kit.If(m.Option(MSG_DEBUG) == TRUE, func() { args = append(args, kit.MDB_COST, m.FormatCost()) }) + kit.If(m.Option(MSG_DEBUG) == TRUE, func() { args = append(args, "msg", "") }) kit.If(m.Option(MSG_DEBUG) == TRUE, func() { args = append(args, m.OptionSimple(LOG_TRACEID)...) }) kit.If(m.Option(MSG_USERPOD), func(p string) { args = append(args, SPACE, p) }) return m.Status(TIME, m.Time(), arg, args)