swirl/controller/service.go

349 lines
9.7 KiB
Go
Raw Normal View History

2017-09-26 12:50:09 +00:00
package controller
import (
"strconv"
"time"
2017-09-26 12:50:09 +00:00
2018-05-07 12:58:32 +00:00
"github.com/cuigh/auxo/data"
"github.com/cuigh/auxo/data/set"
2017-09-26 12:50:09 +00:00
"github.com/cuigh/auxo/errors"
"github.com/cuigh/auxo/net/web"
"github.com/cuigh/auxo/util/cast"
"github.com/cuigh/swirl/biz"
"github.com/cuigh/swirl/biz/docker"
2017-10-10 07:26:07 +00:00
"github.com/cuigh/swirl/misc"
2017-09-26 12:50:09 +00:00
"github.com/cuigh/swirl/model"
)
2017-10-11 03:26:03 +00:00
// ServiceController is a controller of docker service
2017-09-26 12:50:09 +00:00
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:"!" perm:"read,service,name"`
Raw web.HandlerFunc `path:"/:name/raw" name:"service.raw" authorize:"!" perm:"read,service,name"`
Logs web.HandlerFunc `path:"/:name/logs" name:"service.logs" authorize:"!" perm:"read,service,name"`
2018-05-07 12:58:32 +00:00
FetchLogs web.HandlerFunc `path:"/:name/fetch_logs" name:"service.fetch_logs" authorize:"?" desc:"fetch service logs"`
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"`
Rollback web.HandlerFunc `path:"/:name/rollback" method:"post" name:"service.rollback" authorize:"!" perm:"write,service,name"`
2018-04-10 03:25:55 +00:00
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"`
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"`
Update web.HandlerFunc `path:"/:name/edit" method:"post" name:"service.update" authorize:"!" perm:"write,service,name"`
PermEdit web.HandlerFunc `path:"/:name/perm" name:"service.perm.edit" authorize:"!" perm:"write,service,name"`
PermUpdate web.HandlerFunc `path:"/:name/perm" method:"post" name:"service.perm.update" authorize:"!" perm:"write,service,name"`
Stats web.HandlerFunc `path:"/:name/stats" name:"service.stats" authorize:"!" perm:"read,service,name"`
2017-09-26 12:50:09 +00:00
}
2017-10-11 03:26:03 +00:00
// Service creates an instance of ServiceController
2017-09-26 12:50:09 +00:00
func Service() (c *ServiceController) {
2017-10-11 03:26:03 +00:00
return &ServiceController{
List: serviceList,
Detail: serviceDetail,
Raw: serviceRaw,
Logs: serviceLogs,
2018-05-07 12:58:32 +00:00
FetchLogs: serviceFetchLogs,
Delete: serviceDelete,
New: serviceNew,
Create: serviceCreate,
Edit: serviceEdit,
Update: serviceUpdate,
Scale: serviceScale,
Rollback: serviceRollback,
2018-04-10 03:25:55 +00:00
Restart: serviceRestart,
PermEdit: servicePermEdit,
PermUpdate: permUpdate("service", "name"),
Stats: serviceStats,
2017-10-11 03:26:03 +00:00
}
}
2017-09-26 12:50:09 +00:00
2017-10-11 03:26:03 +00:00
func serviceList(ctx web.Context) error {
name := ctx.Q("name")
2017-10-19 06:24:38 +00:00
page := cast.ToInt(ctx.Q("page"), 1)
2017-10-11 03:26:03 +00:00
services, totalCount, err := docker.ServiceList(name, page, model.PageSize)
if err != nil {
return err
2017-09-26 12:50:09 +00:00
}
2017-10-11 03:26:03 +00:00
m := newPagerModel(ctx, totalCount, model.PageSize, page).
2017-11-08 10:36:13 +00:00
Set("Name", name).
Set("Services", services)
2017-10-11 03:26:03 +00:00
return ctx.Render("service/list", m)
}
2017-09-26 12:50:09 +00:00
2017-10-11 03:26:03 +00:00
func serviceDetail(ctx web.Context) error {
name := ctx.P("name")
service, _, err := docker.ServiceInspect(name)
if err != nil {
return err
}
2017-09-26 12:50:09 +00:00
2018-04-16 12:39:24 +00:00
// redirect if name is service id
if name != service.Spec.Name {
return ctx.Redirect("/service/" + service.Spec.Name + "/detail")
}
2017-10-11 03:26:03 +00:00
info := model.NewServiceDetailInfo(service)
for _, vip := range service.Endpoint.VirtualIPs {
n, e := docker.NetworkInspect(vip.NetworkID)
if e != nil {
return e
2017-09-26 12:50:09 +00:00
}
2017-10-11 03:26:03 +00:00
info.Networks = append(info.Networks, model.Network{ID: vip.NetworkID, Name: n.Name, Address: vip.Addr})
}
2017-09-26 12:50:09 +00:00
2017-10-19 12:40:05 +00:00
tasks, _, err := docker.TaskList(&model.TaskListArgs{Service: name})
2017-10-11 03:26:03 +00:00
if err != nil {
return err
2017-09-26 12:50:09 +00:00
}
cmd, err := docker.ServiceCommand(name)
if err != nil {
return err
}
2017-11-08 10:36:13 +00:00
m := newModel(ctx).Set("Service", info).Set("Tasks", tasks).Set("Command", cmd)
2017-10-11 03:26:03 +00:00
return ctx.Render("service/detail", m)
}
2017-09-26 12:50:09 +00:00
2017-10-11 03:26:03 +00:00
func serviceRaw(ctx web.Context) error {
name := ctx.P("name")
_, raw, err := docker.ServiceInspect(name)
if err != nil {
return err
}
2017-09-26 12:50:09 +00:00
2017-10-11 03:26:03 +00:00
j, err := misc.JSONIndent(raw)
if err != nil {
return err
2017-09-26 12:50:09 +00:00
}
2017-11-08 10:36:13 +00:00
m := newModel(ctx).Set("Service", name).Set("Raw", j)
2017-10-11 03:26:03 +00:00
return ctx.Render("service/raw", m)
}
2017-09-28 12:13:22 +00:00
2017-10-11 03:26:03 +00:00
func serviceLogs(ctx web.Context) error {
2018-05-07 12:58:32 +00:00
name := ctx.P("name")
m := newModel(ctx).Set("Service", name)
return ctx.Render("service/logs", m)
}
func serviceFetchLogs(ctx web.Context) error {
2017-10-11 03:26:03 +00:00
name := ctx.P("name")
2017-10-19 06:24:38 +00:00
line := cast.ToInt(ctx.Q("line"), 500)
timestamps := cast.ToBool(ctx.Q("timestamps"), false)
2017-10-11 03:26:03 +00:00
stdout, stderr, err := docker.ServiceLogs(name, line, timestamps)
if err != nil {
2018-05-07 12:58:32 +00:00
return ajaxResult(ctx, err)
2017-09-28 12:13:22 +00:00
}
2018-05-07 12:58:32 +00:00
return ctx.JSON(data.Map{
"stdout": stdout.String(),
"stderr": stderr.String(),
})
2017-10-11 03:26:03 +00:00
}
func serviceDelete(ctx web.Context) error {
name := ctx.P("name")
err := docker.ServiceRemove(name)
if err == nil {
biz.Event.CreateService(model.EventActionDelete, name, ctx.User())
2017-09-26 12:50:09 +00:00
}
return ajaxResult(ctx, err)
2017-10-11 03:26:03 +00:00
}
2017-09-26 12:50:09 +00:00
2017-10-11 03:26:03 +00:00
func serviceNew(ctx web.Context) error {
info := &model.ServiceInfo{}
2017-10-11 03:26:03 +00:00
tid := ctx.Q("template")
if tid != "" {
err := biz.Template.FillInfo(tid, info)
2017-10-11 03:26:03 +00:00
if err != nil {
return err
}
2017-09-26 12:50:09 +00:00
}
2017-10-11 03:26:03 +00:00
networks, err := docker.NetworkList()
if err != nil {
return err
}
secrets, _, err := docker.SecretList("", 1, 100)
if err != nil {
return err
}
configs, _, err := docker.ConfigList("", 1, 100)
if err != nil {
return err
}
registries, err := biz.Registry.List()
if err != nil {
return err
}
2017-11-09 09:16:18 +00:00
checkedNetworks := set.NewStringSet(info.Networks...)
m := newModel(ctx).Set("Service", info).Set("Registries", registries).
2017-11-08 10:36:13 +00:00
Set("Networks", networks).Set("CheckedNetworks", checkedNetworks).
Set("Secrets", secrets).Set("Configs", configs)
2017-10-11 03:26:03 +00:00
return ctx.Render("service/new", m)
}
2017-09-26 12:50:09 +00:00
2017-10-11 03:26:03 +00:00
func serviceCreate(ctx web.Context) error {
info := &model.ServiceInfo{}
err := ctx.Bind(info)
if err != nil {
return err
2017-09-26 12:50:09 +00:00
}
info.Normalize()
2017-09-26 12:50:09 +00:00
2017-10-11 03:26:03 +00:00
if info.Registry != "" {
var registry *model.Registry
registry, err = biz.Registry.Get(info.Registry)
2017-09-26 12:50:09 +00:00
if err != nil {
2017-11-08 10:36:13 +00:00
return errors.Wrap(err, "load registry info failed")
2017-10-11 03:26:03 +00:00
} else if registry == nil {
2017-11-08 10:36:13 +00:00
return errors.New("can't load registry info")
2017-09-26 12:50:09 +00:00
}
2017-10-11 03:26:03 +00:00
info.Image = registry.URL + "/" + info.Image
info.RegistryAuth = registry.GetEncodedAuth()
}
2017-09-26 12:50:09 +00:00
2017-10-11 03:26:03 +00:00
if err = docker.ServiceCreate(info); err == nil {
biz.Event.CreateService(model.EventActionCreate, info.Name, ctx.User())
}
return ajaxResult(ctx, err)
}
2017-09-26 12:50:09 +00:00
2017-10-11 03:26:03 +00:00
func serviceEdit(ctx web.Context) error {
name := ctx.P("name")
service, _, err := docker.ServiceInspect(name)
if err != nil {
return err
2017-09-26 12:50:09 +00:00
}
2017-10-11 03:26:03 +00:00
networks, err := docker.NetworkList()
if err != nil {
return err
}
secrets, _, err := docker.SecretList("", 1, 100)
if err != nil {
return err
}
configs, _, err := docker.ConfigList("", 1, 100)
if err != nil {
return err
}
2017-09-26 12:50:09 +00:00
si := model.NewServiceInfo(service)
names, err := docker.NetworkNames(si.Networks...)
if err != nil {
return err
}
checkedNetworks := set.NewStringSet(names...)
2017-10-11 03:26:03 +00:00
m := newModel(ctx).Set("Service", si).
Set("Stack", service.Spec.Labels["com.docker.stack.namespace"]).
2017-11-08 10:36:13 +00:00
Set("Networks", networks).Set("CheckedNetworks", checkedNetworks).
Set("Secrets", secrets).Set("Configs", configs)
2017-10-11 03:26:03 +00:00
return ctx.Render("service/edit", m)
}
func serviceUpdate(ctx web.Context) error {
info := &model.ServiceInfo{}
err := ctx.Bind(info)
if err == nil {
info.Name = ctx.P("name")
info.Normalize()
2017-10-11 03:26:03 +00:00
err = docker.ServiceUpdate(info)
2017-09-26 12:50:09 +00:00
}
2017-10-11 03:26:03 +00:00
if err == nil {
biz.Event.CreateService(model.EventActionUpdate, info.Name, ctx.User())
}
return ajaxResult(ctx, err)
}
2017-09-26 12:50:09 +00:00
2017-10-11 03:26:03 +00:00
func serviceScale(ctx web.Context) error {
name := ctx.P("name")
2017-10-11 03:26:03 +00:00
count, err := strconv.Atoi(ctx.F("count"))
if err != nil {
return err
2017-09-26 12:50:09 +00:00
}
err = docker.ServiceScale(name, 0, uint64(count))
2017-10-11 03:26:03 +00:00
if err == nil {
biz.Event.CreateService(model.EventActionScale, name, ctx.User())
}
return ajaxResult(ctx, err)
2017-09-26 12:50:09 +00:00
}
2017-10-26 08:16:51 +00:00
func serviceRollback(ctx web.Context) error {
name := ctx.P("name")
2017-10-26 08:16:51 +00:00
err := docker.ServiceRollback(name)
if err == nil {
biz.Event.CreateService(model.EventActionRollback, name, ctx.User())
}
return ajaxResult(ctx, err)
}
2018-04-10 03:25:55 +00:00
func serviceRestart(ctx web.Context) error {
name := ctx.P("name")
2018-04-10 03:25:55 +00:00
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 {
name := ctx.P("name")
m := newModel(ctx).Set("Name", name)
return permEdit(ctx, "service", name, "service/perm", m)
}
func serviceStats(ctx web.Context) error {
name := ctx.P("name")
service, _, err := docker.ServiceInspect(name)
if err != nil {
return err
}
tasks, _, err := docker.TaskList(&model.TaskListArgs{Service: name})
if err != nil {
return err
}
setting, err := biz.Setting.Get()
if err != nil {
return err
}
2018-03-22 08:13:54 +00:00
var charts []*model.Chart
2018-03-12 08:48:16 +00:00
if setting.Metrics.Prometheus != "" {
var dashboard *model.ChartDashboard
if dashboard, err = biz.Chart.GetDashboard("service", name); err != nil {
return err
}
if dashboard == nil {
if dashboard, err = biz.Chart.GetDashboard("service", ""); err != nil {
return err
}
}
2018-04-12 03:34:04 +00:00
if dashboard == nil {
charts, err = biz.Chart.GetServiceCharts(name)
} else {
charts, err = biz.Chart.GetDashboardCharts(dashboard)
}
2018-04-12 03:34:04 +00:00
if err != nil {
return err
}
2018-03-12 08:48:16 +00:00
}
period := cast.ToDuration(ctx.Q("time"), time.Hour)
refresh := cast.ToBool(ctx.Q("refresh"), true)
2018-03-12 08:48:16 +00:00
m := newModel(ctx).Set("Service", service).Set("Tasks", tasks).Set("Time", period.String()).
2018-06-25 10:38:34 +00:00
Set("Refresh", refresh).Set("Prometheus", setting.Metrics.Prometheus).Set("Charts", charts)
return ctx.Render("service/stats", m)
}