mirror of
https://github.com/cuigh/swirl
synced 2025-06-26 18:16:50 +00:00
Refactor code
This commit is contained in:
parent
c3115b952c
commit
6705bd6d64
@ -39,7 +39,7 @@ func chartSearch(b biz.ChartBiz) web.HandlerFunc {
|
||||
return func(ctx web.Context) (err error) {
|
||||
var (
|
||||
args = &model.ChartSearchArgs{}
|
||||
charts []*biz.Chart
|
||||
charts []*model.Chart
|
||||
total int
|
||||
)
|
||||
|
||||
@ -85,7 +85,7 @@ func chartDelete(b biz.ChartBiz) web.HandlerFunc {
|
||||
|
||||
func chartSave(b biz.ChartBiz) web.HandlerFunc {
|
||||
return func(ctx web.Context) error {
|
||||
r := &biz.Chart{}
|
||||
r := &model.Chart{}
|
||||
err := ctx.Bind(r, true)
|
||||
if err == nil {
|
||||
if r.ID == "" {
|
||||
@ -122,7 +122,7 @@ func chartFetchData(b biz.ChartBiz) web.HandlerFunc {
|
||||
func chartFindDashboard(b biz.ChartBiz) web.HandlerFunc {
|
||||
return func(ctx web.Context) (err error) {
|
||||
var (
|
||||
d *biz.Dashboard
|
||||
d *model.Dashboard
|
||||
name = ctx.Query("name")
|
||||
key = ctx.Query("key")
|
||||
)
|
||||
|
@ -26,7 +26,7 @@ func eventSearch(b biz.EventBiz) web.HandlerFunc {
|
||||
return func(ctx web.Context) (err error) {
|
||||
var (
|
||||
args = &model.EventSearchArgs{}
|
||||
events []*biz.Event
|
||||
events []*model.Event
|
||||
total int
|
||||
)
|
||||
|
||||
|
@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"github.com/cuigh/auxo/net/web"
|
||||
"github.com/cuigh/swirl/biz"
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
// RegistryHandler encapsulates registry related handlers.
|
||||
@ -60,7 +61,7 @@ func registryDelete(b biz.RegistryBiz) web.HandlerFunc {
|
||||
|
||||
func registrySave(b biz.RegistryBiz) web.HandlerFunc {
|
||||
return func(ctx web.Context) error {
|
||||
r := &biz.Registry{}
|
||||
r := &model.Registry{}
|
||||
err := ctx.Bind(r, true)
|
||||
if err == nil {
|
||||
if r.ID == "" {
|
||||
|
@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"github.com/cuigh/auxo/net/web"
|
||||
"github.com/cuigh/swirl/biz"
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
// RoleHandler encapsulates role related handlers.
|
||||
@ -61,7 +62,7 @@ func roleDelete(b biz.RoleBiz) web.HandlerFunc {
|
||||
|
||||
func roleSave(b biz.RoleBiz) web.HandlerFunc {
|
||||
return func(ctx web.Context) error {
|
||||
r := &biz.Role{}
|
||||
r := &model.Role{}
|
||||
err := ctx.Bind(r, true)
|
||||
if err == nil {
|
||||
if r.ID == "" {
|
||||
|
14
api/stack.go
14
api/stack.go
@ -6,6 +6,7 @@ import (
|
||||
"github.com/cuigh/auxo/net/web"
|
||||
"github.com/cuigh/swirl/biz"
|
||||
"github.com/cuigh/swirl/docker/compose"
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
// StackHandler encapsulates stack related handlers.
|
||||
@ -53,7 +54,7 @@ func stackSearch(b biz.StackBiz) web.HandlerFunc {
|
||||
return func(ctx web.Context) (err error) {
|
||||
var (
|
||||
args = &Args{}
|
||||
stacks []*biz.Stack
|
||||
stacks []*model.Stack
|
||||
)
|
||||
|
||||
if err = ctx.Bind(args); err == nil {
|
||||
@ -119,8 +120,13 @@ func stackDeploy(b biz.StackBiz) web.HandlerFunc {
|
||||
}
|
||||
|
||||
func stackSave(b biz.StackBiz) web.HandlerFunc {
|
||||
type Args struct {
|
||||
ID string `json:"id"`
|
||||
model.Stack
|
||||
}
|
||||
|
||||
return func(ctx web.Context) error {
|
||||
stack := &biz.Stack{}
|
||||
stack := &Args{}
|
||||
err := ctx.Bind(stack, true)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -133,9 +139,9 @@ func stackSave(b biz.StackBiz) web.HandlerFunc {
|
||||
}
|
||||
|
||||
if stack.ID == "" {
|
||||
err = b.Create(stack, ctx.User())
|
||||
err = b.Create(&stack.Stack, ctx.User())
|
||||
} else {
|
||||
err = b.Update(stack, ctx.User())
|
||||
err = b.Update(&stack.Stack, ctx.User())
|
||||
}
|
||||
return ajax(ctx, err)
|
||||
}
|
||||
|
@ -6,9 +6,12 @@ import (
|
||||
|
||||
"github.com/cuigh/auxo/app"
|
||||
"github.com/cuigh/auxo/data"
|
||||
"github.com/cuigh/auxo/errors"
|
||||
"github.com/cuigh/auxo/net/web"
|
||||
"github.com/cuigh/swirl/biz"
|
||||
"github.com/cuigh/swirl/docker"
|
||||
"github.com/cuigh/swirl/misc"
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
//var ErrSystemInitialized = errors.New("system was already initialized")
|
||||
@ -22,10 +25,10 @@ type SystemHandler struct {
|
||||
}
|
||||
|
||||
// NewSystem creates an instance of SystemHandler
|
||||
func NewSystem(d *docker.Docker, b biz.SystemBiz) *SystemHandler {
|
||||
func NewSystem(d *docker.Docker, b biz.SystemBiz, ub biz.UserBiz) *SystemHandler {
|
||||
return &SystemHandler{
|
||||
CheckState: systemCheckState(b),
|
||||
CreateAdmin: systemCreateAdmin(b),
|
||||
CreateAdmin: systemCreateAdmin(ub),
|
||||
Version: systemVersion,
|
||||
Summarize: systemSummarize(d),
|
||||
}
|
||||
@ -74,12 +77,21 @@ func systemSummarize(d *docker.Docker) web.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func systemCreateAdmin(b biz.SystemBiz) web.HandlerFunc {
|
||||
func systemCreateAdmin(ub biz.UserBiz) web.HandlerFunc {
|
||||
return func(c web.Context) (err error) {
|
||||
user := &biz.User{}
|
||||
if err = c.Bind(user, true); err == nil {
|
||||
err = b.CreateAdmin(user)
|
||||
user := &model.User{}
|
||||
if err = c.Bind(user, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var count int
|
||||
if count, err = ub.Count(); err == nil && count > 0 {
|
||||
return errors.Coded(misc.ErrSystemInitialized, "system was already initialized")
|
||||
}
|
||||
|
||||
user.Admin = true
|
||||
user.Type = biz.UserTypeInternal
|
||||
_, err = ub.Create(user, nil)
|
||||
return ajax(c, err)
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"github.com/cuigh/auxo/data"
|
||||
"github.com/cuigh/auxo/net/web"
|
||||
"github.com/cuigh/swirl/biz"
|
||||
"github.com/cuigh/swirl/model"
|
||||
"github.com/cuigh/swirl/security"
|
||||
)
|
||||
|
||||
@ -69,10 +70,9 @@ func userSignIn(auth *security.Authenticator, eb biz.EventBiz) web.HandlerFunc {
|
||||
|
||||
func userSave(b biz.UserBiz) web.HandlerFunc {
|
||||
return func(ctx web.Context) error {
|
||||
user := &biz.User{}
|
||||
user := &model.User{}
|
||||
err := ctx.Bind(user, true)
|
||||
if err == nil {
|
||||
user.Type = biz.UserTypeInternal
|
||||
if user.ID == "" {
|
||||
_, err = b.Create(user, ctx.User())
|
||||
} else {
|
||||
@ -171,7 +171,7 @@ func userModifyPassword(b biz.UserBiz) web.HandlerFunc {
|
||||
|
||||
func userModifyProfile(b biz.UserBiz) web.HandlerFunc {
|
||||
return func(ctx web.Context) error {
|
||||
u := &biz.User{}
|
||||
u := &model.User{}
|
||||
err := ctx.Bind(u, true)
|
||||
if err == nil {
|
||||
err = b.ModifyProfile(u, ctx.User())
|
||||
|
10
biz/biz.go
10
biz/biz.go
@ -11,6 +11,8 @@ import (
|
||||
|
||||
"github.com/cuigh/auxo/app/container"
|
||||
"github.com/cuigh/auxo/data"
|
||||
"github.com/cuigh/auxo/net/web"
|
||||
"github.com/cuigh/swirl/model"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
@ -101,6 +103,14 @@ func indentJSON(raw []byte) (s string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func now() model.Time {
|
||||
return model.Time(time.Now())
|
||||
}
|
||||
|
||||
func newOperator(user web.User) model.Operator {
|
||||
return model.Operator{ID: user.ID(), Name: user.Name()}
|
||||
}
|
||||
|
||||
func init() {
|
||||
container.Put(NewNetwork)
|
||||
container.Put(NewNode)
|
||||
|
193
biz/chart.go
193
biz/chart.go
@ -14,15 +14,22 @@ import (
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
var builtins = []*model.Chart{
|
||||
model.NewChart("service", "$cpu", "CPU", "${name}", `rate(container_cpu_user_seconds_total{container_label_com_docker_swarm_service_name="${service}"}[5m]) * 100`, "percent:100", 60),
|
||||
model.NewChart("service", "$memory", "Memory", "${name}", `container_memory_usage_bytes{container_label_com_docker_swarm_service_name="${service}"}`, "size:bytes", 60),
|
||||
model.NewChart("service", "$network_in", "Network Receive", "${name}", `sum(irate(container_network_receive_bytes_total{container_label_com_docker_swarm_service_name="${service}"}[5m])) by(name)`, "size:bytes", 60),
|
||||
model.NewChart("service", "$network_out", "Network Send", "${name}", `sum(irate(container_network_transmit_bytes_total{container_label_com_docker_swarm_service_name="${service}"}[5m])) by(name)`, "size:bytes", 60),
|
||||
}
|
||||
|
||||
type ChartBiz interface {
|
||||
Search(args *model.ChartSearchArgs) (charts []*Chart, total int, err error)
|
||||
Search(args *model.ChartSearchArgs) (charts []*model.Chart, total int, err error)
|
||||
Delete(id, title string, user web.User) (err error)
|
||||
Find(id string) (chart *Chart, err error)
|
||||
Find(id string) (chart *model.Chart, err error)
|
||||
Batch(ids ...string) (charts []*model.Chart, err error)
|
||||
Create(chart *Chart, user web.User) (err error)
|
||||
Update(chart *Chart, user web.User) (err error)
|
||||
Create(chart *model.Chart, user web.User) (err error)
|
||||
Update(chart *model.Chart, user web.User) (err error)
|
||||
FetchData(key string, ids []string, period time.Duration) (data.Map, error)
|
||||
FindDashboard(name, key string) (dashboard *Dashboard, err error)
|
||||
FindDashboard(name, key string) (dashboard *model.Dashboard, err error)
|
||||
UpdateDashboard(dashboard *model.Dashboard, user web.User) (err error)
|
||||
}
|
||||
|
||||
@ -31,48 +38,28 @@ func NewChart(d dao.Interface, mb MetricBiz, eb EventBiz) ChartBiz {
|
||||
d: d,
|
||||
mb: mb,
|
||||
eb: eb,
|
||||
builtin: []*model.Chart{
|
||||
model.NewChart("service", "$cpu", "CPU", "${name}", `rate(container_cpu_user_seconds_total{container_label_com_docker_swarm_service_name="${service}"}[5m]) * 100`, "percent:100", 60),
|
||||
model.NewChart("service", "$memory", "Memory", "${name}", `container_memory_usage_bytes{container_label_com_docker_swarm_service_name="${service}"}`, "size:bytes", 60),
|
||||
model.NewChart("service", "$network_in", "Network Receive", "${name}", `sum(irate(container_network_receive_bytes_total{container_label_com_docker_swarm_service_name="${service}"}[5m])) by(name)`, "size:bytes", 60),
|
||||
model.NewChart("service", "$network_out", "Network Send", "${name}", `sum(irate(container_network_transmit_bytes_total{container_label_com_docker_swarm_service_name="${service}"}[5m])) by(name)`, "size:bytes", 60),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type chartBiz struct {
|
||||
builtin []*model.Chart
|
||||
d dao.Interface
|
||||
mb MetricBiz
|
||||
eb EventBiz
|
||||
d dao.Interface
|
||||
mb MetricBiz
|
||||
eb EventBiz
|
||||
}
|
||||
|
||||
func (b *chartBiz) Search(args *model.ChartSearchArgs) (charts []*Chart, total int, err error) {
|
||||
var list []*model.Chart
|
||||
list, total, err = b.d.ChartSearch(context.TODO(), args)
|
||||
if err == nil {
|
||||
charts = make([]*Chart, len(list))
|
||||
for i, c := range list {
|
||||
charts[i] = newChart(c)
|
||||
}
|
||||
}
|
||||
return
|
||||
func (b *chartBiz) Search(args *model.ChartSearchArgs) (charts []*model.Chart, total int, err error) {
|
||||
return b.d.ChartSearch(context.TODO(), args)
|
||||
}
|
||||
|
||||
func (b *chartBiz) Create(chart *Chart, user web.User) (err error) {
|
||||
c := &model.Chart{
|
||||
ID: createId(),
|
||||
CreatedAt: time.Now(),
|
||||
CreatedBy: model.Operator{ID: user.ID(), Name: user.Name()},
|
||||
}
|
||||
c.UpdatedAt = c.CreatedAt
|
||||
if err = copier.CopyWithOption(c, chart, copier.Option{IgnoreEmpty: true, DeepCopy: true}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = b.d.ChartCreate(context.TODO(), c)
|
||||
func (b *chartBiz) Create(chart *model.Chart, user web.User) (err error) {
|
||||
chart.ID = createId()
|
||||
chart.CreatedAt = now()
|
||||
chart.CreatedBy = newOperator(user)
|
||||
chart.UpdatedAt = chart.CreatedAt
|
||||
chart.UpdatedBy = chart.CreatedBy
|
||||
err = b.d.ChartCreate(context.TODO(), chart)
|
||||
if err == nil {
|
||||
b.eb.CreateChart(EventActionCreate, c.ID, c.Title, user)
|
||||
b.eb.CreateChart(EventActionCreate, chart.ID, chart.Title, user)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -85,13 +72,8 @@ func (b *chartBiz) Delete(id, title string, user web.User) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (b *chartBiz) Find(id string) (chart *Chart, err error) {
|
||||
var c *model.Chart
|
||||
c, err = b.d.ChartGet(context.TODO(), id)
|
||||
if err == nil {
|
||||
chart = newChart(c)
|
||||
}
|
||||
return
|
||||
func (b *chartBiz) Find(id string) (chart *model.Chart, err error) {
|
||||
return b.d.ChartGet(context.TODO(), id)
|
||||
}
|
||||
|
||||
func (b *chartBiz) Batch(ids ...string) (charts []*model.Chart, err error) {
|
||||
@ -99,43 +81,30 @@ func (b *chartBiz) Batch(ids ...string) (charts []*model.Chart, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (b *chartBiz) Update(chart *Chart, user web.User) (err error) {
|
||||
c := &model.Chart{
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
if err = copier.CopyWithOption(c, chart, copier.Option{IgnoreEmpty: true, DeepCopy: true}); err != nil {
|
||||
return err
|
||||
}
|
||||
c.UpdatedBy.ID = user.ID()
|
||||
c.UpdatedBy.Name = user.Name()
|
||||
|
||||
err = b.d.ChartUpdate(context.TODO(), c)
|
||||
func (b *chartBiz) Update(chart *model.Chart, user web.User) (err error) {
|
||||
chart.UpdatedAt = now()
|
||||
chart.UpdatedBy = newOperator(user)
|
||||
err = b.d.ChartUpdate(context.TODO(), chart)
|
||||
if err == nil {
|
||||
b.eb.CreateChart(EventActionUpdate, chart.ID, chart.Title, user)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *chartBiz) FindDashboard(name, key string) (dashboard *Dashboard, err error) {
|
||||
var d *model.Dashboard
|
||||
d, err = b.d.DashboardGet(context.TODO(), name, key)
|
||||
if err != nil {
|
||||
func (b *chartBiz) FindDashboard(name, key string) (dashboard *model.Dashboard, err error) {
|
||||
if dashboard, err = b.d.DashboardGet(context.TODO(), name, key); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if d == nil {
|
||||
if dashboard == nil {
|
||||
dashboard = defaultDashboard(name, key)
|
||||
} else {
|
||||
dashboard = newDashboard(d)
|
||||
}
|
||||
err = b.fillCharts(dashboard)
|
||||
return
|
||||
}
|
||||
|
||||
func (b *chartBiz) UpdateDashboard(dashboard *model.Dashboard, user web.User) (err error) {
|
||||
dashboard.UpdatedAt = time.Now()
|
||||
dashboard.UpdatedBy.ID = user.ID()
|
||||
dashboard.UpdatedBy.Name = user.Name()
|
||||
dashboard.UpdatedAt = now()
|
||||
dashboard.UpdatedBy = newOperator(user)
|
||||
return b.d.DashboardUpdate(context.TODO(), dashboard)
|
||||
}
|
||||
|
||||
@ -280,7 +249,7 @@ func (b *chartBiz) getCharts(ids []string) (charts map[string]*model.Chart, err
|
||||
charts = make(map[string]*model.Chart)
|
||||
for _, id := range ids {
|
||||
if id[0] == '$' {
|
||||
for _, c := range b.builtin {
|
||||
for _, c := range builtins {
|
||||
if c.ID == id {
|
||||
charts[id] = c
|
||||
}
|
||||
@ -300,7 +269,7 @@ func (b *chartBiz) getCharts(ids []string) (charts map[string]*model.Chart, err
|
||||
return
|
||||
}
|
||||
|
||||
func (b *chartBiz) fillCharts(d *Dashboard) (err error) {
|
||||
func (b *chartBiz) fillCharts(d *model.Dashboard) (err error) {
|
||||
if len(d.Charts) == 0 {
|
||||
return
|
||||
}
|
||||
@ -319,77 +288,23 @@ func (b *chartBiz) fillCharts(d *Dashboard) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, info := range d.Charts {
|
||||
if c := m[info.ID]; c != nil {
|
||||
info.Type = c.Type
|
||||
info.Title = c.Title
|
||||
info.Unit = c.Unit
|
||||
if info.Width == 0 {
|
||||
info.Width = c.Width
|
||||
}
|
||||
if info.Height == 0 {
|
||||
info.Height = c.Height
|
||||
}
|
||||
info.Margin.Left = c.Margin.Left
|
||||
info.Margin.Right = c.Margin.Right
|
||||
info.Margin.Top = c.Margin.Top
|
||||
info.Margin.Bottom = c.Margin.Bottom
|
||||
for i := range d.Charts {
|
||||
if c := m[d.Charts[i].ID]; c != nil {
|
||||
_ = copier.CopyWithOption(&d.Charts[i], c, copier.Option{IgnoreEmpty: true})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Dashboard struct {
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key,omitempty"`
|
||||
Period int32 `json:"period,omitempty"` // data range in minutes
|
||||
Interval int32 `json:"interval,omitempty"` // refresh interval in seconds, 0 means disabled.
|
||||
Charts []*Chart `json:"charts,omitempty"`
|
||||
}
|
||||
|
||||
type Chart struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title" valid:"required"`
|
||||
Description string `json:"desc,omitempty"`
|
||||
Dashboard string `json:"dashboard,omitempty"`
|
||||
Type string `json:"type" valid:"required"`
|
||||
Unit string `json:"unit"`
|
||||
Width int32 `json:"width" valid:"required"`
|
||||
Height int32 `json:"height" valid:"required"`
|
||||
Margin struct {
|
||||
Left int32 `json:"left,omitempty"`
|
||||
Right int32 `json:"right,omitempty"`
|
||||
Top int32 `json:"top,omitempty"`
|
||||
Bottom int32 `json:"bottom,omitempty"`
|
||||
} `json:"margin"`
|
||||
Metrics []model.ChartMetric `json:"metrics" valid:"required"`
|
||||
Options data.Map `json:"options,omitempty"`
|
||||
CreatedAt string `json:"createdAt,omitempty" copier:"-"`
|
||||
UpdatedAt string `json:"updatedAt,omitempty" copier:"-"`
|
||||
CreatedBy model.Operator `json:"createdBy"`
|
||||
UpdatedBy model.Operator `json:"updatedBy"`
|
||||
}
|
||||
|
||||
func newChart(c *model.Chart) *Chart {
|
||||
chart := &Chart{
|
||||
CreatedAt: formatTime(c.CreatedAt),
|
||||
UpdatedAt: formatTime(c.UpdatedAt),
|
||||
}
|
||||
if err := copier.CopyWithOption(chart, c, copier.Option{IgnoreEmpty: true, DeepCopy: true}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return chart
|
||||
}
|
||||
|
||||
func defaultDashboard(name, key string) *Dashboard {
|
||||
d := &Dashboard{
|
||||
func defaultDashboard(name, key string) *model.Dashboard {
|
||||
d := &model.Dashboard{
|
||||
Name: name,
|
||||
Key: key,
|
||||
Period: 30,
|
||||
Interval: 15,
|
||||
}
|
||||
if name == "service" {
|
||||
d.Charts = []*Chart{
|
||||
d.Charts = []model.ChartInfo{
|
||||
{ID: "$cpu"},
|
||||
{ID: "$memory"},
|
||||
{ID: "$network_in"},
|
||||
@ -398,23 +313,3 @@ func defaultDashboard(name, key string) *Dashboard {
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func newDashboard(d *model.Dashboard) *Dashboard {
|
||||
dashboard := &Dashboard{
|
||||
Name: d.Name,
|
||||
Key: d.Key,
|
||||
Period: d.Period,
|
||||
Interval: d.Interval,
|
||||
}
|
||||
if len(d.Charts) > 0 {
|
||||
dashboard.Charts = make([]*Chart, len(d.Charts))
|
||||
for i, c := range d.Charts {
|
||||
dashboard.Charts[i] = &Chart{
|
||||
ID: c.ID,
|
||||
Width: c.Width,
|
||||
Height: c.Height,
|
||||
}
|
||||
}
|
||||
}
|
||||
return dashboard
|
||||
}
|
||||
|
@ -9,39 +9,6 @@ import (
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Version uint64 `json:"version"`
|
||||
Data string `json:"data"`
|
||||
Labels data.Options `json:"labels,omitempty"`
|
||||
Templating Driver `json:"templating"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type Driver struct {
|
||||
Name string `json:"name"`
|
||||
Options data.Options `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
func newConfig(c *swarm.Config) *Config {
|
||||
config := &Config{
|
||||
ID: c.ID,
|
||||
Name: c.Spec.Name,
|
||||
Version: c.Version.Index,
|
||||
Data: string(c.Spec.Data),
|
||||
Labels: mapToOptions(c.Spec.Labels),
|
||||
CreatedAt: formatTime(c.CreatedAt),
|
||||
UpdatedAt: formatTime(c.UpdatedAt),
|
||||
}
|
||||
if c.Spec.Templating != nil {
|
||||
config.Templating.Name = c.Spec.Templating.Name
|
||||
config.Templating.Options = mapToOptions(c.Spec.Templating.Options)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
type ConfigBiz interface {
|
||||
Search(name string, pageIndex, pageSize int) (configs []*Config, total int, err error)
|
||||
Find(id string) (config *Config, raw string, err error)
|
||||
@ -134,3 +101,36 @@ func (b *configBiz) Update(c *Config, user web.User) (err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Version uint64 `json:"version"`
|
||||
Data string `json:"data"`
|
||||
Labels data.Options `json:"labels,omitempty"`
|
||||
Templating Driver `json:"templating"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type Driver struct {
|
||||
Name string `json:"name"`
|
||||
Options data.Options `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
func newConfig(c *swarm.Config) *Config {
|
||||
config := &Config{
|
||||
ID: c.ID,
|
||||
Name: c.Spec.Name,
|
||||
Version: c.Version.Index,
|
||||
Data: string(c.Spec.Data),
|
||||
Labels: mapToOptions(c.Spec.Labels),
|
||||
CreatedAt: formatTime(c.CreatedAt),
|
||||
UpdatedAt: formatTime(c.UpdatedAt),
|
||||
}
|
||||
if c.Spec.Templating != nil {
|
||||
config.Templating.Name = c.Spec.Templating.Name
|
||||
config.Templating.Options = mapToOptions(c.Spec.Templating.Options)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
250
biz/container.go
250
biz/container.go
@ -11,143 +11,6 @@ import (
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
)
|
||||
|
||||
type Container struct {
|
||||
/* Summary */
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Image string `json:"image,omitempty"`
|
||||
Command string `json:"command,omitempty"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
Ports []*ContainerPort `json:"ports,omitempty"`
|
||||
SizeRw int64 `json:"sizeRw"`
|
||||
SizeRootFs int64 `json:"sizeRootFs"`
|
||||
Labels data.Options `json:"labels"`
|
||||
State string `json:"state"`
|
||||
Status string `json:"status"`
|
||||
NetworkMode string `json:"networkMode"`
|
||||
Mounts []*ContainerMount `json:"mounts"`
|
||||
//Networks map[string]*network.EndpointSettings
|
||||
|
||||
/* Detail */
|
||||
PID int `json:"pid,omitempty"`
|
||||
StartedAt string `json:"startedAt,omitempty"`
|
||||
}
|
||||
|
||||
type ContainerPort struct {
|
||||
IP string `json:"ip,omitempty"`
|
||||
PrivatePort uint16 `json:"privatePort,omitempty"`
|
||||
PublicPort uint16 `json:"publicPort,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
type ContainerMount struct {
|
||||
Type mount.Type `json:"type,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Source string `json:"source,omitempty"`
|
||||
Destination string `json:"destination,omitempty"`
|
||||
Driver string `json:"driver,omitempty"`
|
||||
Mode string `json:"mode,omitempty"`
|
||||
RW bool `json:"rw,omitempty"`
|
||||
Propagation mount.Propagation `json:"propagation,omitempty"`
|
||||
}
|
||||
|
||||
func newContainerMount(m types.MountPoint) *ContainerMount {
|
||||
return &ContainerMount{
|
||||
Type: m.Type,
|
||||
Name: m.Name,
|
||||
Source: m.Source,
|
||||
Destination: m.Destination,
|
||||
Driver: m.Driver,
|
||||
Mode: m.Mode,
|
||||
RW: m.RW,
|
||||
Propagation: m.Propagation,
|
||||
}
|
||||
}
|
||||
|
||||
// EndpointSettings stores the network endpoint details
|
||||
//type EndpointSettings struct {
|
||||
// // Configurations
|
||||
// IPAMConfig *EndpointIPAMConfig
|
||||
// Links []string
|
||||
// Aliases []string
|
||||
// // Operational data
|
||||
// NetworkID string
|
||||
// EndpointID string
|
||||
// Gateway string
|
||||
// IPAddress string
|
||||
// IPPrefixLen int
|
||||
// IPv6Gateway string
|
||||
// GlobalIPv6Address string
|
||||
// GlobalIPv6PrefixLen int
|
||||
// MacAddress string
|
||||
// DriverOpts map[string]string
|
||||
//}
|
||||
|
||||
func newContainerSummary(c *types.Container) *Container {
|
||||
container := &Container{
|
||||
ID: c.ID,
|
||||
Name: c.Names[0],
|
||||
Image: normalizeImage(c.Image),
|
||||
Command: c.Command,
|
||||
CreatedAt: formatTime(time.Unix(c.Created, 0)),
|
||||
SizeRw: c.SizeRw,
|
||||
SizeRootFs: c.SizeRootFs,
|
||||
Labels: mapToOptions(c.Labels),
|
||||
State: c.State,
|
||||
Status: c.Status,
|
||||
NetworkMode: c.HostConfig.NetworkMode,
|
||||
}
|
||||
for _, p := range c.Ports {
|
||||
container.Ports = append(container.Ports, &ContainerPort{
|
||||
IP: p.IP,
|
||||
PrivatePort: p.PrivatePort,
|
||||
PublicPort: p.PublicPort,
|
||||
Type: p.Type,
|
||||
})
|
||||
}
|
||||
for _, m := range c.Mounts {
|
||||
container.Mounts = append(container.Mounts, newContainerMount(m))
|
||||
}
|
||||
return container
|
||||
}
|
||||
|
||||
func newContainerDetail(c *types.ContainerJSON) *Container {
|
||||
created, _ := time.Parse(time.RFC3339Nano, c.Created)
|
||||
startedAt, _ := time.Parse(time.RFC3339Nano, c.State.StartedAt)
|
||||
container := &Container{
|
||||
ID: c.ID,
|
||||
Name: c.Name,
|
||||
Image: c.Image,
|
||||
//Command: c.Command,
|
||||
CreatedAt: formatTime(created),
|
||||
Labels: mapToOptions(c.Config.Labels),
|
||||
State: c.State.Status,
|
||||
//Status: c.Status,
|
||||
NetworkMode: string(c.HostConfig.NetworkMode),
|
||||
// detail
|
||||
PID: c.State.Pid,
|
||||
StartedAt: formatTime(startedAt),
|
||||
}
|
||||
if c.SizeRw != nil {
|
||||
container.SizeRw = *c.SizeRw
|
||||
}
|
||||
if c.SizeRootFs != nil {
|
||||
container.SizeRootFs = *c.SizeRootFs
|
||||
}
|
||||
//for _, p := range c.Ports {
|
||||
// container.Ports = append(container.Ports, &ContainerPort{
|
||||
// IP: p.IP,
|
||||
// PrivatePort: p.PrivatePort,
|
||||
// PublicPort: p.PublicPort,
|
||||
// Type: p.Type,
|
||||
// })
|
||||
//}
|
||||
for _, m := range c.Mounts {
|
||||
container.Mounts = append(container.Mounts, newContainerMount(m))
|
||||
}
|
||||
return container
|
||||
}
|
||||
|
||||
type ContainerBiz interface {
|
||||
Search(name, status string, pageIndex, pageSize int) ([]*Container, int, error)
|
||||
Find(id string) (container *Container, raw string, err error)
|
||||
@ -222,3 +85,116 @@ func (b *containerBiz) FetchLogs(id string, lines int, timestamps bool) (string,
|
||||
}
|
||||
return stdout.String(), stderr.String(), nil
|
||||
}
|
||||
|
||||
type Container struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Image string `json:"image,omitempty"`
|
||||
Command string `json:"command,omitempty"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
Ports []*ContainerPort `json:"ports,omitempty"`
|
||||
SizeRw int64 `json:"sizeRw"`
|
||||
SizeRootFs int64 `json:"sizeRootFs"`
|
||||
Labels data.Options `json:"labels"`
|
||||
State string `json:"state"`
|
||||
Status string `json:"status"`
|
||||
NetworkMode string `json:"networkMode"`
|
||||
Mounts []*ContainerMount `json:"mounts"`
|
||||
PID int `json:"pid,omitempty"`
|
||||
StartedAt string `json:"startedAt,omitempty"`
|
||||
}
|
||||
|
||||
type ContainerPort struct {
|
||||
IP string `json:"ip,omitempty"`
|
||||
PrivatePort uint16 `json:"privatePort,omitempty"`
|
||||
PublicPort uint16 `json:"publicPort,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
type ContainerMount struct {
|
||||
Type mount.Type `json:"type,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Source string `json:"source,omitempty"`
|
||||
Destination string `json:"destination,omitempty"`
|
||||
Driver string `json:"driver,omitempty"`
|
||||
Mode string `json:"mode,omitempty"`
|
||||
RW bool `json:"rw,omitempty"`
|
||||
Propagation mount.Propagation `json:"propagation,omitempty"`
|
||||
}
|
||||
|
||||
func newContainerMount(m types.MountPoint) *ContainerMount {
|
||||
return &ContainerMount{
|
||||
Type: m.Type,
|
||||
Name: m.Name,
|
||||
Source: m.Source,
|
||||
Destination: m.Destination,
|
||||
Driver: m.Driver,
|
||||
Mode: m.Mode,
|
||||
RW: m.RW,
|
||||
Propagation: m.Propagation,
|
||||
}
|
||||
}
|
||||
|
||||
func newContainerSummary(c *types.Container) *Container {
|
||||
container := &Container{
|
||||
ID: c.ID,
|
||||
Name: c.Names[0],
|
||||
Image: normalizeImage(c.Image),
|
||||
Command: c.Command,
|
||||
CreatedAt: formatTime(time.Unix(c.Created, 0)),
|
||||
SizeRw: c.SizeRw,
|
||||
SizeRootFs: c.SizeRootFs,
|
||||
Labels: mapToOptions(c.Labels),
|
||||
State: c.State,
|
||||
Status: c.Status,
|
||||
NetworkMode: c.HostConfig.NetworkMode,
|
||||
}
|
||||
for _, p := range c.Ports {
|
||||
container.Ports = append(container.Ports, &ContainerPort{
|
||||
IP: p.IP,
|
||||
PrivatePort: p.PrivatePort,
|
||||
PublicPort: p.PublicPort,
|
||||
Type: p.Type,
|
||||
})
|
||||
}
|
||||
for _, m := range c.Mounts {
|
||||
container.Mounts = append(container.Mounts, newContainerMount(m))
|
||||
}
|
||||
return container
|
||||
}
|
||||
|
||||
func newContainerDetail(c *types.ContainerJSON) *Container {
|
||||
created, _ := time.Parse(time.RFC3339Nano, c.Created)
|
||||
startedAt, _ := time.Parse(time.RFC3339Nano, c.State.StartedAt)
|
||||
container := &Container{
|
||||
ID: c.ID,
|
||||
Name: c.Name,
|
||||
Image: c.Image,
|
||||
//Command: c.Command,
|
||||
CreatedAt: formatTime(created),
|
||||
Labels: mapToOptions(c.Config.Labels),
|
||||
State: c.State.Status,
|
||||
//Status: c.Status,
|
||||
NetworkMode: string(c.HostConfig.NetworkMode),
|
||||
PID: c.State.Pid,
|
||||
StartedAt: formatTime(startedAt),
|
||||
}
|
||||
if c.SizeRw != nil {
|
||||
container.SizeRw = *c.SizeRw
|
||||
}
|
||||
if c.SizeRootFs != nil {
|
||||
container.SizeRootFs = *c.SizeRootFs
|
||||
}
|
||||
//for _, p := range c.Ports {
|
||||
// container.Ports = append(container.Ports, &ContainerPort{
|
||||
// IP: p.IP,
|
||||
// PrivatePort: p.PrivatePort,
|
||||
// PublicPort: p.PublicPort,
|
||||
// Type: p.Type,
|
||||
// })
|
||||
//}
|
||||
for _, m := range c.Mounts {
|
||||
container.Mounts = append(container.Mounts, newContainerMount(m))
|
||||
}
|
||||
return container
|
||||
}
|
||||
|
39
biz/event.go
39
biz/event.go
@ -2,13 +2,11 @@ package biz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/cuigh/auxo/log"
|
||||
"github.com/cuigh/auxo/net/web"
|
||||
"github.com/cuigh/swirl/dao"
|
||||
"github.com/cuigh/swirl/model"
|
||||
"github.com/jinzhu/copier"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
@ -46,28 +44,8 @@ const (
|
||||
EventActionPrune EventAction = "Prune"
|
||||
)
|
||||
|
||||
type Event struct {
|
||||
ID string `json:"id"`
|
||||
Type EventType `json:"type"`
|
||||
Action EventAction `json:"action"`
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
UserID string `json:"userId"`
|
||||
Username string `json:"username"`
|
||||
Time string `json:"time"`
|
||||
}
|
||||
|
||||
func newEvent(e *model.Event) *Event {
|
||||
event := &Event{
|
||||
Time: formatTime(e.Time),
|
||||
ID: e.ID.Hex(),
|
||||
}
|
||||
_ = copier.CopyWithOption(event, e, copier.Option{IgnoreEmpty: true})
|
||||
return event
|
||||
}
|
||||
|
||||
type EventBiz interface {
|
||||
Search(args *model.EventSearchArgs) (events []*Event, total int, err error)
|
||||
Search(args *model.EventSearchArgs) (events []*model.Event, total int, err error)
|
||||
CreateRegistry(action EventAction, id, name string, user web.User)
|
||||
CreateNode(action EventAction, id, name string, user web.User)
|
||||
CreateNetwork(action EventAction, id, name string, user web.User)
|
||||
@ -91,16 +69,8 @@ type eventBiz struct {
|
||||
d dao.Interface
|
||||
}
|
||||
|
||||
func (b *eventBiz) Search(args *model.EventSearchArgs) (events []*Event, total int, err error) {
|
||||
var list []*model.Event
|
||||
list, total, err = b.d.EventSearch(context.TODO(), args)
|
||||
if err == nil && len(list) > 0 {
|
||||
events = make([]*Event, len(list))
|
||||
for i, e := range list {
|
||||
events[i] = newEvent(e)
|
||||
}
|
||||
}
|
||||
return
|
||||
func (b *eventBiz) Search(args *model.EventSearchArgs) (events []*model.Event, total int, err error) {
|
||||
return b.d.EventSearch(context.TODO(), args)
|
||||
}
|
||||
|
||||
func (b *eventBiz) create(et EventType, ea EventAction, code, name string, user web.User) {
|
||||
@ -112,9 +82,8 @@ func (b *eventBiz) create(et EventType, ea EventAction, code, name string, user
|
||||
Name: name,
|
||||
UserID: user.ID(),
|
||||
Username: user.Name(),
|
||||
Time: time.Now(),
|
||||
Time: now(),
|
||||
}
|
||||
|
||||
err := b.d.EventCreate(context.TODO(), event)
|
||||
if err != nil {
|
||||
log.Get("event").Errorf("failed to create event `%+v`: %v", event, err)
|
||||
|
114
biz/image.go
114
biz/image.go
@ -11,6 +11,63 @@ import (
|
||||
"github.com/docker/docker/api/types/image"
|
||||
)
|
||||
|
||||
type ImageBiz interface {
|
||||
Search(name string, pageIndex, pageSize int) ([]*Image, int, error)
|
||||
Find(name string) (image *Image, raw string, err error)
|
||||
Delete(id string, user web.User) (err error)
|
||||
}
|
||||
|
||||
func NewImage(d *docker.Docker) ImageBiz {
|
||||
return &imageBiz{d: d}
|
||||
}
|
||||
|
||||
type imageBiz struct {
|
||||
d *docker.Docker
|
||||
}
|
||||
|
||||
func (b *imageBiz) Find(id string) (img *Image, raw string, err error) {
|
||||
var (
|
||||
i types.ImageInspect
|
||||
r []byte
|
||||
histories []image.HistoryResponseItem
|
||||
ctx = context.TODO()
|
||||
)
|
||||
|
||||
if i, r, err = b.d.ImageInspect(ctx, id); err == nil {
|
||||
raw, err = indentJSON(r)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
histories, err = b.d.ImageHistory(ctx, id)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
img = newImageDetail(&i, histories)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *imageBiz) Search(name string, pageIndex, pageSize int) (images []*Image, total int, err error) {
|
||||
list, total, err := b.d.ImageList(context.TODO(), name, pageIndex, pageSize)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
images = make([]*Image, len(list))
|
||||
for i, nr := range list {
|
||||
images[i] = newImageSummary(&nr)
|
||||
}
|
||||
return images, total, nil
|
||||
}
|
||||
|
||||
func (b *imageBiz) Delete(id string, user web.User) (err error) {
|
||||
err = b.d.ImageRemove(context.TODO(), id)
|
||||
//if err == nil {
|
||||
// Event.CreateImage(model.EventActionDelete, id, user)
|
||||
//}
|
||||
return
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
/* Summary */
|
||||
ID string `json:"id"`
|
||||
@ -123,60 +180,3 @@ func newImageDetail(is *types.ImageInspect, items []image.HistoryResponseItem) *
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
type ImageBiz interface {
|
||||
Search(name string, pageIndex, pageSize int) ([]*Image, int, error)
|
||||
Find(name string) (image *Image, raw string, err error)
|
||||
Delete(id string, user web.User) (err error)
|
||||
}
|
||||
|
||||
func NewImage(d *docker.Docker) ImageBiz {
|
||||
return &imageBiz{d: d}
|
||||
}
|
||||
|
||||
type imageBiz struct {
|
||||
d *docker.Docker
|
||||
}
|
||||
|
||||
func (b *imageBiz) Find(id string) (img *Image, raw string, err error) {
|
||||
var (
|
||||
i types.ImageInspect
|
||||
r []byte
|
||||
histories []image.HistoryResponseItem
|
||||
ctx = context.TODO()
|
||||
)
|
||||
|
||||
if i, r, err = b.d.ImageInspect(ctx, id); err == nil {
|
||||
raw, err = indentJSON(r)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
histories, err = b.d.ImageHistory(ctx, id)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
img = newImageDetail(&i, histories)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *imageBiz) Search(name string, pageIndex, pageSize int) (images []*Image, total int, err error) {
|
||||
list, total, err := b.d.ImageList(context.TODO(), name, pageIndex, pageSize)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
images = make([]*Image, len(list))
|
||||
for i, nr := range list {
|
||||
images[i] = newImageSummary(&nr)
|
||||
}
|
||||
return images, total, nil
|
||||
}
|
||||
|
||||
func (b *imageBiz) Delete(id string, user web.User) (err error) {
|
||||
err = b.d.ImageRemove(context.TODO(), id)
|
||||
//if err == nil {
|
||||
// Event.CreateImage(model.EventActionDelete, id, user)
|
||||
//}
|
||||
return
|
||||
}
|
||||
|
142
biz/network.go
142
biz/network.go
@ -10,77 +10,6 @@ import (
|
||||
"github.com/docker/docker/api/types/network"
|
||||
)
|
||||
|
||||
type Network struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Created string `json:"created"`
|
||||
Driver string `json:"driver"`
|
||||
Scope string `json:"scope"`
|
||||
Internal bool `json:"internal"`
|
||||
Attachable bool `json:"attachable"`
|
||||
Ingress bool `json:"ingress"`
|
||||
IPv6 bool `json:"ipv6"`
|
||||
IPAM struct {
|
||||
Driver string `json:"driver"`
|
||||
Options data.Options `json:"options"`
|
||||
Config []*IPAMConfig `json:"config"`
|
||||
} `json:"ipam"`
|
||||
Options data.Options `json:"options"`
|
||||
Labels data.Options `json:"labels"`
|
||||
Containers []*NetworkContainer `json:"containers"`
|
||||
}
|
||||
|
||||
type IPAMConfig struct {
|
||||
Subnet string `json:"subnet,omitempty"`
|
||||
Gateway string `json:"gateway,omitempty"`
|
||||
Range string `json:"range,omitempty"`
|
||||
}
|
||||
|
||||
type NetworkContainer struct {
|
||||
ID string `json:"id"` // container id
|
||||
Name string `json:"name"` // container name
|
||||
Mac string `json:"mac"` // mac address
|
||||
IPv4 string `json:"ipv4"` // IPv4 address
|
||||
IPv6 string `json:"ipv6"` // IPv6 address
|
||||
}
|
||||
|
||||
func newNetwork(nr *types.NetworkResource) *Network {
|
||||
n := &Network{
|
||||
ID: nr.ID,
|
||||
Name: nr.Name,
|
||||
Created: formatTime(nr.Created),
|
||||
Driver: nr.Driver,
|
||||
Scope: nr.Scope,
|
||||
Internal: nr.Internal,
|
||||
Attachable: nr.Attachable,
|
||||
Ingress: nr.Ingress,
|
||||
IPv6: nr.EnableIPv6,
|
||||
Options: mapToOptions(nr.Options),
|
||||
Labels: mapToOptions(nr.Labels),
|
||||
}
|
||||
n.IPAM.Driver = nr.IPAM.Driver
|
||||
n.IPAM.Options = mapToOptions(nr.IPAM.Options)
|
||||
n.IPAM.Config = make([]*IPAMConfig, len(nr.IPAM.Config))
|
||||
for i, c := range nr.IPAM.Config {
|
||||
n.IPAM.Config[i] = &IPAMConfig{
|
||||
Subnet: c.Subnet,
|
||||
Gateway: c.Gateway,
|
||||
Range: c.IPRange,
|
||||
}
|
||||
}
|
||||
n.Containers = make([]*NetworkContainer, 0, len(nr.Containers))
|
||||
for id, ep := range nr.Containers {
|
||||
n.Containers = append(n.Containers, &NetworkContainer{
|
||||
ID: id,
|
||||
Name: ep.Name,
|
||||
Mac: ep.MacAddress,
|
||||
IPv4: ep.IPv4Address,
|
||||
IPv6: ep.IPv6Address,
|
||||
})
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
type NetworkBiz interface {
|
||||
Search() ([]*Network, error)
|
||||
Find(name string) (network *Network, raw string, err error)
|
||||
@ -167,3 +96,74 @@ func (b *networkBiz) Disconnect(networkId, networkName, container string, user w
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Network struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Created string `json:"created"`
|
||||
Driver string `json:"driver"`
|
||||
Scope string `json:"scope"`
|
||||
Internal bool `json:"internal"`
|
||||
Attachable bool `json:"attachable"`
|
||||
Ingress bool `json:"ingress"`
|
||||
IPv6 bool `json:"ipv6"`
|
||||
IPAM struct {
|
||||
Driver string `json:"driver"`
|
||||
Options data.Options `json:"options"`
|
||||
Config []*IPAMConfig `json:"config"`
|
||||
} `json:"ipam"`
|
||||
Options data.Options `json:"options"`
|
||||
Labels data.Options `json:"labels"`
|
||||
Containers []*NetworkContainer `json:"containers"`
|
||||
}
|
||||
|
||||
type IPAMConfig struct {
|
||||
Subnet string `json:"subnet,omitempty"`
|
||||
Gateway string `json:"gateway,omitempty"`
|
||||
Range string `json:"range,omitempty"`
|
||||
}
|
||||
|
||||
type NetworkContainer struct {
|
||||
ID string `json:"id"` // container id
|
||||
Name string `json:"name"` // container name
|
||||
Mac string `json:"mac"` // mac address
|
||||
IPv4 string `json:"ipv4"` // IPv4 address
|
||||
IPv6 string `json:"ipv6"` // IPv6 address
|
||||
}
|
||||
|
||||
func newNetwork(nr *types.NetworkResource) *Network {
|
||||
n := &Network{
|
||||
ID: nr.ID,
|
||||
Name: nr.Name,
|
||||
Created: formatTime(nr.Created),
|
||||
Driver: nr.Driver,
|
||||
Scope: nr.Scope,
|
||||
Internal: nr.Internal,
|
||||
Attachable: nr.Attachable,
|
||||
Ingress: nr.Ingress,
|
||||
IPv6: nr.EnableIPv6,
|
||||
Options: mapToOptions(nr.Options),
|
||||
Labels: mapToOptions(nr.Labels),
|
||||
}
|
||||
n.IPAM.Driver = nr.IPAM.Driver
|
||||
n.IPAM.Options = mapToOptions(nr.IPAM.Options)
|
||||
n.IPAM.Config = make([]*IPAMConfig, len(nr.IPAM.Config))
|
||||
for i, c := range nr.IPAM.Config {
|
||||
n.IPAM.Config[i] = &IPAMConfig{
|
||||
Subnet: c.Subnet,
|
||||
Gateway: c.Gateway,
|
||||
Range: c.IPRange,
|
||||
}
|
||||
}
|
||||
n.Containers = make([]*NetworkContainer, 0, len(nr.Containers))
|
||||
for id, ep := range nr.Containers {
|
||||
n.Containers = append(n.Containers, &NetworkContainer{
|
||||
ID: id,
|
||||
Name: ep.Name,
|
||||
Mac: ep.MacAddress,
|
||||
IPv4: ep.IPv4Address,
|
||||
IPv6: ep.IPv6Address,
|
||||
})
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
110
biz/node.go
110
biz/node.go
@ -9,61 +9,6 @@ import (
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
)
|
||||
|
||||
type Node struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Hostname string `json:"hostname"`
|
||||
Version uint64 `json:"version"`
|
||||
Role swarm.NodeRole `json:"role"`
|
||||
Availability swarm.NodeAvailability `json:"availability"`
|
||||
EngineVersion string `json:"engineVersion"`
|
||||
Architecture string `json:"arch"`
|
||||
OS string `json:"os"`
|
||||
CPU int64 `json:"cpu"`
|
||||
Memory float32 `json:"memory"`
|
||||
Address string `json:"address"`
|
||||
State swarm.NodeState `json:"state"`
|
||||
Manager *NodeManager `json:"manager,omitempty"`
|
||||
Labels data.Options `json:"labels,omitempty"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type NodeManager struct {
|
||||
Leader bool `json:"leader,omitempty"`
|
||||
Reachability swarm.Reachability `json:"reachability,omitempty"`
|
||||
Addr string `json:"addr,omitempty"`
|
||||
}
|
||||
|
||||
func newNode(sn *swarm.Node) *Node {
|
||||
n := &Node{
|
||||
ID: sn.ID,
|
||||
Name: sn.Spec.Name,
|
||||
Hostname: sn.Description.Hostname,
|
||||
Version: sn.Version.Index,
|
||||
Role: sn.Spec.Role,
|
||||
Availability: sn.Spec.Availability,
|
||||
EngineVersion: sn.Description.Engine.EngineVersion,
|
||||
Architecture: sn.Description.Platform.Architecture,
|
||||
OS: sn.Description.Platform.OS,
|
||||
CPU: sn.Description.Resources.NanoCPUs / 1e9,
|
||||
Memory: float32(sn.Description.Resources.MemoryBytes>>20) / 1024,
|
||||
Address: sn.Status.Addr,
|
||||
State: sn.Status.State,
|
||||
Labels: mapToOptions(sn.Spec.Labels),
|
||||
CreatedAt: formatTime(sn.CreatedAt),
|
||||
UpdatedAt: formatTime(sn.UpdatedAt),
|
||||
}
|
||||
if n.Role == swarm.NodeRoleManager {
|
||||
n.Manager = &NodeManager{
|
||||
Leader: sn.ManagerStatus.Leader,
|
||||
Reachability: sn.ManagerStatus.Reachability,
|
||||
Addr: sn.ManagerStatus.Addr,
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
type NodeBiz interface {
|
||||
Search() ([]*Node, error)
|
||||
Find(id string) (node *Node, raw string, err error)
|
||||
@ -129,3 +74,58 @@ func (b *nodeBiz) Update(n *Node, user web.User) (err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Hostname string `json:"hostname"`
|
||||
Version uint64 `json:"version"`
|
||||
Role swarm.NodeRole `json:"role"`
|
||||
Availability swarm.NodeAvailability `json:"availability"`
|
||||
EngineVersion string `json:"engineVersion"`
|
||||
Architecture string `json:"arch"`
|
||||
OS string `json:"os"`
|
||||
CPU int64 `json:"cpu"`
|
||||
Memory float32 `json:"memory"`
|
||||
Address string `json:"address"`
|
||||
State swarm.NodeState `json:"state"`
|
||||
Manager *NodeManager `json:"manager,omitempty"`
|
||||
Labels data.Options `json:"labels,omitempty"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type NodeManager struct {
|
||||
Leader bool `json:"leader,omitempty"`
|
||||
Reachability swarm.Reachability `json:"reachability,omitempty"`
|
||||
Addr string `json:"addr,omitempty"`
|
||||
}
|
||||
|
||||
func newNode(sn *swarm.Node) *Node {
|
||||
n := &Node{
|
||||
ID: sn.ID,
|
||||
Name: sn.Spec.Name,
|
||||
Hostname: sn.Description.Hostname,
|
||||
Version: sn.Version.Index,
|
||||
Role: sn.Spec.Role,
|
||||
Availability: sn.Spec.Availability,
|
||||
EngineVersion: sn.Description.Engine.EngineVersion,
|
||||
Architecture: sn.Description.Platform.Architecture,
|
||||
OS: sn.Description.Platform.OS,
|
||||
CPU: sn.Description.Resources.NanoCPUs / 1e9,
|
||||
Memory: float32(sn.Description.Resources.MemoryBytes>>20) / 1024,
|
||||
Address: sn.Status.Addr,
|
||||
State: sn.Status.State,
|
||||
Labels: mapToOptions(sn.Spec.Labels),
|
||||
CreatedAt: formatTime(sn.CreatedAt),
|
||||
UpdatedAt: formatTime(sn.UpdatedAt),
|
||||
}
|
||||
if n.Role == swarm.NodeRoleManager {
|
||||
n.Manager = &NodeManager{
|
||||
Leader: sn.ManagerStatus.Leader,
|
||||
Reachability: sn.ManagerStatus.Reachability,
|
||||
Addr: sn.ManagerStatus.Addr,
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/cuigh/auxo/net/web"
|
||||
"github.com/cuigh/swirl/dao"
|
||||
@ -13,12 +12,12 @@ import (
|
||||
)
|
||||
|
||||
type RegistryBiz interface {
|
||||
Search() ([]*Registry, error)
|
||||
Find(id string) (*Registry, error)
|
||||
Search() ([]*model.Registry, error)
|
||||
Find(id string) (*model.Registry, error)
|
||||
GetAuth(url string) (auth string, err error)
|
||||
Delete(id, name string, user web.User) (err error)
|
||||
Create(registry *Registry, user web.User) (err error)
|
||||
Update(registry *Registry, user web.User) (err error)
|
||||
Create(registry *model.Registry, user web.User) (err error)
|
||||
Update(registry *model.Registry, user web.User) (err error)
|
||||
}
|
||||
|
||||
func NewRegistry(d dao.Interface, eb EventBiz) RegistryBiz {
|
||||
@ -30,13 +29,11 @@ type registryBiz struct {
|
||||
eb EventBiz
|
||||
}
|
||||
|
||||
func (b *registryBiz) Create(registry *Registry, user web.User) (err error) {
|
||||
r := registry.Convert()
|
||||
func (b *registryBiz) Create(r *model.Registry, user web.User) (err error) {
|
||||
r.ID = createId()
|
||||
r.CreatedAt = time.Now()
|
||||
r.CreatedAt = now()
|
||||
r.UpdatedAt = r.CreatedAt
|
||||
r.CreatedBy.ID = user.ID()
|
||||
r.CreatedBy.Name = user.Name()
|
||||
r.CreatedBy = newOperator(user)
|
||||
r.UpdatedBy = r.CreatedBy
|
||||
|
||||
err = b.d.RegistryCreate(context.TODO(), r)
|
||||
@ -46,32 +43,30 @@ func (b *registryBiz) Create(registry *Registry, user web.User) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (b *registryBiz) Update(registry *Registry, user web.User) (err error) {
|
||||
r := registry.Convert()
|
||||
r.UpdatedAt = time.Now()
|
||||
r.UpdatedBy.ID = user.ID()
|
||||
r.UpdatedBy.Name = user.Name()
|
||||
func (b *registryBiz) Update(r *model.Registry, user web.User) (err error) {
|
||||
r.UpdatedAt = now()
|
||||
r.UpdatedBy = newOperator(user)
|
||||
err = b.d.RegistryUpdate(context.TODO(), r)
|
||||
if err == nil {
|
||||
b.eb.CreateRegistry(EventActionUpdate, registry.ID, registry.Name, user)
|
||||
b.eb.CreateRegistry(EventActionUpdate, r.ID, r.Name, user)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *registryBiz) Search() (registries []*Registry, err error) {
|
||||
var list []*model.Registry
|
||||
if list, err = b.d.RegistryGetAll(context.TODO()); err == nil {
|
||||
for _, r := range list {
|
||||
registries = append(registries, newRegistry(r))
|
||||
func (b *registryBiz) Search() (registries []*model.Registry, err error) {
|
||||
registries, err = b.d.RegistryGetAll(context.TODO())
|
||||
if err == nil {
|
||||
for _, r := range registries {
|
||||
r.Password = ""
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *registryBiz) Find(id string) (registry *Registry, err error) {
|
||||
var r *model.Registry
|
||||
if r, err = b.d.RegistryGet(context.TODO(), id); err == nil {
|
||||
registry = newRegistry(r)
|
||||
func (b *registryBiz) Find(id string) (registry *model.Registry, err error) {
|
||||
registry, err = b.d.RegistryGet(context.TODO(), id)
|
||||
if err == nil {
|
||||
registry.Password = ""
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -101,43 +96,3 @@ func (b *registryBiz) Delete(id, name string, user web.User) (err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Registry struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name" valid:"required"`
|
||||
URL string `json:"url" valid:"required,url"`
|
||||
Username string `json:"username" valid:"required"`
|
||||
Password string `json:"password" copier:"-"`
|
||||
CreatedAt string `json:"createdAt,omitempty" copier:"-"`
|
||||
UpdatedAt string `json:"updatedAt,omitempty" copier:"-"`
|
||||
CreatedBy model.Operator `json:"createdBy" bson:"created_by"`
|
||||
UpdatedBy model.Operator `json:"updatedBy" bson:"updated_by"`
|
||||
}
|
||||
|
||||
func newRegistry(r *model.Registry) *Registry {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &Registry{
|
||||
ID: r.ID,
|
||||
Name: r.Name,
|
||||
URL: r.URL,
|
||||
Username: r.Username,
|
||||
CreatedAt: formatTime(r.CreatedAt),
|
||||
UpdatedAt: formatTime(r.UpdatedAt),
|
||||
CreatedBy: r.CreatedBy,
|
||||
UpdatedBy: r.UpdatedBy,
|
||||
//Password: r.Password, // omit password
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Registry) Convert() *model.Registry {
|
||||
return &model.Registry{
|
||||
ID: r.ID,
|
||||
Name: r.Name,
|
||||
URL: r.URL,
|
||||
Username: r.Username,
|
||||
Password: r.Password,
|
||||
}
|
||||
}
|
||||
|
66
biz/role.go
66
biz/role.go
@ -2,43 +2,18 @@ package biz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/cuigh/auxo/net/web"
|
||||
"github.com/cuigh/swirl/dao"
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
type Role struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty" valid:"required"`
|
||||
Description string `json:"desc,omitempty"`
|
||||
Perms []string `json:"perms,omitempty"`
|
||||
CreatedAt string `json:"createdAt,omitempty"`
|
||||
UpdatedAt string `json:"updatedAt,omitempty"`
|
||||
CreatedBy model.Operator `json:"createdBy" bson:"created_by"`
|
||||
UpdatedBy model.Operator `json:"updatedBy" bson:"updated_by"`
|
||||
}
|
||||
|
||||
func newRole(r *model.Role) *Role {
|
||||
return &Role{
|
||||
ID: r.ID,
|
||||
Name: r.Name,
|
||||
Description: r.Description,
|
||||
Perms: r.Perms,
|
||||
CreatedAt: formatTime(r.CreatedAt),
|
||||
UpdatedAt: formatTime(r.UpdatedAt),
|
||||
CreatedBy: r.CreatedBy,
|
||||
UpdatedBy: r.UpdatedBy,
|
||||
}
|
||||
}
|
||||
|
||||
type RoleBiz interface {
|
||||
Search(name string) ([]*Role, error)
|
||||
Find(id string) (role *Role, err error)
|
||||
Create(role *Role, user web.User) (err error)
|
||||
Search(name string) ([]*model.Role, error)
|
||||
Find(id string) (role *model.Role, err error)
|
||||
Create(role *model.Role, user web.User) (err error)
|
||||
Delete(id, name string, user web.User) (err error)
|
||||
Update(r *Role, user web.User) (err error)
|
||||
Update(r *model.Role, user web.User) (err error)
|
||||
}
|
||||
|
||||
func NewRole(d dao.Interface, eb EventBiz) RoleBiz {
|
||||
@ -50,26 +25,21 @@ type roleBiz struct {
|
||||
eb EventBiz
|
||||
}
|
||||
|
||||
func (b *roleBiz) Search(name string) (roles []*Role, err error) {
|
||||
var list []*model.Role
|
||||
list, err = b.d.RoleSearch(context.TODO(), name)
|
||||
if err == nil {
|
||||
for _, r := range list {
|
||||
roles = append(roles, newRole(r))
|
||||
}
|
||||
}
|
||||
return
|
||||
func (b *roleBiz) Search(name string) (roles []*model.Role, err error) {
|
||||
return b.d.RoleSearch(context.TODO(), name)
|
||||
}
|
||||
|
||||
func (b *roleBiz) Create(role *Role, user web.User) (err error) {
|
||||
func (b *roleBiz) Create(role *model.Role, user web.User) (err error) {
|
||||
r := &model.Role{
|
||||
ID: createId(),
|
||||
Name: role.Name,
|
||||
Description: role.Description,
|
||||
Perms: role.Perms,
|
||||
CreatedAt: time.Now(),
|
||||
CreatedAt: now(),
|
||||
CreatedBy: newOperator(user),
|
||||
}
|
||||
r.UpdatedAt = r.CreatedAt
|
||||
r.UpdatedBy = r.CreatedBy
|
||||
err = b.d.RoleCreate(context.TODO(), r)
|
||||
if err == nil {
|
||||
b.eb.CreateRole(EventActionCreate, r.ID, role.Name, user)
|
||||
@ -85,25 +55,19 @@ func (b *roleBiz) Delete(id, name string, user web.User) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (b *roleBiz) Find(id string) (role *Role, err error) {
|
||||
var r *model.Role
|
||||
r, err = b.d.RoleGet(context.TODO(), id)
|
||||
if r != nil {
|
||||
role = newRole(r)
|
||||
}
|
||||
return
|
||||
func (b *roleBiz) Find(id string) (role *model.Role, err error) {
|
||||
return b.d.RoleGet(context.TODO(), id)
|
||||
}
|
||||
|
||||
func (b *roleBiz) Update(role *Role, user web.User) (err error) {
|
||||
func (b *roleBiz) Update(role *model.Role, user web.User) (err error) {
|
||||
r := &model.Role{
|
||||
ID: role.ID,
|
||||
Name: role.Name,
|
||||
Description: role.Description,
|
||||
Perms: role.Perms,
|
||||
UpdatedAt: time.Now(),
|
||||
UpdatedAt: now(),
|
||||
UpdatedBy: newOperator(user),
|
||||
}
|
||||
r.UpdatedBy.ID = user.ID()
|
||||
r.UpdatedBy.Name = user.Name()
|
||||
err = b.d.RoleUpdate(context.TODO(), r)
|
||||
if err == nil {
|
||||
b.eb.CreateRole(EventActionUpdate, role.ID, role.Name, user)
|
||||
|
@ -9,39 +9,6 @@ import (
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
)
|
||||
|
||||
type Secret struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Version uint64 `json:"version"`
|
||||
Data string `json:"data"`
|
||||
Labels data.Options `json:"labels,omitempty"`
|
||||
Driver Driver `json:"driver"`
|
||||
Templating Driver `json:"templating"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func newSecret(c *swarm.Secret) *Secret {
|
||||
secret := &Secret{
|
||||
ID: c.ID,
|
||||
Name: c.Spec.Name,
|
||||
Version: c.Version.Index,
|
||||
Data: string(c.Spec.Data),
|
||||
Labels: mapToOptions(c.Spec.Labels),
|
||||
CreatedAt: formatTime(c.CreatedAt),
|
||||
UpdatedAt: formatTime(c.UpdatedAt),
|
||||
}
|
||||
if c.Spec.Driver != nil {
|
||||
secret.Driver.Name = c.Spec.Driver.Name
|
||||
secret.Driver.Options = mapToOptions(c.Spec.Driver.Options)
|
||||
}
|
||||
if c.Spec.Templating != nil {
|
||||
secret.Templating.Name = c.Spec.Templating.Name
|
||||
secret.Templating.Options = mapToOptions(c.Spec.Templating.Options)
|
||||
}
|
||||
return secret
|
||||
}
|
||||
|
||||
type SecretBiz interface {
|
||||
Search(name string, pageIndex, pageSize int) (secrets []*Secret, total int, err error)
|
||||
Find(id string) (secret *Secret, raw string, err error)
|
||||
@ -146,3 +113,36 @@ func (b *secretBiz) Update(c *Secret, user web.User) (err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Secret struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Version uint64 `json:"version"`
|
||||
Data string `json:"data"`
|
||||
Labels data.Options `json:"labels,omitempty"`
|
||||
Driver Driver `json:"driver"`
|
||||
Templating Driver `json:"templating"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func newSecret(c *swarm.Secret) *Secret {
|
||||
secret := &Secret{
|
||||
ID: c.ID,
|
||||
Name: c.Spec.Name,
|
||||
Version: c.Version.Index,
|
||||
Data: string(c.Spec.Data),
|
||||
Labels: mapToOptions(c.Spec.Labels),
|
||||
CreatedAt: formatTime(c.CreatedAt),
|
||||
UpdatedAt: formatTime(c.UpdatedAt),
|
||||
}
|
||||
if c.Spec.Driver != nil {
|
||||
secret.Driver.Name = c.Spec.Driver.Name
|
||||
secret.Driver.Options = mapToOptions(c.Spec.Driver.Options)
|
||||
}
|
||||
if c.Spec.Templating != nil {
|
||||
secret.Templating.Name = c.Spec.Templating.Name
|
||||
secret.Templating.Options = mapToOptions(c.Spec.Templating.Options)
|
||||
}
|
||||
return secret
|
||||
}
|
||||
|
72
biz/stack.go
72
biz/stack.go
@ -3,7 +3,6 @@ package biz
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cuigh/auxo/errors"
|
||||
"github.com/cuigh/auxo/net/web"
|
||||
@ -15,13 +14,13 @@ import (
|
||||
)
|
||||
|
||||
type StackBiz interface {
|
||||
Search(name, filter string) (stacks []*Stack, err error)
|
||||
Find(name string) (stack *Stack, err error)
|
||||
Search(name, filter string) (stacks []*model.Stack, err error)
|
||||
Find(name string) (stack *model.Stack, err error)
|
||||
Delete(name string, user web.User) (err error)
|
||||
Shutdown(name string, user web.User) (err error)
|
||||
Deploy(name string, user web.User) (err error)
|
||||
Create(s *Stack, user web.User) (err error)
|
||||
Update(s *Stack, user web.User) (err error)
|
||||
Create(s *model.Stack, user web.User) (err error)
|
||||
Update(s *model.Stack, user web.User) (err error)
|
||||
}
|
||||
|
||||
func NewStack(d *docker.Docker, s dao.Interface, eb EventBiz) StackBiz {
|
||||
@ -34,7 +33,7 @@ type stackBiz struct {
|
||||
eb EventBiz
|
||||
}
|
||||
|
||||
func (b *stackBiz) Search(name, filter string) (stacks []*Stack, err error) {
|
||||
func (b *stackBiz) Search(name, filter string) (stacks []*model.Stack, err error) {
|
||||
var (
|
||||
activeStacks map[string][]string
|
||||
internalStacks []*model.Stack
|
||||
@ -53,8 +52,8 @@ func (b *stackBiz) Search(name, filter string) (stacks []*Stack, err error) {
|
||||
}
|
||||
|
||||
// merge stacks and definitions
|
||||
for _, s := range internalStacks {
|
||||
stack := newStack(s)
|
||||
for i := range internalStacks {
|
||||
stack := internalStacks[i]
|
||||
if services, ok := activeStacks[stack.Name]; ok {
|
||||
stack.Services = services
|
||||
delete(activeStacks, stack.Name)
|
||||
@ -64,7 +63,7 @@ func (b *stackBiz) Search(name, filter string) (stacks []*Stack, err error) {
|
||||
}
|
||||
}
|
||||
for n, services := range activeStacks {
|
||||
stack := &Stack{Name: n, Services: services}
|
||||
stack := &model.Stack{Name: n, Services: services}
|
||||
if !b.filter(stack, name, filter) {
|
||||
stacks = append(stacks, stack)
|
||||
}
|
||||
@ -72,17 +71,17 @@ func (b *stackBiz) Search(name, filter string) (stacks []*Stack, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (b *stackBiz) Find(name string) (stack *Stack, err error) {
|
||||
s, err := b.s.StackGet(context.TODO(), name)
|
||||
func (b *stackBiz) Find(name string) (s *model.Stack, err error) {
|
||||
s, err = b.s.StackGet(context.TODO(), name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if s == nil {
|
||||
return &Stack{ID: name, Name: name}, nil
|
||||
s = &model.Stack{Name: name}
|
||||
}
|
||||
return newStack(s), nil
|
||||
return
|
||||
}
|
||||
|
||||
func (b *stackBiz) filter(stack *Stack, name, filter string) bool {
|
||||
func (b *stackBiz) filter(stack *model.Stack, name, filter string) bool {
|
||||
if name != "" {
|
||||
if !strings.Contains(strings.ToLower(stack.Name), strings.ToLower(name)) {
|
||||
return true
|
||||
@ -107,15 +106,12 @@ func (b *stackBiz) filter(stack *Stack, name, filter string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (b *stackBiz) Create(s *Stack, user web.User) (err error) {
|
||||
func (b *stackBiz) Create(s *model.Stack, user web.User) (err error) {
|
||||
stack := &model.Stack{
|
||||
Name: s.Name,
|
||||
Content: s.Content,
|
||||
CreatedAt: time.Now(),
|
||||
CreatedBy: model.Operator{
|
||||
ID: user.ID(),
|
||||
Name: user.Name(),
|
||||
},
|
||||
CreatedAt: now(),
|
||||
CreatedBy: newOperator(user),
|
||||
}
|
||||
stack.UpdatedAt = stack.CreatedAt
|
||||
stack.UpdatedBy = stack.CreatedBy
|
||||
@ -126,18 +122,13 @@ func (b *stackBiz) Create(s *Stack, user web.User) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (b *stackBiz) Get(name string) (stack *model.Stack, err error) {
|
||||
return b.s.StackGet(context.TODO(), name)
|
||||
}
|
||||
|
||||
func (b *stackBiz) Update(s *Stack, user web.User) (err error) {
|
||||
func (b *stackBiz) Update(s *model.Stack, user web.User) (err error) {
|
||||
stack := &model.Stack{
|
||||
Name: s.Name,
|
||||
Content: s.Content,
|
||||
UpdatedAt: time.Now(),
|
||||
UpdatedAt: now(),
|
||||
UpdatedBy: newOperator(user),
|
||||
}
|
||||
stack.UpdatedBy.ID = user.ID()
|
||||
stack.UpdatedBy.Name = user.Name()
|
||||
err = b.s.StackUpdate(context.TODO(), stack)
|
||||
if err == nil {
|
||||
b.eb.CreateStack(EventActionUpdate, stack.Name, user)
|
||||
@ -200,28 +191,3 @@ func (b *stackBiz) Deploy(name string, user web.User) (err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Stack struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
Services []string `json:"services,omitempty"`
|
||||
Internal bool `json:"internal"`
|
||||
CreatedAt string `json:"createdAt,omitempty"`
|
||||
UpdatedAt string `json:"updatedAt,omitempty"`
|
||||
CreatedBy model.Operator `json:"createdBy,omitempty"`
|
||||
UpdatedBy model.Operator `json:"updatedBy,omitempty"`
|
||||
}
|
||||
|
||||
func newStack(s *model.Stack) *Stack {
|
||||
return &Stack{
|
||||
ID: s.Name,
|
||||
Name: s.Name,
|
||||
Content: s.Content,
|
||||
Internal: true,
|
||||
CreatedAt: formatTime(s.CreatedAt),
|
||||
UpdatedAt: formatTime(s.UpdatedAt),
|
||||
CreatedBy: s.CreatedBy,
|
||||
UpdatedBy: s.UpdatedBy,
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package biz
|
||||
import (
|
||||
"github.com/cuigh/auxo/app"
|
||||
"github.com/cuigh/auxo/data"
|
||||
"github.com/cuigh/auxo/errors"
|
||||
"github.com/cuigh/swirl/dao"
|
||||
"github.com/cuigh/swirl/misc"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
@ -12,23 +11,22 @@ import (
|
||||
type SystemBiz interface {
|
||||
Init() (err error)
|
||||
CheckState() (state *SystemState, err error)
|
||||
CreateAdmin(user *User) (err error)
|
||||
}
|
||||
|
||||
func NewSystem(d dao.Interface, ub UserBiz, sb SettingBiz, s *misc.Setting) SystemBiz {
|
||||
return &systemBiz{
|
||||
s: s,
|
||||
d: d,
|
||||
ub: ub,
|
||||
sb: sb,
|
||||
s: s,
|
||||
}
|
||||
}
|
||||
|
||||
type systemBiz struct {
|
||||
s *misc.Setting
|
||||
d dao.Interface
|
||||
ub UserBiz
|
||||
sb SettingBiz
|
||||
s *misc.Setting
|
||||
}
|
||||
|
||||
func (b *systemBiz) Init() (err error) {
|
||||
@ -51,21 +49,6 @@ func (b *systemBiz) CheckState() (state *SystemState, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (b *systemBiz) CreateAdmin(user *User) (err error) {
|
||||
user.Admin = true
|
||||
user.Type = UserTypeInternal
|
||||
|
||||
var count int
|
||||
if count, err = b.ub.Count(); err == nil {
|
||||
if count > 0 {
|
||||
err = errors.Coded(1, "system was already initialized")
|
||||
} else {
|
||||
_, err = b.ub.Create(user, nil)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type SystemState struct {
|
||||
Fresh bool `json:"fresh"`
|
||||
}
|
||||
|
114
biz/task.go
114
biz/task.go
@ -8,6 +8,63 @@ import (
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
)
|
||||
|
||||
type TaskBiz interface {
|
||||
Search(node, service, mode string, pageIndex, pageSize int) (tasks []*Task, total int, err error)
|
||||
Find(id string) (task *Task, raw string, err error)
|
||||
FetchLogs(id string, lines int, timestamps bool) (stdout, stderr string, err error)
|
||||
}
|
||||
|
||||
func NewTask(d *docker.Docker) TaskBiz {
|
||||
return &taskBiz{d: d}
|
||||
}
|
||||
|
||||
type taskBiz struct {
|
||||
d *docker.Docker
|
||||
}
|
||||
|
||||
func (b *taskBiz) Find(id string) (task *Task, raw string, err error) {
|
||||
var (
|
||||
t swarm.Task
|
||||
s swarm.Service
|
||||
r []byte
|
||||
)
|
||||
t, r, err = b.d.TaskInspect(context.TODO(), id)
|
||||
if err == nil {
|
||||
raw, err = indentJSON(r)
|
||||
}
|
||||
if err == nil {
|
||||
task = newTask(&t)
|
||||
if s, _, _ = b.d.ServiceInspect(context.TODO(), t.ServiceID, false); s.Spec.Name == "" {
|
||||
task.ServiceName = task.ServiceID
|
||||
} else {
|
||||
task.ServiceName = s.Spec.Name
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *taskBiz) Search(node, service, state string, pageIndex, pageSize int) (tasks []*Task, total int, err error) {
|
||||
var list []swarm.Task
|
||||
list, total, err = b.d.TaskList(context.TODO(), node, service, state, pageIndex, pageSize)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
tasks = make([]*Task, len(list))
|
||||
for i, t := range list {
|
||||
tasks[i] = newTask(&t)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *taskBiz) FetchLogs(id string, lines int, timestamps bool) (string, string, error) {
|
||||
stdout, stderr, err := b.d.TaskLogs(context.TODO(), id, lines, timestamps)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return stdout.String(), stderr.String(), nil
|
||||
}
|
||||
|
||||
type Task struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
@ -67,60 +124,3 @@ func newTask(t *swarm.Task) *Task {
|
||||
}
|
||||
return task
|
||||
}
|
||||
|
||||
type TaskBiz interface {
|
||||
Search(node, service, mode string, pageIndex, pageSize int) (tasks []*Task, total int, err error)
|
||||
Find(id string) (task *Task, raw string, err error)
|
||||
FetchLogs(id string, lines int, timestamps bool) (stdout, stderr string, err error)
|
||||
}
|
||||
|
||||
func NewTask(d *docker.Docker) TaskBiz {
|
||||
return &taskBiz{d: d}
|
||||
}
|
||||
|
||||
type taskBiz struct {
|
||||
d *docker.Docker
|
||||
}
|
||||
|
||||
func (b *taskBiz) Find(id string) (task *Task, raw string, err error) {
|
||||
var (
|
||||
t swarm.Task
|
||||
s swarm.Service
|
||||
r []byte
|
||||
)
|
||||
t, r, err = b.d.TaskInspect(context.TODO(), id)
|
||||
if err == nil {
|
||||
raw, err = indentJSON(r)
|
||||
}
|
||||
if err == nil {
|
||||
task = newTask(&t)
|
||||
if s, _, _ = b.d.ServiceInspect(context.TODO(), t.ServiceID, false); s.Spec.Name == "" {
|
||||
task.ServiceName = task.ServiceID
|
||||
} else {
|
||||
task.ServiceName = s.Spec.Name
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *taskBiz) Search(node, service, state string, pageIndex, pageSize int) (tasks []*Task, total int, err error) {
|
||||
var list []swarm.Task
|
||||
list, total, err = b.d.TaskList(context.TODO(), node, service, state, pageIndex, pageSize)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
tasks = make([]*Task, len(list))
|
||||
for i, t := range list {
|
||||
tasks[i] = newTask(&t)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *taskBiz) FetchLogs(id string, lines int, timestamps bool) (string, string, error) {
|
||||
stdout, stderr, err := b.d.TaskLogs(context.TODO(), id, lines, timestamps)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return stdout.String(), stderr.String(), nil
|
||||
}
|
||||
|
182
biz/user.go
182
biz/user.go
@ -2,16 +2,13 @@ package biz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/cuigh/auxo/data/guid"
|
||||
"github.com/cuigh/auxo/errors"
|
||||
"github.com/cuigh/auxo/net/web"
|
||||
"github.com/cuigh/auxo/security/passwd"
|
||||
"github.com/cuigh/swirl/dao"
|
||||
"github.com/cuigh/swirl/misc"
|
||||
"github.com/cuigh/swirl/model"
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -29,17 +26,17 @@ const (
|
||||
)
|
||||
|
||||
type UserBiz interface {
|
||||
Search(name, loginName, filter string, pageIndex, pageSize int) (users []*User, total int, err error)
|
||||
Create(user *User, ctxUser web.User) (id string, err error)
|
||||
Update(user *User, ctxUser web.User) (err error)
|
||||
FindByID(id string) (user *User, err error)
|
||||
FindByName(loginName string) (user *User, err error)
|
||||
Search(name, loginName, filter string, pageIndex, pageSize int) (users []*model.User, total int, err error)
|
||||
Create(user *model.User, ctxUser web.User) (id string, err error)
|
||||
Update(user *model.User, ctxUser web.User) (err error)
|
||||
FindByID(id string) (user *model.User, err error)
|
||||
FindByName(loginName string) (user *model.User, err error)
|
||||
FindPrivacy(loginName string) (privacy *UserPrivacy, err error)
|
||||
Count() (count int, err error)
|
||||
Delete(id, name string, user web.User) (err error)
|
||||
SetStatus(id string, status int32, user web.User) (err error)
|
||||
ModifyPassword(oldPwd, newPwd string, user web.User) (err error)
|
||||
ModifyProfile(user *User, ctxUser web.User) (err error)
|
||||
ModifyProfile(user *model.User, ctxUser web.User) (err error)
|
||||
}
|
||||
|
||||
func NewUser(d dao.Interface, eb EventBiz) UserBiz {
|
||||
@ -51,17 +48,14 @@ type userBiz struct {
|
||||
eb EventBiz
|
||||
}
|
||||
|
||||
func (b *userBiz) Search(name, loginName, filter string, pageIndex, pageSize int) (users []*User, total int, err error) {
|
||||
var (
|
||||
list []*model.User
|
||||
args = &model.UserSearchArgs{
|
||||
Name: name,
|
||||
LoginName: loginName,
|
||||
Status: -1,
|
||||
PageIndex: pageIndex,
|
||||
PageSize: pageSize,
|
||||
}
|
||||
)
|
||||
func (b *userBiz) Search(name, loginName, filter string, pageIndex, pageSize int) (users []*model.User, total int, err error) {
|
||||
var args = &model.UserSearchArgs{
|
||||
Name: name,
|
||||
LoginName: loginName,
|
||||
Status: -1,
|
||||
PageIndex: pageIndex,
|
||||
PageSize: pageSize,
|
||||
}
|
||||
|
||||
switch filter {
|
||||
case "admins":
|
||||
@ -72,31 +66,15 @@ func (b *userBiz) Search(name, loginName, filter string, pageIndex, pageSize int
|
||||
args.Status = UserStatusBlocked
|
||||
}
|
||||
|
||||
list, total, err = b.d.UserSearch(context.TODO(), args)
|
||||
if err == nil {
|
||||
for _, u := range list {
|
||||
users = append(users, newUser(u))
|
||||
}
|
||||
}
|
||||
return
|
||||
return b.d.UserSearch(context.TODO(), args)
|
||||
}
|
||||
|
||||
func (b *userBiz) FindByID(id string) (user *User, err error) {
|
||||
var u *model.User
|
||||
u, err = b.d.UserGet(context.TODO(), id)
|
||||
if u != nil {
|
||||
user = newUser(u)
|
||||
}
|
||||
return
|
||||
func (b *userBiz) FindByID(id string) (user *model.User, err error) {
|
||||
return b.d.UserGet(context.TODO(), id)
|
||||
}
|
||||
|
||||
func (b *userBiz) FindByName(loginName string) (user *User, err error) {
|
||||
var u *model.User
|
||||
u, err = b.d.UserGetByName(context.TODO(), loginName)
|
||||
if u != nil {
|
||||
user = newUser(u)
|
||||
}
|
||||
return
|
||||
func (b *userBiz) FindByName(loginName string) (user *model.User, err error) {
|
||||
return b.d.UserGetByName(context.TODO(), loginName)
|
||||
}
|
||||
|
||||
func (b *userBiz) FindPrivacy(loginName string) (privacy *UserPrivacy, err error) {
|
||||
@ -115,23 +93,17 @@ func (b *userBiz) FindPrivacy(loginName string) (privacy *UserPrivacy, err error
|
||||
return
|
||||
}
|
||||
|
||||
func (b *userBiz) Create(u *User, ctxUser web.User) (id string, err error) {
|
||||
user := &model.User{
|
||||
ID: createId(),
|
||||
Name: u.Name,
|
||||
LoginName: u.LoginName,
|
||||
Email: u.Email,
|
||||
Admin: u.Admin,
|
||||
Type: u.Type,
|
||||
Status: UserStatusActive,
|
||||
Roles: u.Roles,
|
||||
CreatedAt: time.Now(),
|
||||
CreatedBy: model.Operator{ID: ctxUser.ID(), Name: ctxUser.Name()},
|
||||
func (b *userBiz) Create(user *model.User, ctxUser web.User) (id string, err error) {
|
||||
user.ID = createId()
|
||||
user.Status = UserStatusActive
|
||||
user.CreatedAt = now()
|
||||
if ctxUser != nil {
|
||||
user.CreatedBy = newOperator(ctxUser)
|
||||
}
|
||||
user.UpdatedAt = user.CreatedAt
|
||||
user.UpdatedBy = user.CreatedBy
|
||||
if user.Type == UserTypeInternal {
|
||||
user.Password, user.Salt, err = passwd.Generate(u.Password)
|
||||
user.Password, user.Salt, err = passwd.Generate(user.Password)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -144,21 +116,11 @@ func (b *userBiz) Create(u *User, ctxUser web.User) (id string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (b *userBiz) Update(u *User, ctxUser web.User) (err error) {
|
||||
user := &model.User{
|
||||
ID: u.ID,
|
||||
Name: u.Name,
|
||||
LoginName: u.LoginName,
|
||||
Email: u.Email,
|
||||
Admin: u.Admin,
|
||||
Type: u.Type,
|
||||
Roles: u.Roles,
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
user.UpdatedBy.ID = ctxUser.ID()
|
||||
user.UpdatedBy.Name = ctxUser.Name()
|
||||
func (b *userBiz) Update(user *model.User, ctxUser web.User) (err error) {
|
||||
user.UpdatedAt = now()
|
||||
user.UpdatedBy = newOperator(ctxUser)
|
||||
if err = b.d.UserUpdate(context.TODO(), user); err == nil {
|
||||
b.eb.CreateUser(EventActionUpdate, u.LoginName, u.Name, ctxUser)
|
||||
b.eb.CreateUser(EventActionUpdate, user.LoginName, user.Name, ctxUser)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -167,8 +129,8 @@ func (b *userBiz) SetStatus(id string, status int32, user web.User) (err error)
|
||||
u := &model.User{
|
||||
ID: id,
|
||||
Status: status,
|
||||
UpdatedAt: time.Now(),
|
||||
UpdatedBy: model.Operator{ID: user.ID(), Name: user.Name()},
|
||||
UpdatedAt: now(),
|
||||
UpdatedBy: newOperator(user),
|
||||
}
|
||||
return b.d.UserUpdateStatus(context.TODO(), u)
|
||||
}
|
||||
@ -194,81 +156,49 @@ func (b *userBiz) ModifyPassword(oldPwd, newPwd string, user web.User) (err erro
|
||||
return errors.Coded(misc.ErrOldPasswordIncorrect, "current password is incorrect")
|
||||
}
|
||||
|
||||
u.Password, u.Salt, err = passwd.Generate(newPwd)
|
||||
if err != nil {
|
||||
if u.Password, u.Salt, err = passwd.Generate(newPwd); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
u.UpdatedAt = time.Now()
|
||||
u.UpdatedBy.ID = user.ID()
|
||||
u.UpdatedBy.Name = user.Name()
|
||||
err = b.d.UserUpdatePassword(context.TODO(), u)
|
||||
return
|
||||
u.UpdatedAt = now()
|
||||
u.UpdatedBy = newOperator(user)
|
||||
return b.d.UserUpdatePassword(context.TODO(), u)
|
||||
}
|
||||
|
||||
func (b *userBiz) ModifyProfile(u *User, user web.User) (err error) {
|
||||
return b.d.UserUpdateProfile(context.TODO(), &model.User{
|
||||
ID: user.ID(),
|
||||
Name: u.Name,
|
||||
LoginName: u.LoginName,
|
||||
Email: u.Email,
|
||||
UpdatedAt: time.Now(),
|
||||
UpdatedBy: model.Operator{ID: user.ID(), Name: user.Name()},
|
||||
})
|
||||
func (b *userBiz) ModifyProfile(u *model.User, user web.User) (err error) {
|
||||
u.ID = user.ID()
|
||||
u.UpdatedAt = now()
|
||||
u.UpdatedBy = newOperator(user)
|
||||
return b.d.UserUpdateProfile(context.TODO(), u)
|
||||
}
|
||||
|
||||
func (b *userBiz) Count() (count int, err error) {
|
||||
return b.d.UserCount(context.TODO())
|
||||
}
|
||||
|
||||
func (b *userBiz) UpdateSession(id string) (token string, err error) {
|
||||
session := &model.Session{
|
||||
UserID: id,
|
||||
Token: guid.New().String(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
session.Expires = session.UpdatedAt.Add(time.Hour * 24)
|
||||
err = b.d.SessionUpdate(context.TODO(), session)
|
||||
if err == nil {
|
||||
token = session.Token
|
||||
}
|
||||
return
|
||||
}
|
||||
//func (b *userBiz) UpdateSession(id string) (token string, err error) {
|
||||
// session := &model.Session{
|
||||
// UserID: id,
|
||||
// Token: guid.New().String(),
|
||||
// UpdatedAt: time.Now(),
|
||||
// }
|
||||
// session.Expires = session.UpdatedAt.Add(time.Hour * 24)
|
||||
// err = b.d.SessionUpdate(context.TODO(), session)
|
||||
// if err == nil {
|
||||
// token = session.Token
|
||||
// }
|
||||
// return
|
||||
//}
|
||||
|
||||
func (b *userBiz) GetSession(token string) (session *model.Session, err error) {
|
||||
return b.d.SessionGet(context.TODO(), token)
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name" valid:"required"`
|
||||
LoginName string `json:"loginName" valid:"required"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Email string `json:"email" valid:"required"`
|
||||
Admin bool `json:"admin"`
|
||||
Type string `json:"type"`
|
||||
Status int32 `json:"status,omitempty"`
|
||||
Roles []string `json:"roles,omitempty"`
|
||||
CreatedAt string `json:"createdAt,omitempty"`
|
||||
UpdatedAt string `json:"updatedAt,omitempty"`
|
||||
CreatedBy model.Operator `json:"createdBy"`
|
||||
UpdatedBy model.Operator `json:"updatedBy"`
|
||||
}
|
||||
|
||||
type UserPrivacy struct {
|
||||
ID string
|
||||
Name string
|
||||
Password string
|
||||
Salt string
|
||||
Password string `json:"-"`
|
||||
Salt string `json:"-"`
|
||||
Type string
|
||||
Status int32
|
||||
}
|
||||
|
||||
func newUser(u *model.User) *User {
|
||||
user := &User{
|
||||
CreatedAt: formatTime(u.CreatedAt),
|
||||
UpdatedAt: formatTime(u.UpdatedAt),
|
||||
}
|
||||
_ = copier.CopyWithOption(user, u, copier.Option{IgnoreEmpty: true, DeepCopy: true})
|
||||
return user
|
||||
}
|
||||
|
@ -11,41 +11,6 @@ import (
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
)
|
||||
|
||||
type Volume struct {
|
||||
Name string `json:"name"`
|
||||
Driver string `json:"driver,omitempty"`
|
||||
CustomDriver string `json:"customDriver,omitempty"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
MountPoint string `json:"mountPoint,omitempty"`
|
||||
Scope string `json:"scope"`
|
||||
Labels data.Options `json:"labels,omitempty"`
|
||||
Options data.Options `json:"options,omitempty"`
|
||||
Status map[string]interface{} `json:"status,omitempty"`
|
||||
RefCount int64 `json:"refCount"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
func newVolume(v *types.Volume) *Volume {
|
||||
createdAt, _ := time.Parse(time.RFC3339Nano, v.CreatedAt)
|
||||
vol := &Volume{
|
||||
Name: v.Name,
|
||||
Driver: v.Driver,
|
||||
CreatedAt: formatTime(createdAt),
|
||||
MountPoint: v.Mountpoint,
|
||||
Scope: v.Scope,
|
||||
Status: v.Status,
|
||||
Labels: mapToOptions(v.Labels),
|
||||
Options: mapToOptions(v.Options),
|
||||
RefCount: -1,
|
||||
Size: -1,
|
||||
}
|
||||
if v.UsageData != nil {
|
||||
vol.RefCount = v.UsageData.RefCount
|
||||
vol.Size = v.UsageData.Size
|
||||
}
|
||||
return vol
|
||||
}
|
||||
|
||||
type VolumeBiz interface {
|
||||
Search(name string, pageIndex, pageSize int) ([]*Volume, int, error)
|
||||
Find(name string) (volume *Volume, raw string, err error)
|
||||
@ -129,3 +94,38 @@ func (b *volumeBiz) Prune(user web.User) (deletedVolumes []string, reclaimedSpac
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Volume struct {
|
||||
Name string `json:"name"`
|
||||
Driver string `json:"driver,omitempty"`
|
||||
CustomDriver string `json:"customDriver,omitempty"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
MountPoint string `json:"mountPoint,omitempty"`
|
||||
Scope string `json:"scope"`
|
||||
Labels data.Options `json:"labels,omitempty"`
|
||||
Options data.Options `json:"options,omitempty"`
|
||||
Status map[string]interface{} `json:"status,omitempty"`
|
||||
RefCount int64 `json:"refCount"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
func newVolume(v *types.Volume) *Volume {
|
||||
createdAt, _ := time.Parse(time.RFC3339Nano, v.CreatedAt)
|
||||
vol := &Volume{
|
||||
Name: v.Name,
|
||||
Driver: v.Driver,
|
||||
CreatedAt: formatTime(createdAt),
|
||||
MountPoint: v.Mountpoint,
|
||||
Scope: v.Scope,
|
||||
Status: v.Status,
|
||||
Labels: mapToOptions(v.Labels),
|
||||
Options: mapToOptions(v.Options),
|
||||
RefCount: -1,
|
||||
Size: -1,
|
||||
}
|
||||
if v.UsageData != nil {
|
||||
vol.RefCount = v.UsageData.RefCount
|
||||
vol.Size = v.UsageData.Size
|
||||
}
|
||||
return vol
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package bolt
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/cuigh/swirl/misc"
|
||||
"github.com/cuigh/swirl/model"
|
||||
@ -33,7 +34,7 @@ func (d *Dao) ChartSearch(ctx context.Context, args *model.ChartSearchArgs) (cha
|
||||
if err == nil {
|
||||
count = len(charts)
|
||||
sort.Slice(charts, func(i, j int) bool {
|
||||
return charts[i].CreatedAt.After(charts[j].UpdatedAt)
|
||||
return time.Time(charts[i].UpdatedAt).After(time.Time(charts[j].UpdatedAt))
|
||||
})
|
||||
start, end := misc.Page(count, args.PageIndex, args.PageSize)
|
||||
charts = charts[start:end]
|
||||
|
@ -3,6 +3,7 @@ package bolt
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/cuigh/swirl/misc"
|
||||
"github.com/cuigh/swirl/model"
|
||||
@ -34,7 +35,7 @@ func (d *Dao) EventSearch(ctx context.Context, args *model.EventSearchArgs) (eve
|
||||
if err == nil {
|
||||
count = len(events)
|
||||
sort.Slice(events, func(i, j int) bool {
|
||||
return events[i].Time.After(events[j].Time)
|
||||
return time.Time(events[i].Time).After(time.Time(events[j].Time))
|
||||
})
|
||||
start, end := misc.Page(count, args.PageIndex, args.PageSize)
|
||||
events = events[start:end]
|
||||
|
@ -40,7 +40,7 @@ func (d *Dao) RoleGet(ctx context.Context, id string) (role *model.Role, err err
|
||||
}
|
||||
|
||||
func (d *Dao) RoleUpdate(ctx context.Context, role *model.Role) (err error) {
|
||||
old := &model.Registry{}
|
||||
old := &model.Role{}
|
||||
return d.update(Role, role.ID, old, func() interface{} {
|
||||
role.CreatedAt = old.CreatedAt
|
||||
role.CreatedBy = old.CreatedBy
|
||||
|
@ -127,11 +127,13 @@ func (d *Dao) UserUpdatePassword(ctx context.Context, user *model.User) (err err
|
||||
|
||||
func (d *Dao) SessionGet(ctx context.Context, token string) (session *model.Session, err error) {
|
||||
s := &model.Session{}
|
||||
found, err := d.find(Session, s, func() bool { return s.Token == token })
|
||||
if found {
|
||||
return s, nil
|
||||
err = d.get(Session, token, s)
|
||||
if err == ErrNoRecords {
|
||||
return nil, nil
|
||||
} else if err != nil {
|
||||
s = nil
|
||||
}
|
||||
return nil, err
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) SessionUpdate(ctx context.Context, session *model.Session) (err error) {
|
||||
|
2
main.go
2
main.go
@ -30,7 +30,7 @@ var (
|
||||
|
||||
func main() {
|
||||
app.Name = "Swirl"
|
||||
app.Version = "1.0.0beta3"
|
||||
app.Version = "1.0.0beta4"
|
||||
app.Desc = "A web management UI for Docker, focused on swarm cluster"
|
||||
app.Action = func(ctx *app.Context) error {
|
||||
return run.Pipeline(misc.LoadOptions, initSystem, scaler.Start, startServer)
|
||||
|
@ -7,6 +7,7 @@ const (
|
||||
ErrAccountDisabled = 1002
|
||||
ErrOldPasswordIncorrect = 1003
|
||||
ErrExternalStack = 1004
|
||||
ErrSystemInitialized = 1005
|
||||
)
|
||||
|
||||
func Error(code int32, err error) error {
|
||||
|
234
model/model.go
234
model/model.go
@ -59,8 +59,8 @@ type Operator struct {
|
||||
// Setting represents the options of swirl.
|
||||
type Setting struct {
|
||||
ID string `json:"id" bson:"_id"`
|
||||
Options []*SettingOption `json:"options" bson:"options,omitempty"`
|
||||
UpdatedAt time.Time `bson:"updated_at" json:"updatedAt,omitempty"`
|
||||
Options []*SettingOption `json:"options" bson:"options"`
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updated_at"`
|
||||
UpdatedBy Operator `json:"updatedBy" bson:"updated_by"`
|
||||
}
|
||||
|
||||
@ -71,31 +71,31 @@ type SettingOption struct {
|
||||
}
|
||||
|
||||
type Role struct {
|
||||
ID string `bson:"_id" json:"id,omitempty"`
|
||||
Name string `bson:"name" json:"name,omitempty" valid:"required"`
|
||||
Description string `bson:"desc" json:"desc,omitempty"`
|
||||
Perms []string `bson:"perms" json:"perms,omitempty"`
|
||||
CreatedAt time.Time `bson:"created_at" json:"created_at,omitempty"`
|
||||
UpdatedAt time.Time `bson:"updated_at" json:"updated_at,omitempty"`
|
||||
CreatedBy Operator `json:"createdBy" bson:"created_by"`
|
||||
UpdatedBy Operator `json:"updatedBy" bson:"updated_by"`
|
||||
ID string `json:"id,omitempty" bson:"_id"`
|
||||
Name string `json:"name,omitempty" bson:"name" valid:"required"`
|
||||
Description string `json:"desc,omitempty" bson:"desc,omitempty"`
|
||||
Perms []string `json:"perms,omitempty" bson:"perms,omitempty"`
|
||||
UpdatedAt Time `json:"updatedAt" bson:"updated_at"`
|
||||
CreatedAt Time `json:"createdAt" bson:"created_at"`
|
||||
CreatedBy Operator `json:"createdBy" bson:"created_by"`
|
||||
UpdatedBy Operator `json:"updatedBy" bson:"updated_by"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID string `bson:"_id" json:"id,omitempty"`
|
||||
Name string `bson:"name" json:"name,omitempty" valid:"required"`
|
||||
LoginName string `bson:"login_name" json:"loginName,omitempty" valid:"required"`
|
||||
Password string `bson:"password" json:"-"`
|
||||
Salt string `bson:"salt" json:"-"`
|
||||
Email string `bson:"email" json:"email,omitempty" valid:"required"`
|
||||
Admin bool `bson:"admin" json:"admin,omitempty"`
|
||||
Type string `bson:"type" json:"type,omitempty"`
|
||||
Status int32 `bson:"status" json:"status,omitempty"`
|
||||
Roles []string `bson:"roles" json:"roles,omitempty"`
|
||||
CreatedAt time.Time `bson:"created_at" json:"createdAt,omitempty"`
|
||||
UpdatedAt time.Time `bson:"updated_at" json:"updatedAt,omitempty"`
|
||||
CreatedBy Operator `json:"createdBy" bson:"created_by"`
|
||||
UpdatedBy Operator `json:"updatedBy" bson:"updated_by"`
|
||||
ID string `json:"id,omitempty" bson:"_id"`
|
||||
Name string `json:"name" bson:"name" valid:"required"`
|
||||
LoginName string `json:"loginName" bson:"login_name" valid:"required"`
|
||||
Password string `json:"-" bson:"password"`
|
||||
Salt string `json:"-" bson:"salt"`
|
||||
Email string `json:"email" bson:"email" valid:"required"`
|
||||
Admin bool `json:"admin" bson:"admin"`
|
||||
Type string `json:"type" bson:"type"`
|
||||
Status int32 `json:"status" bson:"status"`
|
||||
Roles []string `json:"roles,omitempty" bson:"roles,omitempty"`
|
||||
CreatedAt Time `json:"createdAt" bson:"created_at"`
|
||||
UpdatedAt Time `json:"updatedAt" bson:"updated_at"`
|
||||
CreatedBy Operator `json:"createdBy" bson:"created_by"`
|
||||
UpdatedBy Operator `json:"updatedBy" bson:"updated_by"`
|
||||
}
|
||||
|
||||
type UserSearchArgs struct {
|
||||
@ -108,15 +108,15 @@ type UserSearchArgs struct {
|
||||
}
|
||||
|
||||
type Registry struct {
|
||||
ID string `bson:"_id" json:"id"`
|
||||
Name string `bson:"name" json:"name"`
|
||||
URL string `bson:"url" json:"url"`
|
||||
Username string `bson:"username" json:"username"`
|
||||
Password string `bson:"password" json:"-"`
|
||||
CreatedAt time.Time `bson:"created_at" json:"createdAt,omitempty"`
|
||||
UpdatedAt time.Time `bson:"updated_at" json:"updatedAt,omitempty"`
|
||||
CreatedBy Operator `json:"createdBy" bson:"created_by"`
|
||||
UpdatedBy Operator `json:"updatedBy" bson:"updated_by"`
|
||||
ID string `json:"id" bson:"_id"`
|
||||
Name string `json:"name" bson:"name"`
|
||||
URL string `json:"url" bson:"url"`
|
||||
Username string `json:"username" bson:"username"`
|
||||
Password string `json:"password,omitempty" bson:"password,omitempty"`
|
||||
CreatedAt Time `json:"createdAt" bson:"created_at"`
|
||||
UpdatedAt Time `json:"updatedAt" bson:"updated_at"`
|
||||
CreatedBy Operator `json:"createdBy" bson:"created_by"`
|
||||
UpdatedBy Operator `json:"updatedBy" bson:"updated_by"`
|
||||
}
|
||||
|
||||
func (r *Registry) Match(image string) bool {
|
||||
@ -136,25 +136,25 @@ func (r *Registry) GetEncodedAuth() string {
|
||||
}
|
||||
|
||||
type Stack struct {
|
||||
Name string `bson:"_id" json:"name,omitempty"`
|
||||
Content string `bson:"content" json:"content,omitempty" bind:"content=form,content=file"`
|
||||
Services []string `bson:"-" json:"services,omitempty"`
|
||||
Internal bool `bson:"-" json:"internal"`
|
||||
CreatedAt time.Time `bson:"created_at" json:"createdAt,omitempty"`
|
||||
UpdatedAt time.Time `bson:"updated_at" json:"updatedAt,omitempty"`
|
||||
CreatedBy Operator `json:"createdBy" bson:"created_by"`
|
||||
UpdatedBy Operator `json:"updatedBy" bson:"updated_by"`
|
||||
Name string `json:"name" bson:"_id"`
|
||||
Content string `json:"content" bson:"content"`
|
||||
Services []string `json:"services,omitempty" bson:"-"`
|
||||
Internal bool `json:"internal" bson:"-"`
|
||||
CreatedAt Time `json:"createdAt" bson:"created_at"`
|
||||
UpdatedAt Time `json:"updatedAt" bson:"updated_at"`
|
||||
CreatedBy Operator `json:"createdBy" bson:"created_by"`
|
||||
UpdatedBy Operator `json:"updatedBy" bson:"updated_by"`
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
ID primitive.ObjectID `bson:"_id"`
|
||||
Type string `bson:"type"`
|
||||
Action string `bson:"action"`
|
||||
Code string `bson:"code"`
|
||||
Name string `bson:"name"`
|
||||
UserID string `bson:"user_id"`
|
||||
Username string `bson:"username"`
|
||||
Time time.Time `bson:"time"`
|
||||
ID primitive.ObjectID `json:"id" bson:"_id"`
|
||||
Type string `json:"type" bson:"type"`
|
||||
Action string `json:"action" bson:"action"`
|
||||
Code string `json:"code" bson:"code"`
|
||||
Name string `json:"name" bson:"name"`
|
||||
UserID string `json:"userId" bson:"user_id"`
|
||||
Username string `json:"username" bson:"username"`
|
||||
Time Time `json:"time" bson:"time"`
|
||||
}
|
||||
|
||||
type EventSearchArgs struct {
|
||||
@ -166,27 +166,26 @@ type EventSearchArgs struct {
|
||||
|
||||
// Chart represents a dashboard chart.
|
||||
type Chart struct {
|
||||
ID string `json:"id" bson:"_id"` // unique, the name of build-in charts has '$' prefix.
|
||||
Title string `json:"title" valid:"required"`
|
||||
ID string `json:"id" bson:"_id"` // the id of built-in charts has '$' prefix.
|
||||
Title string `json:"title" bson:"title" valid:"required"`
|
||||
Description string `json:"desc" bson:"desc"`
|
||||
Metrics []ChartMetric `json:"metrics" valid:"required"`
|
||||
Dashboard string `json:"dashboard"` // home/service/task...
|
||||
Type string `json:"type"` // pie/line...
|
||||
Unit string `json:"unit"` // bytes/milliseconds/percent:100...
|
||||
Width int32 `json:"width"` // 1-12(12 columns total)
|
||||
Height int32 `json:"height"` // default 50
|
||||
Options data.Map `json:"options,omitempty"`
|
||||
Metrics []ChartMetric `json:"metrics" bson:"metrics" valid:"required"`
|
||||
Dashboard string `json:"dashboard" bson:"dashboard"` // home/service...
|
||||
Type string `json:"type" bson:"type"` // pie/line...
|
||||
Unit string `json:"unit" bson:"unit"` // bytes/milliseconds/percent:100...
|
||||
Width int32 `json:"width" bson:"width"` // 1-12(12 columns total)
|
||||
Height int32 `json:"height" bson:"height"` // default 50
|
||||
Options data.Map `json:"options,omitempty" bson:"options,omitempty"`
|
||||
Margin struct {
|
||||
Left int32 `json:"left,omitempty"`
|
||||
Right int32 `json:"right,omitempty"`
|
||||
Top int32 `json:"top,omitempty"`
|
||||
Bottom int32 `json:"bottom,omitempty"`
|
||||
} `json:"margin"`
|
||||
//Colors []string `json:"colors"`
|
||||
CreatedAt time.Time `bson:"created_at" json:"createdAt,omitempty"`
|
||||
UpdatedAt time.Time `bson:"updated_at" json:"updatedAt,omitempty"`
|
||||
CreatedBy Operator `json:"createdBy" bson:"created_by"`
|
||||
UpdatedBy Operator `json:"updatedBy" bson:"updated_by"`
|
||||
Left int32 `json:"left,omitempty" bson:"left,omitempty"`
|
||||
Right int32 `json:"right,omitempty" bson:"right,omitempty"`
|
||||
Top int32 `json:"top,omitempty" bson:"top,omitempty"`
|
||||
Bottom int32 `json:"bottom,omitempty" bson:"bottom,omitempty"`
|
||||
} `json:"margin" bson:"margin"`
|
||||
CreatedAt Time `json:"createdAt" bson:"created_at"`
|
||||
UpdatedAt Time `json:"updatedAt" bson:"updated_at"`
|
||||
CreatedBy Operator `json:"createdBy" bson:"created_by"`
|
||||
UpdatedBy Operator `json:"updatedBy" bson:"updated_by"`
|
||||
}
|
||||
|
||||
func NewChart(dashboard, id, title, legend, query, unit string, left int32) *Chart {
|
||||
@ -220,20 +219,28 @@ type ChartSearchArgs struct {
|
||||
}
|
||||
|
||||
type Dashboard struct {
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key,omitempty"`
|
||||
Period int32 `json:"period,omitempty"` // data range in minutes
|
||||
Interval int32 `json:"interval,omitempty"` // refresh interval in seconds, 0 means disabled.
|
||||
Charts []ChartInfo `json:"charts,omitempty"`
|
||||
UpdatedAt time.Time `bson:"updated_at" json:"updatedAt,omitempty"`
|
||||
UpdatedBy Operator `json:"updatedBy" bson:"updated_by"`
|
||||
Name string `json:"name" bson:"name"`
|
||||
Key string `json:"key,omitempty" bson:"key,omitempty"`
|
||||
Period int32 `json:"period,omitempty" bson:"period,omitempty"` // data range in minutes
|
||||
Interval int32 `json:"interval,omitempty" bson:"interval,omitempty"` // refresh interval in seconds, 0 means disabled.
|
||||
Charts []ChartInfo `json:"charts,omitempty" bson:"charts,omitempty"`
|
||||
UpdatedAt Time `json:"-" bson:"updated_at"`
|
||||
UpdatedBy Operator `json:"-" bson:"updated_by"`
|
||||
}
|
||||
|
||||
type ChartInfo struct {
|
||||
ID string `json:"id"`
|
||||
Width int32 `json:"width,omitempty"`
|
||||
Height int32 `json:"height,omitempty"`
|
||||
//Colors []string `json:"colors,omitempty"`
|
||||
ID string `json:"id" bson:"id"`
|
||||
Width int32 `json:"width,omitempty" bson:"width,omitempty"`
|
||||
Height int32 `json:"height,omitempty" bson:"height,omitempty"`
|
||||
Title string `json:"title" bson:"-"`
|
||||
Type string `json:"type" bson:"-"`
|
||||
Unit string `json:"unit" bson:"-"`
|
||||
Margin struct {
|
||||
Left int32 `json:"left,omitempty" bson:"-"`
|
||||
Right int32 `json:"right,omitempty" bson:"-"`
|
||||
Top int32 `json:"top,omitempty" bson:"-"`
|
||||
Bottom int32 `json:"bottom,omitempty" bson:"-"`
|
||||
} `json:"margin" bson:"-"`
|
||||
}
|
||||
|
||||
func (cd *Dashboard) ID() string {
|
||||
@ -244,65 +251,12 @@ func (cd *Dashboard) ID() string {
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
UserID string `bson:"_id" json:"id,omitempty"`
|
||||
Token string `bson:"token" json:"token,omitempty"`
|
||||
Expires time.Time `bson:"expires" json:"expires,omitempty"`
|
||||
UpdatedAt time.Time `bson:"updated_at" json:"updated_at,omitempty"`
|
||||
ID string `json:"id" bson:"_id"` // token
|
||||
UserID string `json:"userId" bson:"user_id"`
|
||||
Roles []string `json:"roles" bson:"roles"`
|
||||
Perm int64 `json:"perm" bson:"perm"`
|
||||
Dirty bool `json:"dirty" bson:"dirty"`
|
||||
Expiry time.Time `json:"expiry" bson:"expiry"`
|
||||
MaxExpiry time.Time `json:"maxExpiry" bson:"max_expiry"`
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updated_at"`
|
||||
}
|
||||
|
||||
//type AuthUser struct {
|
||||
// user *User
|
||||
// roles []*Role
|
||||
// perms map[string]struct{}
|
||||
//}
|
||||
//
|
||||
//func NewAuthUser(user *User, roles []*Role) *AuthUser {
|
||||
// if user == nil {
|
||||
// panic(111)
|
||||
// }
|
||||
// u := &AuthUser{
|
||||
// user: user,
|
||||
// roles: roles,
|
||||
// perms: make(map[string]struct{}),
|
||||
// }
|
||||
// for _, role := range roles {
|
||||
// for _, perm := range role.Perms {
|
||||
// u.perms[perm] = data.Empty
|
||||
// }
|
||||
// }
|
||||
// return u
|
||||
//}
|
||||
//
|
||||
//func (u *AuthUser) ID() string {
|
||||
// return u.user.ID
|
||||
//}
|
||||
//
|
||||
//func (u *AuthUser) Name() string {
|
||||
// return u.user.Name
|
||||
//}
|
||||
//
|
||||
//func (u *AuthUser) Anonymous() bool {
|
||||
// return u.user.ID == ""
|
||||
//}
|
||||
//
|
||||
//func (u *AuthUser) Admin() bool {
|
||||
// return u.user.Admin
|
||||
//}
|
||||
//
|
||||
//func (u *AuthUser) IsInRole(roleID string) bool {
|
||||
// for _, role := range u.roles {
|
||||
// if role.ID == roleID {
|
||||
// return true
|
||||
// }
|
||||
// }
|
||||
// return false
|
||||
//}
|
||||
//
|
||||
//func (u *AuthUser) IsAllowed(perm string) bool {
|
||||
// if u.user.Admin {
|
||||
// return true
|
||||
// }
|
||||
//
|
||||
// _, ok := u.perms[perm]
|
||||
// return ok
|
||||
//}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/cuigh/auxo/security/passwd"
|
||||
"github.com/cuigh/swirl/biz"
|
||||
"github.com/cuigh/swirl/misc"
|
||||
"github.com/cuigh/swirl/model"
|
||||
)
|
||||
|
||||
type Authenticator struct {
|
||||
@ -92,7 +93,7 @@ func ldapRealm(s *misc.Setting, ub biz.UserBiz) RealmFunc {
|
||||
lu = user.(*ldap.User)
|
||||
)
|
||||
if u == nil {
|
||||
id, err = ub.Create(&biz.User{
|
||||
id, err = ub.Create(&model.User{
|
||||
Type: biz.UserTypeLDAP,
|
||||
LoginName: loginName,
|
||||
Name: lu.Name(),
|
||||
|
@ -20,8 +20,8 @@ export interface Chart {
|
||||
top: number;
|
||||
bottom: number;
|
||||
};
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
createdBy: {
|
||||
id: string;
|
||||
name: string;
|
||||
|
@ -8,7 +8,7 @@ export interface Event {
|
||||
name: string;
|
||||
userId: string;
|
||||
username: string;
|
||||
time: string;
|
||||
time: number;
|
||||
}
|
||||
|
||||
export interface SearchArgs {
|
||||
|
@ -6,8 +6,8 @@ export interface Registry {
|
||||
url: string;
|
||||
username: string;
|
||||
password: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
createdBy: {
|
||||
id: string;
|
||||
name: string;
|
||||
|
@ -5,8 +5,8 @@ export interface Role {
|
||||
name: string;
|
||||
desc: string;
|
||||
perms: string[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
createdBy: {
|
||||
id: string;
|
||||
name: string;
|
||||
|
@ -6,8 +6,8 @@ export interface Stack {
|
||||
content: string;
|
||||
services?: string[];
|
||||
internal: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
createdBy: {
|
||||
id: string;
|
||||
name: string;
|
||||
|
@ -17,8 +17,8 @@ export interface User {
|
||||
status: number;
|
||||
email: string;
|
||||
roles: string[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
createdBy: {
|
||||
id: string;
|
||||
name: string;
|
||||
|
@ -394,6 +394,7 @@ export default {
|
||||
"1002": "Account is disabled",
|
||||
"1003": "Old password is incorrect",
|
||||
"1004": "Can not deploy external stack",
|
||||
"1005": "system was already initialized",
|
||||
},
|
||||
"copyright": "© 2017-2021 cuigh. All rights reserved.",
|
||||
}
|
@ -394,6 +394,7 @@ export default {
|
||||
"1002": "账户已禁用",
|
||||
"1003": "旧密码不正确",
|
||||
"1004": "不能发布外部编排",
|
||||
"1005": "系统已经初始化",
|
||||
},
|
||||
"copyright": "© 2017-2021 cuigh. 保留所有权利。",
|
||||
}
|
@ -68,7 +68,7 @@ import XCode from "@/components/Code.vue";
|
||||
import XIcon from "@/components/Icon.vue";
|
||||
import chartApi from "@/api/chart";
|
||||
import type { Chart } from "@/api/chart";
|
||||
import { renderButtons, renderLink, renderTag } from "@/utils/render";
|
||||
import { renderButtons, renderLink, renderTag, renderTime } from "@/utils/render";
|
||||
import { useDataTable } from "@/utils/data-table";
|
||||
import { toTitle } from "@/utils";
|
||||
import { useI18n } from 'vue-i18n'
|
||||
@ -119,7 +119,8 @@ const columns = [
|
||||
},
|
||||
{
|
||||
title: t('fields.updated_at'),
|
||||
key: "updatedAt"
|
||||
key: "updatedAt",
|
||||
render: (c: Chart) => renderTime(c.updatedAt),
|
||||
},
|
||||
{
|
||||
title: t('fields.actions'),
|
||||
@ -175,7 +176,7 @@ function importChart() {
|
||||
}
|
||||
|
||||
function exportChart(c: Chart) {
|
||||
const { id, createdAt, updatedAt, ...chart } = c
|
||||
const { id, createdAt, updatedAt, createdBy, updatedBy, ...chart } = c
|
||||
window.dialog.success({
|
||||
showIcon: false,
|
||||
title: t('dialogs.export_chart.title'),
|
||||
|
@ -57,11 +57,15 @@
|
||||
<x-description-item :label="t('fields.created_by')">
|
||||
<x-anchor :url="`/system/users/${model.createdBy?.id}`">{{ model.createdBy?.name }}</x-anchor>
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.created_at')">{{ model.createdAt }}</x-description-item>
|
||||
<x-description-item :label="t('fields.created_at')">
|
||||
<n-time :time="model.createdAt" format="y-MM-dd HH:mm:ss" />
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_by')">
|
||||
<x-anchor :url="`/system/users/${model.updatedBy?.id}`">{{ model.updatedBy?.name }}</x-anchor>
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_at')">{{ model.updatedAt }}</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_at')">
|
||||
<n-time :time="model.updatedAt" format="y-MM-dd HH:mm:ss" />
|
||||
</x-description-item>
|
||||
</x-description>
|
||||
<x-panel :title="t('fields.metrics')">
|
||||
<n-table size="small" :bordered="true" :single-line="false">
|
||||
@ -89,6 +93,7 @@ import {
|
||||
NSpace,
|
||||
NIcon,
|
||||
NTable,
|
||||
NTime,
|
||||
} from "naive-ui";
|
||||
import { ArrowBackCircleOutline as BackIcon } from "@vicons/ionicons5";
|
||||
import XPageHeader from "@/components/PageHeader.vue";
|
||||
|
@ -59,7 +59,7 @@ import XPageHeader from "@/components/PageHeader.vue";
|
||||
import eventApi from "@/api/event";
|
||||
import type { Event } from "@/api/event";
|
||||
import { useDataTable } from "@/utils/data-table";
|
||||
import { renderLink, renderTag } from "@/utils/render";
|
||||
import { renderLink, renderTag, renderTime } from "@/utils/render";
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
@ -186,7 +186,8 @@ const columns = [
|
||||
},
|
||||
{
|
||||
title: t('fields.time'),
|
||||
key: "time"
|
||||
key: "time",
|
||||
render: (e: Event) => renderTime(e.time),
|
||||
},
|
||||
];
|
||||
const { state, pagination, fetchData, changePageSize } = useDataTable(eventApi.search, filter)
|
||||
|
@ -30,8 +30,12 @@
|
||||
</td>
|
||||
<td>{{ r.url }}</td>
|
||||
<td>{{ r.username }}</td>
|
||||
<td>{{ r.createdAt }}</td>
|
||||
<td>{{ r.updatedAt }}</td>
|
||||
<td>
|
||||
<n-time :time="r.createdAt" format="y-MM-dd HH:mm:ss" />
|
||||
</td>
|
||||
<td>
|
||||
<n-time :time="r.updatedAt" format="y-MM-dd HH:mm:ss" />
|
||||
</td>
|
||||
<td>
|
||||
<n-button
|
||||
size="tiny"
|
||||
@ -60,6 +64,7 @@ import {
|
||||
NTable,
|
||||
NPopconfirm,
|
||||
NIcon,
|
||||
NTime,
|
||||
} from "naive-ui";
|
||||
import { AddOutline as AddIcon } from "@vicons/ionicons5";
|
||||
import XPageHeader from "@/components/PageHeader.vue";
|
||||
|
@ -25,11 +25,15 @@
|
||||
<x-description-item :label="t('fields.created_by')">
|
||||
<x-anchor :url="`/system/users/${model.createdBy?.id}`">{{ model.createdBy?.name }}</x-anchor>
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.created_at')">{{ model.createdAt }}</x-description-item>
|
||||
<x-description-item :label="t('fields.created_at')">
|
||||
<n-time :time="model.createdAt" format="y-MM-dd HH:mm:ss" />
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_by')">
|
||||
<x-anchor :url="`/system/users/${model.updatedBy?.id}`">{{ model.updatedBy?.name }}</x-anchor>
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_at')">{{ model.updatedAt }}</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_at')">
|
||||
<n-time :time="model.updatedAt" format="y-MM-dd HH:mm:ss" />
|
||||
</x-description-item>
|
||||
</x-description>
|
||||
</n-space>
|
||||
</template>
|
||||
@ -40,6 +44,7 @@ import {
|
||||
NButton,
|
||||
NSpace,
|
||||
NIcon,
|
||||
NTime,
|
||||
} from "naive-ui";
|
||||
import { ArrowBackCircleOutline as BackIcon } from "@vicons/ionicons5";
|
||||
import XPageHeader from "@/components/PageHeader.vue";
|
||||
|
@ -33,7 +33,9 @@
|
||||
</td>
|
||||
<td>{{ r.name }}</td>
|
||||
<td>{{ r.desc }}</td>
|
||||
<td>{{ r.updatedAt }}</td>
|
||||
<td>
|
||||
<n-time :time="r.updatedAt" format="y-MM-dd HH:mm:ss" />
|
||||
</td>
|
||||
<td>
|
||||
<n-popconfirm :show-icon="false" @positive-click="deleteRole(r, index)">
|
||||
<template #trigger>
|
||||
@ -63,6 +65,7 @@ import {
|
||||
NIcon,
|
||||
NTable,
|
||||
NPopconfirm,
|
||||
NTime,
|
||||
} from "naive-ui";
|
||||
import {
|
||||
AddOutline as AddIcon,
|
||||
|
@ -24,11 +24,15 @@
|
||||
<x-description-item :label="t('fields.created_by')">
|
||||
<x-anchor :url="`/system/users/${model.createdBy?.id}`">{{ model.createdBy?.name }}</x-anchor>
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.created_at')">{{ model.createdAt }}</x-description-item>
|
||||
<x-description-item :label="t('fields.created_at')">
|
||||
<n-time :time="model.createdAt" format="y-MM-dd HH:mm:ss" />
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_by')">
|
||||
<x-anchor :url="`/system/users/${model.updatedBy?.id}`">{{ model.updatedBy?.name }}</x-anchor>
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_at')">{{ model.updatedAt }}</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_at')">
|
||||
<n-time :time="model.updatedAt" format="y-MM-dd HH:mm:ss" />
|
||||
</x-description-item>
|
||||
<x-description-item :span="2" :label="t('fields.perms')">
|
||||
<n-grid cols="1 480:2 960:3 1440:4" x-gap="6">
|
||||
<n-gi span="1" v-for="g in ps">
|
||||
@ -48,6 +52,7 @@ import {
|
||||
NIcon,
|
||||
NGrid,
|
||||
NGi,
|
||||
NTime,
|
||||
} from "naive-ui";
|
||||
import { useRoute } from "vue-router";
|
||||
import { ArrowBackCircleOutline as BackIcon } from "@vicons/ionicons5";
|
||||
|
@ -152,6 +152,7 @@ async function fetchData() {
|
||||
if (name) {
|
||||
let tr = await stackApi.find(name);
|
||||
model.value = tr.data as Stack;
|
||||
model.value.id = model.value.name
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,12 @@
|
||||
</n-tag>
|
||||
</n-space>
|
||||
</td>
|
||||
<td>{{ r.createdAt }}</td>
|
||||
<td>{{ r.updatedAt }}</td>
|
||||
<td>
|
||||
<n-time :time="r.createdAt" format="y-MM-dd HH:mm:ss" />
|
||||
</td>
|
||||
<td>
|
||||
<n-time :time="r.updatedAt" format="y-MM-dd HH:mm:ss" />
|
||||
</td>
|
||||
<td>
|
||||
<n-button
|
||||
size="tiny"
|
||||
@ -86,6 +90,7 @@ import {
|
||||
NTable,
|
||||
NPopconfirm,
|
||||
NTag,
|
||||
NTime,
|
||||
} from "naive-ui";
|
||||
import { AddOutline as AddIcon } from "@vicons/ionicons5";
|
||||
import XPageHeader from "@/components/PageHeader.vue";
|
||||
|
@ -23,11 +23,15 @@
|
||||
<x-description-item :label="t('fields.created_by')">
|
||||
<x-anchor :url="`/system/users/${model.createdBy?.id}`">{{ model.createdBy?.name }}</x-anchor>
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.created_at')">{{ model.createdAt }}</x-description-item>
|
||||
<x-description-item :label="t('fields.created_at')">
|
||||
<n-time :time="model.createdAt" format="y-MM-dd HH:mm:ss" />
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_by')">
|
||||
<x-anchor :url="`/system/users/${model.updatedBy?.id}`">{{ model.updatedBy?.name }}</x-anchor>
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_at')">{{ model.updatedAt }}</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_at')">
|
||||
<n-time :time="model.updatedAt" format="y-MM-dd HH:mm:ss" />
|
||||
</x-description-item>
|
||||
</x-description>
|
||||
<x-panel :title="t('fields.content')">
|
||||
<x-code :code="model.content" language="yaml" />
|
||||
@ -42,6 +46,7 @@ import {
|
||||
NButton,
|
||||
NSpace,
|
||||
NIcon,
|
||||
NTime,
|
||||
} from "naive-ui";
|
||||
import { ArrowBackCircleOutline as BackIcon } from "@vicons/ionicons5";
|
||||
import XPageHeader from "@/components/PageHeader.vue";
|
||||
|
@ -70,7 +70,7 @@ import XPageHeader from "@/components/PageHeader.vue";
|
||||
import userApi from "@/api/user";
|
||||
import type { User } from "@/api/user";
|
||||
import { useDataTable } from "@/utils/data-table";
|
||||
import { renderButtons, renderLink, renderTag } from "@/utils/render";
|
||||
import { renderButtons, renderLink, renderTag, renderTime } from "@/utils/render";
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
@ -114,6 +114,7 @@ const columns = [
|
||||
{
|
||||
title: t('fields.updated_at'),
|
||||
key: "updatedAt",
|
||||
render: (row: User) => renderTime(row.updatedAt),
|
||||
},
|
||||
{
|
||||
title: t('fields.actions'),
|
||||
|
@ -48,13 +48,17 @@
|
||||
:url="`/system/users/${model.user.createdBy?.id}`"
|
||||
>{{ model.user.createdBy?.name }}</x-anchor>
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.created_at')">{{ model.user.createdAt }}</x-description-item>
|
||||
<x-description-item :label="t('fields.created_at')">
|
||||
<n-time :time="model.user.createdAt" format="y-MM-dd HH:mm:ss" />
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_by')">
|
||||
<x-anchor
|
||||
:url="`/system/users/${model.user.updatedBy?.id}`"
|
||||
>{{ model.user.updatedBy?.name }}</x-anchor>
|
||||
</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_at')">{{ model.user.updatedAt }}</x-description-item>
|
||||
<x-description-item :label="t('fields.updated_at')">
|
||||
<n-time :time="model.user.updatedAt" format="y-MM-dd HH:mm:ss" />
|
||||
</x-description-item>
|
||||
<x-description-item
|
||||
:label="t('objects.role', 2)"
|
||||
:span="2"
|
||||
@ -80,6 +84,7 @@ import {
|
||||
NTag,
|
||||
NSpace,
|
||||
NIcon,
|
||||
NTime,
|
||||
} from "naive-ui";
|
||||
import { useRoute } from "vue-router";
|
||||
import { ArrowBackCircleOutline as BackIcon } from "@vicons/ionicons5";
|
||||
|
Loading…
Reference in New Issue
Block a user