{{ .Raw }}
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") }}
+
- TASK
-
-
- A task is a container running on a swarm. It is the atomic scheduling unit of swarm.
-
-
{{ 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) }} | +
{{ .Raw }}