mirror of
https://github.com/cuigh/swirl
synced 2024-12-28 14:51:57 +00:00
Add support for service rollback
This commit is contained in:
parent
39f4f897ab
commit
ac5184037a
@ -1756,7 +1756,9 @@ var Swirl;
|
||||
class ListPage {
|
||||
constructor() {
|
||||
this.table = new Table("#table-items");
|
||||
this.table.on("delete-service", this.deleteService.bind(this)).on("scale-service", this.scaleService.bind(this));
|
||||
this.table.on("delete-service", this.deleteService.bind(this))
|
||||
.on("scale-service", this.scaleService.bind(this))
|
||||
.on("rollback-service", this.rollbackService.bind(this));
|
||||
$("#btn-delete").click(this.deleteServices.bind(this));
|
||||
}
|
||||
deleteService(e) {
|
||||
@ -1796,6 +1798,14 @@ var Swirl;
|
||||
});
|
||||
});
|
||||
}
|
||||
rollbackService(e) {
|
||||
let $btn = $(e.target).closest("button"), $tr = $btn.closest("tr"), name = $tr.find("td:eq(1)").text().trim();
|
||||
Modal.confirm(`Are you sure to rollback service: <strong>${name}</strong>?`, "Rollback service", (dlg, e) => {
|
||||
$ajax.post("rollback", { name: name }).trigger(e.target).encoder("form").json(() => {
|
||||
dlg.close();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Service.ListPage = ListPage;
|
||||
})(Service = Swirl.Service || (Swirl.Service = {}));
|
||||
|
File diff suppressed because one or more lines are too long
@ -11,7 +11,9 @@ namespace Swirl.Service {
|
||||
this.table = new Table("#table-items");
|
||||
|
||||
// bind events
|
||||
this.table.on("delete-service", this.deleteService.bind(this)).on("scale-service", this.scaleService.bind(this));
|
||||
this.table.on("delete-service", this.deleteService.bind(this))
|
||||
.on("scale-service", this.scaleService.bind(this))
|
||||
.on("rollback-service", this.rollbackService.bind(this));
|
||||
$("#btn-delete").click(this.deleteServices.bind(this));
|
||||
}
|
||||
|
||||
@ -19,7 +21,7 @@ namespace Swirl.Service {
|
||||
let $tr = $(e.target).closest("tr");
|
||||
let name = $tr.find("td:eq(1)").text().trim();
|
||||
Modal.confirm(`Are you sure to remove service: <strong>${name}</strong>?`, "Delete service", (dlg, e) => {
|
||||
$ajax.post("delete", { names: name }).trigger(e.target).encoder("form").json<AjaxResult>(() => {
|
||||
$ajax.post("delete", {names: name}).trigger(e.target).encoder("form").json<AjaxResult>(() => {
|
||||
$tr.remove();
|
||||
dlg.close();
|
||||
})
|
||||
@ -34,7 +36,7 @@ namespace Swirl.Service {
|
||||
}
|
||||
|
||||
Modal.confirm(`Are you sure to remove ${names.length} services?`, "Delete services", (dlg, e) => {
|
||||
$ajax.post("delete", { names: names.join(",") }).trigger(e.target).encoder("form").json<AjaxResult>(() => {
|
||||
$ajax.post("delete", {names: names.join(",")}).trigger(e.target).encoder("form").json<AjaxResult>(() => {
|
||||
this.table.selectedRows().remove();
|
||||
dlg.close();
|
||||
})
|
||||
@ -55,5 +57,16 @@ namespace Swirl.Service {
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
private rollbackService(e: JQueryEventObject) {
|
||||
let $btn = $(e.target).closest("button"),
|
||||
$tr = $btn.closest("tr"),
|
||||
name = $tr.find("td:eq(1)").text().trim();
|
||||
Modal.confirm(`Are you sure to rollback service: <strong>${name}</strong>?`, "Rollback service", (dlg, e) => {
|
||||
$ajax.post("rollback", {name: name}).trigger(e.target).encoder("form").json<AjaxResult>(() => {
|
||||
dlg.close();
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -697,3 +697,28 @@ func ServiceCommand(name string) (cmd string, err error) {
|
||||
cmd = b.String()
|
||||
return
|
||||
}
|
||||
|
||||
// ServiceRollback rollbacks a service.
|
||||
func ServiceRollback(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
|
||||
}
|
||||
|
||||
if service.PreviousSpec == nil {
|
||||
return errors.New("can't rollback service, previous spec is not exists")
|
||||
}
|
||||
|
||||
spec := *service.PreviousSpec
|
||||
options := types.ServiceUpdateOptions{
|
||||
RegistryAuthFrom: types.RegistryAuthFromPreviousSpec,
|
||||
QueryRegistry: false,
|
||||
}
|
||||
resp, err := cli.ServiceUpdate(context.Background(), name, service.Version, spec, options)
|
||||
if err == nil && len(resp.Warnings) > 0 {
|
||||
mgr.Logger().Warnf("service %s was rollbacked but got warnings: %v", name, resp.Warnings)
|
||||
}
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ button.update: Update
|
||||
button.return: Return
|
||||
button.leave: Leave
|
||||
button.scale: Scale
|
||||
button.rollback: Rollback
|
||||
button.previous: Previous
|
||||
button.next: Next
|
||||
|
||||
|
@ -18,6 +18,7 @@ button.update: 更新
|
||||
button.return: 返回
|
||||
button.leave: 离开
|
||||
button.scale: 调整
|
||||
button.rollback: 回退
|
||||
button.previous: 前一页
|
||||
button.next: 后一页
|
||||
|
||||
|
@ -17,31 +17,33 @@ import (
|
||||
|
||||
// ServiceController is a controller of docker service
|
||||
type ServiceController struct {
|
||||
List web.HandlerFunc `path:"/" name:"service.list" authorize:"!" desc:"service list page"`
|
||||
Detail web.HandlerFunc `path:"/:name/detail" name:"service.detail" authorize:"!" desc:"service detail page"`
|
||||
Raw web.HandlerFunc `path:"/:name/raw" name:"service.raw" authorize:"!" desc:"service raw page"`
|
||||
Logs web.HandlerFunc `path:"/:name/logs" name:"service.logs" authorize:"!" desc:"service logs page"`
|
||||
Delete web.HandlerFunc `path:"/delete" method:"post" name:"service.delete" authorize:"!" desc:"delete service"`
|
||||
Scale web.HandlerFunc `path:"/scale" method:"post" name:"service.scale" authorize:"!" desc:"scale service"`
|
||||
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"`
|
||||
Edit web.HandlerFunc `path:"/:name/edit" name:"service.edit" authorize:"!" desc:"service edit page"`
|
||||
Update web.HandlerFunc `path:"/:name/edit" method:"post" name:"service.update" authorize:"!" desc:"update service"`
|
||||
List web.HandlerFunc `path:"/" name:"service.list" authorize:"!" desc:"service list page"`
|
||||
Detail web.HandlerFunc `path:"/:name/detail" name:"service.detail" authorize:"!" desc:"service detail page"`
|
||||
Raw web.HandlerFunc `path:"/:name/raw" name:"service.raw" authorize:"!" desc:"service raw page"`
|
||||
Logs web.HandlerFunc `path:"/:name/logs" name:"service.logs" authorize:"!" desc:"service logs page"`
|
||||
Delete web.HandlerFunc `path:"/delete" method:"post" name:"service.delete" authorize:"!" desc:"delete service"`
|
||||
Scale web.HandlerFunc `path:"/scale" method:"post" name:"service.scale" authorize:"!" desc:"scale service"`
|
||||
Rollback web.HandlerFunc `path:"/rollback" method:"post" name:"service.rollback" authorize:"!" desc:"rollback service"`
|
||||
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"`
|
||||
Edit web.HandlerFunc `path:"/:name/edit" name:"service.edit" authorize:"!" desc:"service edit page"`
|
||||
Update web.HandlerFunc `path:"/:name/edit" method:"post" name:"service.update" authorize:"!" desc:"update service"`
|
||||
}
|
||||
|
||||
// Service creates an instance of ServiceController
|
||||
func Service() (c *ServiceController) {
|
||||
return &ServiceController{
|
||||
List: serviceList,
|
||||
Detail: serviceDetail,
|
||||
Raw: serviceRaw,
|
||||
Logs: serviceLogs,
|
||||
Delete: serviceDelete,
|
||||
New: serviceNew,
|
||||
Create: serviceCreate,
|
||||
Edit: serviceEdit,
|
||||
Update: serviceUpdate,
|
||||
Scale: serviceScale,
|
||||
List: serviceList,
|
||||
Detail: serviceDetail,
|
||||
Raw: serviceRaw,
|
||||
Logs: serviceLogs,
|
||||
Delete: serviceDelete,
|
||||
New: serviceNew,
|
||||
Create: serviceCreate,
|
||||
Edit: serviceEdit,
|
||||
Update: serviceUpdate,
|
||||
Scale: serviceScale,
|
||||
Rollback: serviceRollback,
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,3 +265,12 @@ func serviceScale(ctx web.Context) error {
|
||||
}
|
||||
return ajaxResult(ctx, err)
|
||||
}
|
||||
|
||||
func serviceRollback(ctx web.Context) error {
|
||||
name := ctx.F("name")
|
||||
err := docker.ServiceRollback(name)
|
||||
if err == nil {
|
||||
biz.Event.CreateService(model.EventActionRollback, name, ctx.User())
|
||||
}
|
||||
return ajaxResult(ctx, err)
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ var Perms = []PermGroup{
|
||||
{Key: "service.delete", Text: "Delete"},
|
||||
{Key: "service.update", Text: "Update"},
|
||||
{Key: "service.scale", Text: "Scale"},
|
||||
{Key: "service.rollback", Text: "Rollback"},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -86,6 +86,7 @@ type ServiceListInfo struct {
|
||||
Actives uint64
|
||||
Replicas uint64
|
||||
UpdatedAt time.Time
|
||||
Rollback bool
|
||||
}
|
||||
|
||||
func NewServiceListInfo(service swarm.Service, actives uint64) *ServiceListInfo {
|
||||
@ -94,6 +95,7 @@ func NewServiceListInfo(service swarm.Service, actives uint64) *ServiceListInfo
|
||||
Image: normalizeImage(service.Spec.TaskTemplate.ContainerSpec.Image),
|
||||
Actives: actives,
|
||||
UpdatedAt: service.UpdatedAt.Local(),
|
||||
Rollback: service.PreviousSpec != nil,
|
||||
}
|
||||
if service.Spec.Mode.Replicated != nil && service.Spec.Mode.Replicated.Replicas != nil {
|
||||
info.Mode = "replicated"
|
||||
|
@ -38,6 +38,7 @@ const (
|
||||
EventActionDelete EventAction = "Delete"
|
||||
EventActionUpdate EventAction = "Update"
|
||||
EventActionScale EventAction = "Scale"
|
||||
EventActionRollback EventAction = "Rollback"
|
||||
EventActionDisconnect EventAction = "Disconnect"
|
||||
)
|
||||
|
||||
|
@ -48,7 +48,7 @@
|
||||
<th>{{ i18n("field.image") }}</th>
|
||||
<th width="145">Mode</th>
|
||||
<th>{{ i18n("field.updated-at") }}</th>
|
||||
<th width="110">{{ i18n("field.action") }}</th>
|
||||
<th width="140">{{ i18n("field.action") }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -73,6 +73,11 @@
|
||||
<span class="icon"><i class="fa fa-arrows"></i></span>
|
||||
</button>
|
||||
{{end}}
|
||||
{{if .Rollback }}
|
||||
<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 class="icon"><i class="fa fa-history"></i></span>
|
||||
</button>
|
||||
{{end}}
|
||||
<button class="button is-small is-danger is-outlined tooltip is-tooltip-bottom" data-tooltip="{{ i18n("button.delete") }}" data-action="delete-service">
|
||||
<span class="icon"><i class="fa fa-remove"></i></span>
|
||||
</button>
|
||||
|
Loading…
Reference in New Issue
Block a user