diff --git a/biz/docker/task.go b/biz/docker/task.go index 443e2a4..44c4ef3 100644 --- a/biz/docker/task.go +++ b/biz/docker/task.go @@ -2,10 +2,12 @@ package docker import ( "context" + "io" + "math" "sort" - "io" - + "github.com/cuigh/auxo/util/choose" + "github.com/cuigh/swirl/misc" "github.com/cuigh/swirl/model" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" @@ -14,35 +16,50 @@ import ( ) // TaskList return all running tasks of a service or a node. -func TaskList(service, node string) (infos []*model.TaskInfo, err error) { +func TaskList(args *model.TaskListArgs) (infos []*model.TaskInfo, totalCount int, err error) { err = mgr.Do(func(ctx context.Context, cli *client.Client) (err error) { var ( tasks []swarm.Task + opts = types.TaskListOptions{ + Filters: filters.NewArgs(), + } ) - opts := types.TaskListOptions{ - Filters: filters.NewArgs(), + if args.PageIndex < 1 { + args.PageIndex = 1 } - if service != "" { - opts.Filters.Add("service", service) + if args.PageSize < 1 { + args.PageSize = math.MaxInt32 } - if node != "" { - opts.Filters.Add("node", node) + if args.Service != "" { + opts.Filters.Add("service", args.Service) } + if args.Node != "" { + opts.Filters.Add("node", args.Node) + } + if args.Name != "" { + opts.Filters.Add("name", args.Name) + } + if args.State != "" { + opts.Filters.Add("desired-state", args.State) + } + tasks, err = cli.TaskList(ctx, opts) - if err == nil && len(tasks) > 0 { + totalCount = len(tasks) + if err == nil && totalCount > 0 { sort.Slice(tasks, func(i, j int) bool { return tasks[i].UpdatedAt.After(tasks[j].UpdatedAt) }) + start, end := misc.Page(totalCount, args.PageIndex, args.PageSize) + tasks = tasks[start:end] nodes := make(map[string]string) for _, t := range tasks { if _, ok := nodes[t.NodeID]; !ok { if n, _, e := cli.NodeInspectWithRaw(ctx, t.NodeID); e == nil { - nodes[t.NodeID] = n.Description.Hostname + nodes[t.NodeID] = choose.String(n.Spec.Name == "", n.Description.Hostname, n.Spec.Name) } else { nodes[t.NodeID] = "" - //mgr.Logger().Warnf("Node %s of task %s can't be load: %s", t.NodeID, t.ID, e) } } } diff --git a/config/i18n/en.yml b/config/i18n/en.yml index 2ae303c..334e473 100644 --- a/config/i18n/en.yml +++ b/config/i18n/en.yml @@ -132,6 +132,10 @@ stack.title: Stack stack.description: A stack is a logical grouping of related services that are usually deployed together and require each other to work as intended. stack.button.deploy: Deploy +# task pages +task.title: Task +task.description: A task is a container running on a swarm. It is the atomic scheduling unit of swarm. + # secret pages secret.title: Secret secret.description: Secrets are sensitive data that can be used by services. diff --git a/config/i18n/zh.yml b/config/i18n/zh.yml index 156ebef..afa4ea8 100644 --- a/config/i18n/zh.yml +++ b/config/i18n/zh.yml @@ -132,6 +132,10 @@ stack.title: 编排 stack.description: 编排是相关服务的一个逻辑分组,这些服务通常互相依赖,需要一块部署。 stack.button.deploy: 部署 +# task pages +task.title: 任务 +task.description: 任务是运行在 Swarm 集群上的一个容器,它是 Swarm 调度的原子单元。 + # secret pages secret.title: 私密配置 secret.description: 运行服务需要的敏感数据,如密钥。 diff --git a/controller/node.go b/controller/node.go index 2784a2a..403e4f3 100644 --- a/controller/node.go +++ b/controller/node.go @@ -52,7 +52,7 @@ func nodeDetail(ctx web.Context) error { return err } - tasks, err := docker.TaskList("", id) + tasks, _, err := docker.TaskList(&model.TaskListArgs{Node: id}) if err != nil { return err } diff --git a/controller/service.go b/controller/service.go index 86eae15..f690ac1 100644 --- a/controller/service.go +++ b/controller/service.go @@ -75,7 +75,7 @@ func serviceDetail(ctx web.Context) error { info.Networks = append(info.Networks, model.Network{ID: vip.NetworkID, Name: n.Name, Address: vip.Addr}) } - tasks, err := docker.TaskList(name, "") + tasks, _, err := docker.TaskList(&model.TaskListArgs{Service: name}) if err != nil { return err } diff --git a/controller/task.go b/controller/task.go index 5c8c5ea..74f1a7e 100644 --- a/controller/task.go +++ b/controller/task.go @@ -4,10 +4,12 @@ import ( "github.com/cuigh/auxo/net/web" "github.com/cuigh/swirl/biz/docker" "github.com/cuigh/swirl/misc" + "github.com/cuigh/swirl/model" ) // TaskController is a controller of swarm task type TaskController struct { + List web.HandlerFunc `path:"/" name:"task.list" authorize:"!" desc:"task list page"` Detail web.HandlerFunc `path:"/:id/detail" name:"task.detail" authorize:"!" desc:"task detail page"` Raw web.HandlerFunc `path:"/:id/raw" name:"task.raw" authorize:"!" desc:"task raw page"` } @@ -15,11 +17,34 @@ type TaskController struct { // Task creates an instance of TaskController func Task() (c *TaskController) { return &TaskController{ + List: taskList, Detail: taskDetail, Raw: taskRaw, } } +func taskList(ctx web.Context) error { + args := &model.TaskListArgs{} + err := ctx.Bind(args) + if err != nil { + return err + } + args.PageSize = model.PageSize + if args.PageIndex == 0 { + args.PageIndex = 1 + } + + tasks, totalCount, err := docker.TaskList(args) + if err != nil { + return err + } + + m := newPagerModel(ctx, totalCount, args.PageSize, args.PageIndex). + Add("Args", args). + Add("Tasks", tasks) + return ctx.Render("task/list", m) +} + func taskDetail(ctx web.Context) error { id := ctx.P("id") task, _, err := docker.TaskInspect(id) diff --git a/misc/misc.go b/misc/misc.go index 2f71225..1bd0f53 100644 --- a/misc/misc.go +++ b/misc/misc.go @@ -9,7 +9,7 @@ import ( const ( // Version is the version of Swirl - Version = "0.5.5" + Version = "0.5.6" ) const ( diff --git a/misc/perm.go b/misc/perm.go index ca27404..245a576 100644 --- a/misc/perm.go +++ b/misc/perm.go @@ -87,6 +87,7 @@ var Perms = []PermGroup{ { Name: "Task", Perms: []Perm{ + {Key: "task.list", Text: "View list"}, {Key: "task.detail", Text: "View detail"}, {Key: "task.raw", Text: "View raw"}, }, diff --git a/model/docker.go b/model/docker.go index 95d35aa..541dbb9 100644 --- a/model/docker.go +++ b/model/docker.go @@ -478,6 +478,15 @@ type ConfigUpdateInfo struct { ConfigCreateInfo } +type TaskListArgs struct { + Service string `query:"service"` + Node string `query:"node"` + Name string `query:"name"` + State string `query:"state"` + PageIndex int `query:"page"` + PageSize int `query:"size"` +} + type TaskInfo struct { swarm.Task NodeName string diff --git a/views/_layouts/default.jet b/views/_layouts/default.jet index ae5ba81..68029b7 100644 --- a/views/_layouts/default.jet +++ b/views/_layouts/default.jet @@ -39,6 +39,7 @@ {{ i18n("menu.node") }} {{ i18n("menu.network") }} {{ i18n("menu.service") }} + {{ i18n("menu.task") }} {{ i18n("menu.stack") }} {{ i18n("menu.secret") }} {{ i18n("menu.config") }} diff --git a/views/task/_base.jet b/views/task/_base.jet new file mode 100644 index 0000000..4228792 --- /dev/null +++ b/views/task/_base.jet @@ -0,0 +1,13 @@ +{{ extends "../_layouts/default" }} + +{{ block body() }} +
+
+
+

{{ i18n("task.title") }}

+

{{ i18n("task.description") }}

+
+
+
+{{ yield body_content() }} +{{ end }} diff --git a/views/task/detail.jet b/views/task/detail.jet index 43b0601..68db17f 100644 --- a/views/task/detail.jet +++ b/views/task/detail.jet @@ -1,23 +1,12 @@ -{{ extends "../_layouts/default" }} +{{ extends "_base" }} -{{ block body() }} -
-
-
-

- TASK -

-

- A task is a container running on a swarm. It is the atomic scheduling unit of swarm. -

-
-
-
+{{ block body_content() }}
@@ -26,19 +15,15 @@

{{ .Task.Name ? .Task.Name : .Task.ID }} -

+
@@ -104,6 +89,10 @@ {{ end }} + + + {{ i18n("button.return") }} + {{ end }} \ No newline at end of file diff --git a/views/task/list.jet b/views/task/list.jet new file mode 100644 index 0000000..ef8be87 --- /dev/null +++ b/views/task/list.jet @@ -0,0 +1,73 @@ +{{ extends "_base" }} +{{ import "../_modules/pager" }} + +{{ block body_content() }} +
+ + + + + + + + + + + + + + + {{range .Tasks}} + + + + + + + + + {{end}} + +
{{ i18n("field.id") }}Service{{ i18n("field.image") }}Node{{ i18n("field.state") }}{{ i18n("field.created-at") }}
{{ .ID }}{{ .ServiceID }}{{ limit(.Image, 50) }}{{ .NodeName }}{{ .Status.State }}{{ time(.CreatedAt) }}
+ {{ yield pager(info=.Pager) }} +
+{{ end }} \ No newline at end of file diff --git a/views/task/raw.jet b/views/task/raw.jet index e44c5f7..1f7d4dc 100644 --- a/views/task/raw.jet +++ b/views/task/raw.jet @@ -1,4 +1,4 @@ -{{ extends "../_layouts/default" }} +{{ extends "_base" }} {{ block style() }} @@ -9,24 +9,13 @@ {{ end }} -{{ block body() }} -
-
-
-

- TASK -

-

- A task is a container running on a swarm. It is the atomic scheduling unit of swarm. -

-
-
-
+{{ block body_content() }}
@@ -42,12 +31,8 @@ @@ -56,6 +41,10 @@
{{ .Raw }}
+ + + {{ i18n("button.return") }} + {{ end }} \ No newline at end of file