mirror of
https://github.com/cuigh/swirl
synced 2025-06-26 18:16:50 +00:00
Support restarting service
This commit is contained in:
parent
2277893dfe
commit
536dc59cc6
@ -1145,7 +1145,7 @@ var Swirl;
|
|||||||
<p class="card-header-title is-paddingless">${this.opts.title}</p>
|
<p class="card-header-title is-paddingless">${this.opts.title}</p>
|
||||||
<a data-action="remove-chart" class="card-header-icon" aria-label="remove chart">
|
<a data-action="remove-chart" class="card-header-icon" aria-label="remove chart">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<i class="fas fa-times has-text-danger" aria-hidden="true"></i>
|
<i class="fas fa-trash has-text-danger" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</header>
|
</header>
|
||||||
@ -2339,7 +2339,7 @@ var Swirl;
|
|||||||
<td>
|
<td>
|
||||||
<a class="button is-small is-outlined is-danger" data-action="delete-${this.name}">
|
<a class="button is-small is-outlined is-danger" data-action="delete-${this.name}">
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
@ -2416,7 +2416,8 @@ var Swirl;
|
|||||||
this.table = new Table("#table-items");
|
this.table = new Table("#table-items");
|
||||||
this.table.on("delete-service", this.deleteService.bind(this))
|
this.table.on("delete-service", this.deleteService.bind(this))
|
||||||
.on("scale-service", this.scaleService.bind(this))
|
.on("scale-service", this.scaleService.bind(this))
|
||||||
.on("rollback-service", this.rollbackService.bind(this));
|
.on("rollback-service", this.rollbackService.bind(this))
|
||||||
|
.on("restart-service", this.restartService.bind(this));
|
||||||
}
|
}
|
||||||
deleteService(e) {
|
deleteService(e) {
|
||||||
let $tr = $(e.target).closest("tr");
|
let $tr = $(e.target).closest("tr");
|
||||||
@ -2429,23 +2430,30 @@ var Swirl;
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
scaleService(e) {
|
scaleService(e) {
|
||||||
let $btn = $(e.target).closest("button");
|
let $target = $(e.target), $tr = $target.closest("tr");
|
||||||
let $tr = $btn.closest("tr");
|
|
||||||
let data = {
|
let data = {
|
||||||
name: $tr.find("td:eq(0)").text().trim(),
|
name: $tr.find("td:eq(0)").text().trim(),
|
||||||
count: $btn.data("replicas"),
|
count: $target.data("replicas"),
|
||||||
};
|
};
|
||||||
Modal.confirm(`<input name="count" value="${data.count}" class="input" placeholder="Replicas">`, "Scale service", (dlg, e) => {
|
Modal.confirm(`<input name="count" value="${data.count}" class="input" placeholder="Replicas">`, "Scale service", dlg => {
|
||||||
data.count = dlg.find("input[name=count]").val();
|
data.count = dlg.find("input[name=count]").val();
|
||||||
$ajax.post(`${data.name}/scale`, data).trigger(e.target).encoder("form").json(() => {
|
$ajax.post(`${data.name}/scale`, data).encoder("form").json(() => {
|
||||||
location.reload();
|
location.reload();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
rollbackService(e) {
|
rollbackService(e) {
|
||||||
let $btn = $(e.target).closest("button"), $tr = $btn.closest("tr"), name = $tr.find("td:eq(0)").text().trim();
|
let $tr = $(e.target).closest("tr"), name = $tr.find("td:eq(0)").text().trim();
|
||||||
Modal.confirm(`Are you sure to rollback service: <strong>${name}</strong>?`, "Rollback service", (dlg, e) => {
|
Modal.confirm(`Are you sure to rollback service: <strong>${name}</strong>?`, "Rollback service", dlg => {
|
||||||
$ajax.post(`${name}/rollback`, { name: name }).trigger(e.target).encoder("form").json(() => {
|
$ajax.post(`${name}/rollback`, { name: name }).encoder("form").json(() => {
|
||||||
|
dlg.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
restartService(e) {
|
||||||
|
let $tr = $(e.target).closest("tr"), name = $tr.find("td:eq(0)").text().trim();
|
||||||
|
Modal.confirm(`Are you sure to restart service: <strong>${name}</strong>?`, "Restart service", dlg => {
|
||||||
|
$ajax.post(`${name}/restart`, { name: name }).encoder("form").json(() => {
|
||||||
dlg.close();
|
dlg.close();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -31,7 +31,7 @@ namespace Swirl.Core {
|
|||||||
<p class="card-header-title is-paddingless">${this.opts.title}</p>
|
<p class="card-header-title is-paddingless">${this.opts.title}</p>
|
||||||
<a data-action="remove-chart" class="card-header-icon" aria-label="remove chart">
|
<a data-action="remove-chart" class="card-header-icon" aria-label="remove chart">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<i class="fas fa-times has-text-danger" aria-hidden="true"></i>
|
<i class="fas fa-trash has-text-danger" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@ -176,7 +176,7 @@ namespace Swirl.Service {
|
|||||||
<td>
|
<td>
|
||||||
<a class="button is-small is-outlined is-danger" data-action="delete-${this.name}">
|
<a class="button is-small is-outlined is-danger" data-action="delete-${this.name}">
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@ -13,7 +13,8 @@ namespace Swirl.Service {
|
|||||||
// bind events
|
// bind events
|
||||||
this.table.on("delete-service", this.deleteService.bind(this))
|
this.table.on("delete-service", this.deleteService.bind(this))
|
||||||
.on("scale-service", this.scaleService.bind(this))
|
.on("scale-service", this.scaleService.bind(this))
|
||||||
.on("rollback-service", this.rollbackService.bind(this));
|
.on("rollback-service", this.rollbackService.bind(this))
|
||||||
|
.on("restart-service", this.restartService.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
private deleteService(e: JQueryEventObject) {
|
private deleteService(e: JQueryEventObject) {
|
||||||
@ -28,26 +29,35 @@ namespace Swirl.Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private scaleService(e: JQueryEventObject) {
|
private scaleService(e: JQueryEventObject) {
|
||||||
let $btn = $(e.target).closest("button");
|
let $target = $(e.target),
|
||||||
let $tr = $btn.closest("tr");
|
$tr = $target.closest("tr");
|
||||||
let data = {
|
let data = {
|
||||||
name: $tr.find("td:eq(0)").text().trim(),
|
name: $tr.find("td:eq(0)").text().trim(),
|
||||||
count: $btn.data("replicas"),
|
count: $target.data("replicas"),
|
||||||
};
|
};
|
||||||
Modal.confirm(`<input name="count" value="${data.count}" class="input" placeholder="Replicas">`, "Scale service", (dlg, e) => {
|
Modal.confirm(`<input name="count" value="${data.count}" class="input" placeholder="Replicas">`, "Scale service", dlg => {
|
||||||
data.count = dlg.find("input[name=count]").val();
|
data.count = dlg.find("input[name=count]").val();
|
||||||
$ajax.post(`${data.name}/scale`, data).trigger(e.target).encoder("form").json<AjaxResult>(() => {
|
$ajax.post(`${data.name}/scale`, data).encoder("form").json<AjaxResult>(() => {
|
||||||
location.reload();
|
location.reload();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private rollbackService(e: JQueryEventObject) {
|
private rollbackService(e: JQueryEventObject) {
|
||||||
let $btn = $(e.target).closest("button"),
|
let $tr = $(e.target).closest("tr"),
|
||||||
$tr = $btn.closest("tr"),
|
|
||||||
name = $tr.find("td:eq(0)").text().trim();
|
name = $tr.find("td:eq(0)").text().trim();
|
||||||
Modal.confirm(`Are you sure to rollback service: <strong>${name}</strong>?`, "Rollback service", (dlg, e) => {
|
Modal.confirm(`Are you sure to rollback service: <strong>${name}</strong>?`, "Rollback service", dlg => {
|
||||||
$ajax.post(`${name}/rollback`, {name: name}).trigger(e.target).encoder("form").json<AjaxResult>(() => {
|
$ajax.post(`${name}/rollback`, {name: name}).encoder("form").json<AjaxResult>(() => {
|
||||||
|
dlg.close();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private restartService(e: JQueryEventObject) {
|
||||||
|
let $tr = $(e.target).closest("tr"),
|
||||||
|
name = $tr.find("td:eq(0)").text().trim();
|
||||||
|
Modal.confirm(`Are you sure to restart service: <strong>${name}</strong>?`, "Restart service", dlg => {
|
||||||
|
$ajax.post(`${name}/restart`, {name: name}).encoder("form").json<AjaxResult>(() => {
|
||||||
dlg.close();
|
dlg.close();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
@ -340,19 +340,15 @@ func ServiceScale(name string, version, count uint64) error {
|
|||||||
|
|
||||||
spec := service.Spec
|
spec := service.Spec
|
||||||
if spec.Mode.Replicated == nil {
|
if spec.Mode.Replicated == nil {
|
||||||
return errors.New("the mode of service isn't replicated")
|
return errors.New("scale can only be used with replicated mode")
|
||||||
}
|
}
|
||||||
spec.Mode.Replicated.Replicas = &count
|
spec.Mode.Replicated.Replicas = &count
|
||||||
|
|
||||||
options := types.ServiceUpdateOptions{
|
|
||||||
RegistryAuthFrom: types.RegistryAuthFromSpec,
|
|
||||||
QueryRegistry: false,
|
|
||||||
}
|
|
||||||
ver := service.Version
|
ver := service.Version
|
||||||
if version > 0 {
|
if version > 0 {
|
||||||
ver = swarm.Version{Index: version}
|
ver = swarm.Version{Index: version}
|
||||||
}
|
}
|
||||||
resp, err := cli.ServiceUpdate(context.Background(), name, ver, spec, options)
|
resp, err := cli.ServiceUpdate(context.Background(), name, ver, spec, types.ServiceUpdateOptions{})
|
||||||
if err == nil && len(resp.Warnings) > 0 {
|
if err == nil && len(resp.Warnings) > 0 {
|
||||||
mgr.Logger().Warnf("service %s was scaled but got warnings: %v", name, resp.Warnings)
|
mgr.Logger().Warnf("service %s was scaled but got warnings: %v", name, resp.Warnings)
|
||||||
}
|
}
|
||||||
@ -734,20 +730,30 @@ func ServiceRollback(name string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if service.PreviousSpec == nil {
|
|
||||||
return errors.New("can't rollback service, previous spec is not exists")
|
|
||||||
}
|
|
||||||
|
|
||||||
spec := *service.PreviousSpec
|
|
||||||
options := types.ServiceUpdateOptions{
|
options := types.ServiceUpdateOptions{
|
||||||
RegistryAuthFrom: types.RegistryAuthFromPreviousSpec,
|
Rollback: "previous",
|
||||||
QueryRegistry: false,
|
|
||||||
Rollback: "previous",
|
|
||||||
}
|
}
|
||||||
resp, err := cli.ServiceUpdate(context.Background(), name, service.Version, spec, options)
|
resp, err := cli.ServiceUpdate(context.Background(), name, service.Version, service.Spec, options)
|
||||||
if err == nil && len(resp.Warnings) > 0 {
|
if err == nil && len(resp.Warnings) > 0 {
|
||||||
mgr.Logger().Warnf("service %s was rollbacked but got warnings: %v", name, resp.Warnings)
|
mgr.Logger().Warnf("service %s was rollbacked but got warnings: %v", name, resp.Warnings)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServiceRestart force to refresh a service.
|
||||||
|
func ServiceRestart(name string) error {
|
||||||
|
return mgr.Do(func(ctx context.Context, cli *client.Client) (err error) {
|
||||||
|
service, _, err := cli.ServiceInspectWithRaw(ctx, name, types.ServiceInspectOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
service.Spec.TaskTemplate.ForceUpdate++
|
||||||
|
resp, err := cli.ServiceUpdate(context.Background(), name, service.Version, service.Spec, types.ServiceUpdateOptions{})
|
||||||
|
if err == nil && len(resp.Warnings) > 0 {
|
||||||
|
mgr.Logger().Warnf("service %s was restarted but got warnings: %v", name, resp.Warnings)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ button.return: Return
|
|||||||
button.leave: Leave
|
button.leave: Leave
|
||||||
button.scale: Scale
|
button.scale: Scale
|
||||||
button.rollback: Rollback
|
button.rollback: Rollback
|
||||||
|
button.restart: Restart
|
||||||
button.previous: Previous
|
button.previous: Previous
|
||||||
button.next: Next
|
button.next: Next
|
||||||
button.import: Import
|
button.import: Import
|
||||||
@ -71,7 +72,7 @@ menu.stack.task: Tasks
|
|||||||
menu.stack.archive: Archives
|
menu.stack.archive: Archives
|
||||||
menu.task: Tasks
|
menu.task: Tasks
|
||||||
menu.secret: Secrets
|
menu.secret: Secrets
|
||||||
menu.config: Config
|
menu.config: Configs
|
||||||
menu.system: System
|
menu.system: System
|
||||||
menu.role: Roles
|
menu.role: Roles
|
||||||
menu.user: Users
|
menu.user: Users
|
||||||
|
|||||||
@ -20,6 +20,7 @@ button.return: 返回
|
|||||||
button.leave: 离开
|
button.leave: 离开
|
||||||
button.scale: 调整
|
button.scale: 调整
|
||||||
button.rollback: 回退
|
button.rollback: 回退
|
||||||
|
button.restart: 重启
|
||||||
button.previous: 前一页
|
button.previous: 前一页
|
||||||
button.next: 后一页
|
button.next: 后一页
|
||||||
button.import: 导入
|
button.import: 导入
|
||||||
|
|||||||
@ -24,6 +24,7 @@ type ServiceController struct {
|
|||||||
Delete web.HandlerFunc `path:"/:name/delete" method:"post" name:"service.delete" authorize:"!" perm:"write,service,name"`
|
Delete web.HandlerFunc `path:"/:name/delete" method:"post" name:"service.delete" authorize:"!" perm:"write,service,name"`
|
||||||
Scale web.HandlerFunc `path:"/:name/scale" method:"post" name:"service.scale" authorize:"!" perm:"write,service,name"`
|
Scale web.HandlerFunc `path:"/:name/scale" method:"post" name:"service.scale" authorize:"!" perm:"write,service,name"`
|
||||||
Rollback web.HandlerFunc `path:"/:name/rollback" method:"post" name:"service.rollback" authorize:"!" perm:"write,service,name"`
|
Rollback web.HandlerFunc `path:"/:name/rollback" method:"post" name:"service.rollback" authorize:"!" perm:"write,service,name"`
|
||||||
|
Restart web.HandlerFunc `path:"/:name/restart" method:"post" name:"service.restart" authorize:"!" perm:"write,service,name"`
|
||||||
New web.HandlerFunc `path:"/new" name:"service.new" authorize:"!" desc:"new service page"`
|
New web.HandlerFunc `path:"/new" name:"service.new" authorize:"!" desc:"new service page"`
|
||||||
Create web.HandlerFunc `path:"/new" method:"post" name:"service.create" authorize:"!" desc:"create service"`
|
Create web.HandlerFunc `path:"/new" method:"post" name:"service.create" authorize:"!" desc:"create service"`
|
||||||
Edit web.HandlerFunc `path:"/:name/edit" name:"service.edit" authorize:"!" perm:"write,service,name"`
|
Edit web.HandlerFunc `path:"/:name/edit" name:"service.edit" authorize:"!" perm:"write,service,name"`
|
||||||
@ -47,6 +48,7 @@ func Service() (c *ServiceController) {
|
|||||||
Update: serviceUpdate,
|
Update: serviceUpdate,
|
||||||
Scale: serviceScale,
|
Scale: serviceScale,
|
||||||
Rollback: serviceRollback,
|
Rollback: serviceRollback,
|
||||||
|
Restart: serviceRestart,
|
||||||
PermEdit: servicePermEdit,
|
PermEdit: servicePermEdit,
|
||||||
PermUpdate: permUpdate("service", "name"),
|
PermUpdate: permUpdate("service", "name"),
|
||||||
Stats: serviceStats,
|
Stats: serviceStats,
|
||||||
@ -271,6 +273,15 @@ func serviceRollback(ctx web.Context) error {
|
|||||||
return ajaxResult(ctx, err)
|
return ajaxResult(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func serviceRestart(ctx web.Context) error {
|
||||||
|
name := ctx.F("name")
|
||||||
|
err := docker.ServiceRestart(name)
|
||||||
|
if err == nil {
|
||||||
|
biz.Event.CreateService(model.EventActionRestart, name, ctx.User())
|
||||||
|
}
|
||||||
|
return ajaxResult(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
func servicePermEdit(ctx web.Context) error {
|
func servicePermEdit(ctx web.Context) error {
|
||||||
name := ctx.P("name")
|
name := ctx.P("name")
|
||||||
m := newModel(ctx).Set("Name", name)
|
m := newModel(ctx).Set("Name", name)
|
||||||
|
|||||||
@ -36,6 +36,7 @@ const (
|
|||||||
EventActionUpdate EventAction = "Update"
|
EventActionUpdate EventAction = "Update"
|
||||||
EventActionScale EventAction = "Scale"
|
EventActionScale EventAction = "Scale"
|
||||||
EventActionRollback EventAction = "Rollback"
|
EventActionRollback EventAction = "Rollback"
|
||||||
|
EventActionRestart EventAction = "Restart"
|
||||||
EventActionDisconnect EventAction = "Disconnect"
|
EventActionDisconnect EventAction = "Disconnect"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -261,7 +261,7 @@
|
|||||||
<td>
|
<td>
|
||||||
<a class="button is-small is-outlined is-danger" data-action="delete-secret">
|
<a class="button is-small is-outlined is-danger" data-action="delete-secret">
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
@ -301,7 +301,7 @@
|
|||||||
<td>
|
<td>
|
||||||
<a class="button is-small is-outlined is-danger" data-action="delete-config">
|
<a class="button is-small is-outlined is-danger" data-action="delete-config">
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@ -40,7 +40,7 @@
|
|||||||
<!-- Right side -->
|
<!-- Right side -->
|
||||||
<div class="level-right">
|
<div class="level-right">
|
||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<button id="btn-delete" class="button is-danger"><span class="icon"><i class="fas fa-times"></i></span><span>{{ i18n("button.delete") }}</span></button>
|
<button id="btn-delete" class="button is-danger"><span class="icon"><i class="fas fa-trash"></i></span><span>{{ i18n("button.delete") }}</span></button>
|
||||||
</p>
|
</p>
|
||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<a href="new" class="button is-success"><span class="icon"><i class="fas fa-plus"></i></span><span>{{ i18n("button.new") }}</span></a>
|
<a href="new" class="button is-success"><span class="icon"><i class="fas fa-plus"></i></span><span>{{ i18n("button.new") }}</span></a>
|
||||||
|
|||||||
@ -54,7 +54,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</p>
|
</p>
|
||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<button id="btn-delete" class="button is-danger"><span class="icon"><i class="fas fa-times"></i></span><span>{{ i18n("button.delete") }}</span></button>
|
<button id="btn-delete" class="button is-danger"><span class="icon"><i class="fas fa-trash"></i></span><span>{{ i18n("button.delete") }}</span></button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@ -41,7 +41,7 @@
|
|||||||
<!-- Right side -->
|
<!-- Right side -->
|
||||||
<div class="level-right">
|
<div class="level-right">
|
||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<button id="btn-delete" class="button is-danger"><span class="icon"><i class="fas fa-times"></i></span><span>{{ i18n("button.delete") }}</span></button>
|
<button id="btn-delete" class="button is-danger"><span class="icon"><i class="fas fa-trash"></i></span><span>{{ i18n("button.delete") }}</span></button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@ -40,7 +40,7 @@
|
|||||||
<!-- Right side -->
|
<!-- Right side -->
|
||||||
<div class="level-right">
|
<div class="level-right">
|
||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<button id="btn-delete" class="button is-danger"><span class="icon"><i class="fas fa-times"></i></span><span>{{ i18n("button.delete") }}</span></button>
|
<button id="btn-delete" class="button is-danger"><span class="icon"><i class="fas fa-trash"></i></span><span>{{ i18n("button.delete") }}</span></button>
|
||||||
</p>
|
</p>
|
||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<a href="new" class="button is-success"><span class="icon"><i class="fas fa-plus"></i></span><span>{{ i18n("button.new") }}</span></a>
|
<a href="new" class="button is-success"><span class="icon"><i class="fas fa-plus"></i></span><span>{{ i18n("button.new") }}</span></a>
|
||||||
|
|||||||
@ -44,7 +44,7 @@
|
|||||||
<th>{{ i18n("field.image") }}</th>
|
<th>{{ i18n("field.image") }}</th>
|
||||||
<th width="145">Mode</th>
|
<th width="145">Mode</th>
|
||||||
<th>{{ i18n("field.updated-at") }}</th>
|
<th>{{ i18n("field.updated-at") }}</th>
|
||||||
<th width="140">{{ i18n("field.action") }}</th>
|
<th width="190">{{ i18n("field.action") }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -60,22 +60,28 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>{{time(.UpdatedAt)}}{{ if .UpdateStatus }}<span class="icon {{ if .UpdateStatus == "completed" }}has-text-success{{ else if .UpdateStatus == "updating" }}has-text-warning{{ else }}has-text-danger{{ end }} tooltip" data-tooltip="{{.UpdateStatus}}"><i class="fas fa-circle"></i></span>{{ end }}</td>
|
<td>{{time(.UpdatedAt)}}{{ if .UpdateStatus }}<span class="icon {{ if .UpdateStatus == "completed" }}has-text-success{{ else if .UpdateStatus == "updating" }}has-text-warning{{ else }}has-text-danger{{ end }} tooltip" data-tooltip="{{.UpdateStatus}}"><i class="fas fa-circle"></i></span>{{ end }}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{.Name}}/edit" class="button is-small is-dark is-outlined tooltip is-tooltip-bottom" data-tooltip="{{ i18n("button.edit") }}">
|
<a href="{{.Name}}/edit" class="button is-small is-dark is-outlined">{{ i18n("button.edit") }}</a>
|
||||||
<span class="icon"><i class="fas fa-edit"></i></span>
|
<button class="button is-small is-danger is-outlined" data-action="delete-service">{{ i18n("button.delete") }}</button>
|
||||||
</a>
|
<div class="dropdown is-hoverable is-right">
|
||||||
{{if .Mode == "replicated"}}
|
<div class="dropdown-trigger">
|
||||||
<button type="button" class="button is-small is-info is-outlined tooltip is-tooltip-bottom" data-tooltip="{{ i18n("button.scale") }}" data-action="scale-service" data-replicas="{{.Replicas}}">
|
<button class="button is-small" aria-haspopup="true" aria-controls="dropdown-menu-{{ .Name }}">
|
||||||
<span class="icon"><i class="fas fa-arrows-alt"></i></span>
|
<span>More</span>
|
||||||
</button>
|
<span class="icon is-small">
|
||||||
{{end}}
|
<i class="fas fa-angle-down" aria-hidden="true"></i>
|
||||||
{{if .Rollback }}
|
{*<i class="fas fa-ellipsis-v" aria-hidden="true"></i>*}
|
||||||
<button type="button" class="button is-small is-info is-outlined tooltip is-tooltip-bottom" data-tooltip="{{ i18n("button.rollback") }}" data-action="rollback-service">
|
</span>
|
||||||
<span class="icon"><i class="fas fa-history"></i></span>
|
</button>
|
||||||
</button>
|
</div>
|
||||||
{{end}}
|
<div class="dropdown-menu" id="dropdown-menu-{{ .Name }}" role="menu">
|
||||||
<button class="button is-small is-danger is-outlined tooltip is-tooltip-bottom" data-tooltip="{{ i18n("button.delete") }}" data-action="delete-service">
|
<div class="dropdown-content">
|
||||||
<span class="icon"><i class="fas fa-times"></i></span>
|
{{if .Mode == "replicated" }}<a class="dropdown-item" data-action="scale-service" data-replicas="{{.Replicas}}">{{ i18n("button.scale") }}</a>{{end}}
|
||||||
</button>
|
{{if .Rollback }}<a class="dropdown-item" data-action="rollback-service">{{ i18n("button.rollback") }}</a>{{end}}
|
||||||
|
<a class="dropdown-item" data-action="restart-service">{{ i18n("button.restart") }}</a>
|
||||||
|
{*<a class="dropdown-item has-text-danger" data-action="delete-service">{{ i18n("button.delete") }}</a>*}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
@ -59,7 +59,7 @@
|
|||||||
<span class="icon"><i class="fas fa-edit"></i></span>
|
<span class="icon"><i class="fas fa-edit"></i></span>
|
||||||
</a>
|
</a>
|
||||||
<button class="button is-small is-danger is-outlined tooltip is-tooltip-bottom" data-tooltip="{{ i18n("button.delete") }}" data-action="delete-template">
|
<button class="button is-small is-danger is-outlined tooltip is-tooltip-bottom" data-tooltip="{{ i18n("button.delete") }}" data-action="delete-template">
|
||||||
<span class="icon"><i class="fas fa-times"></i></span>
|
<span class="icon"><i class="fas fa-trash"></i></span>
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">{{ i18n("field.name") }}</label>
|
<label class="label">{{ i18n("field.name") }}</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input name="name" value="{{ .Chart.Name }}" class="input" placeholder="lower-case letters and underline only" data-v-rule="native;regex" data-v-arg-regex="[a-z_]+" data-v-msg-regex="Only lower-case letters and underline are allowed." required{{if .Chart.Name}} readonly{{ end }}>
|
<input name="name" value="{{ .Chart.Name }}" class="input" placeholder="Only lower-case letters and underscores are allowed" data-v-rule="native;regex" data-v-arg-regex="[a-z_]+" data-v-msg-regex="Only lower-case letters and underline are allowed." required{{if .Chart.Name}} readonly{{ end }}>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
@ -97,7 +97,7 @@
|
|||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Query expression</label>
|
<label class="label">Query expression</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input name="query" value="{{ .Chart.Query }}" class="input" placeholder="Prometheus query expression" data-v-rule="native" required>
|
<input name="query" value="{{ .Chart.Query }}" class="input" placeholder="Prometheus query expression, for service dashboard, you can use '${service}' variable" data-v-rule="native" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
|||||||
@ -40,10 +40,10 @@
|
|||||||
<!-- Right side -->
|
<!-- Right side -->
|
||||||
<div class="level-right">
|
<div class="level-right">
|
||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<button id="btn-delete" class="button is-danger"><span class="icon"><i class="fas fa-times"></i></span><span>{{ i18n("button.delete") }}</span></button>
|
<button id="btn-delete" class="button is-danger"><span class="icon"><i class="fas fa-trash"></i></span><span>{{ i18n("button.delete") }}</span></button>
|
||||||
</p>
|
</p>
|
||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<button id="btn-prune" class="button is-warning"><span class="icon"><i class="fas fa-times-circle"></i></span><span>{{ i18n("button.prune") }}</span></button>
|
<button id="btn-prune" class="button is-warning"><span class="icon"><i class="fas fa-trash-alt"></i></span><span>{{ i18n("button.prune") }}</span></button>
|
||||||
</p>
|
</p>
|
||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<a class="button is-success" href="new"><span class="icon"><i class="fas fa-plus"></i></span><span>{{ i18n("button.new") }}</span></a>
|
<a class="button is-success" href="new"><span class="icon"><i class="fas fa-plus"></i></span><span>{{ i18n("button.new") }}</span></a>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user