feat: 容器操作优化等

This commit is contained in:
meilin.huang
2025-09-06 21:32:48 +08:00
parent 25195b6360
commit 66d5fd6ca4
64 changed files with 1208 additions and 1856 deletions

View File

@@ -33,7 +33,7 @@ require (
github.com/stretchr/testify v1.10.0
github.com/tidwall/gjson v1.18.0
github.com/veops/go-ansiterm v0.0.5
go.mongodb.org/mongo-driver/v2 v2.2.2 // mongo
go.mongodb.org/mongo-driver/v2 v2.3.0 // mongo
golang.org/x/crypto v0.41.0 // ssh
golang.org/x/oauth2 v0.30.0
golang.org/x/sync v0.16.0
@@ -41,7 +41,7 @@ require (
gopkg.in/yaml.v3 v3.0.1
// gorm
gorm.io/driver/mysql v1.6.0
gorm.io/gorm v1.30.2
gorm.io/gorm v1.30.3
)
require (

View File

@@ -3,6 +3,7 @@ package api
import "mayfly-go/pkg/ioc"
func InitIoc() {
ioc.Register(new(ContainerConf))
ioc.Register(new(Docker))
ioc.Register(new(Container))
ioc.Register(new(Image))

View File

@@ -6,7 +6,6 @@ import (
"io"
"mayfly-go/internal/docker/api/form"
"mayfly-go/internal/docker/api/vo"
"mayfly-go/internal/docker/dkm"
"mayfly-go/internal/docker/imsg"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/errorx"
@@ -52,12 +51,11 @@ func (d *Container) ReqConfs() *req.Confs {
req.NewGet("/logs", d.ContainerLogs).NoRes(),
}
return req.NewConfs("docker/containers", reqs[:]...)
return req.NewConfs("docker/:id/containers", reqs[:]...)
}
func (d *Container) GetContainers(rc *req.Ctx) {
cli, err := dkm.GetCli(rc.Query("host"))
biz.ErrIsNil(err)
cli := GetCli(rc)
cs, err := cli.ContainerList()
biz.ErrIsNil(err)
@@ -89,8 +87,7 @@ func (d *Container) GetContainers(rc *req.Ctx) {
}
func (d *Container) GetContainersStats(rc *req.Ctx) {
cli, err := dkm.GetCli(rc.Query("host"))
biz.ErrIsNil(err)
cli := GetCli(rc)
cs, err := cli.ContainerList()
biz.ErrIsNil(err)
@@ -141,8 +138,7 @@ func (d *Container) ContainerCreate(rc *req.Ctx) {
rc.ReqParam = containerCreate
cli, err := dkm.GetCli(containerCreate.Host)
biz.ErrIsNil(err)
cli := GetCli(rc)
config, hostConfig, networkConfig, err := loadConfigInfo(true, containerCreate, nil)
biz.ErrIsNil(err)
@@ -167,36 +163,30 @@ func (d *Container) ContainerStop(rc *req.Ctx) {
containerOp := &form.ContainerOp{}
biz.ErrIsNil(rc.BindJSON(containerOp))
rc.ReqParam = collx.Kvs("host", containerOp.Host, "containerId", containerOp.ContainerId)
cli := GetCli(rc)
rc.ReqParam = collx.Kvs("addr", cli.Server.Addr, "containerId", containerOp.ContainerId)
cli, err := dkm.GetCli(containerOp.Host)
biz.ErrIsNil(err)
err = cli.ContainerStop(containerOp.ContainerId)
biz.ErrIsNil(err)
biz.ErrIsNil(cli.ContainerStop(containerOp.ContainerId))
}
func (d *Container) ContainerRemove(rc *req.Ctx) {
containerOp := &form.ContainerOp{}
biz.ErrIsNil(rc.BindJSON(containerOp))
rc.ReqParam = collx.Kvs("host", containerOp.Host, "containerId", containerOp.ContainerId)
cli := GetCli(rc)
rc.ReqParam = collx.Kvs("addr", cli.Server.Addr, "containerId", containerOp.ContainerId)
cli, err := dkm.GetCli(containerOp.Host)
biz.ErrIsNil(err)
err = cli.ContainerRemove(containerOp.ContainerId)
biz.ErrIsNil(err)
biz.ErrIsNil(cli.ContainerRemove(containerOp.ContainerId))
}
func (d *Container) ContainerRestart(rc *req.Ctx) {
containerOp := &form.ContainerOp{}
biz.ErrIsNil(rc.BindJSON(containerOp))
rc.ReqParam = collx.Kvs("host", containerOp.Host, "containerId", containerOp.ContainerId)
cli := GetCli(rc)
rc.ReqParam = collx.Kvs("addr", cli.Server.Addr, "containerId", containerOp.ContainerId)
cli, err := dkm.GetCli(containerOp.Host)
biz.ErrIsNil(err)
err = cli.ContainerRestart(containerOp.ContainerId)
biz.ErrIsNil(err)
biz.ErrIsNil(cli.ContainerRestart(containerOp.ContainerId))
}
func (d *Container) ContainerLogs(rc *req.Ctx) {
@@ -211,9 +201,7 @@ func (d *Container) ContainerLogs(rc *req.Ctx) {
}()
biz.ErrIsNilAppendErr(err, "Upgrade websocket fail: %s")
cli, err := dkm.GetCli(rc.Query("host"))
biz.ErrIsNil(err)
cli := GetCli(rc)
ctx, cancel := context.WithCancel(rc.MetaCtx)
defer cancel()
@@ -288,9 +276,7 @@ func (d *Container) ContainerExecAttach(rc *req.Ctx) {
biz.ErrIsNilAppendErr(err, "Upgrade websocket fail: %s")
wsConn.WriteMessage(websocket.TextMessage, []byte("Connecting to container..."))
cli, err := dkm.GetCli(rc.Query("host"))
biz.ErrIsNil(err)
cli := GetCli(rc)
cols := rc.QueryIntDefault("cols", 80)
rows := rc.QueryIntDefault("rows", 32)
@@ -311,9 +297,7 @@ func (d *Container) ContainerProxy(rc *req.Ctx) {
containerID := pathParts[2]
remainingPath := strings.Join(pathParts[3:], "/")
cli, err := dkm.GetCli(rc.Query("host"))
biz.ErrIsNil(err)
cli := GetCli(rc)
ctx := rc.MetaCtx
containerJSON, err := cli.DockerClient.ContainerInspect(ctx, containerID)
biz.ErrIsNil(err)

View File

@@ -0,0 +1,96 @@
package api
import (
"mayfly-go/internal/docker/api/form"
"mayfly-go/internal/docker/api/vo"
"mayfly-go/internal/docker/application"
"mayfly-go/internal/docker/application/dto"
"mayfly-go/internal/docker/dkm"
"mayfly-go/internal/docker/domain/entity"
"mayfly-go/internal/pkg/consts"
tagapp "mayfly-go/internal/tag/application"
tagentity "mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/collx"
"strings"
"github.com/spf13/cast"
)
type ContainerConf struct {
containerApp application.Container `inject:"T"`
tagTreeApp tagapp.TagTree `inject:"T"`
}
func (cc *ContainerConf) ReqConfs() *req.Confs {
reqs := [...]*req.Conf{
req.NewGet("/page", cc.GetContainerPage),
req.NewPost("/save", cc.Save),
req.NewDelete("/del/:ids", cc.Delete),
}
return req.NewConfs("docker/container-conf", reqs[:]...)
}
func (cc *ContainerConf) GetContainerPage(rc *req.Ctx) {
condition := req.BindQuery[*entity.ContainerQuery](rc)
tags := cc.tagTreeApp.GetAccountTags(rc.GetLoginAccount().Id, &tagentity.TagTreeQuery{
TypePaths: collx.AsArray(tagentity.NewTypePaths(tagentity.TagTypeContainer)),
CodePathLikes: collx.AsArray(condition.TagPath),
})
// 不存在,即没有可操作数据
if len(tags) == 0 {
rc.ResData = model.NewEmptyPageResult[any]()
return
}
tagCodePaths := tags.GetCodePaths()
containerCodes := tagentity.GetCodesByCodePaths(tagentity.TagTypeContainer, tagCodePaths...)
condition.Codes = collx.ArrayDeduplicate(containerCodes)
res, err := cc.containerApp.GetContainerPage(condition)
biz.ErrIsNil(err)
if res.Total == 0 {
rc.ResData = res
return
}
resVo := model.PageResultConv[*entity.Container, *vo.ContainerConf](res)
containerVos := resVo.List
cc.tagTreeApp.FillTagInfo(tagentity.TagType(consts.ResourceTypeContainer), collx.ArrayMap(containerVos, func(cvo *vo.ContainerConf) tagentity.ITagResource {
return cvo
})...)
rc.ResData = resVo
}
func (c *ContainerConf) Save(rc *req.Ctx) {
machineForm, container := req.BindJsonAndCopyTo[*form.ContainerSave, *entity.Container](rc)
rc.ReqParam = machineForm
biz.ErrIsNil(c.containerApp.SaveContainer(rc.MetaCtx, &dto.SaveContainer{
Container: container,
TagCodePaths: machineForm.TagCodePaths,
}))
}
func (c *ContainerConf) Delete(rc *req.Ctx) {
idsStr := rc.PathParam("ids")
rc.ReqParam = idsStr
ids := strings.Split(idsStr, ",")
for _, v := range ids {
biz.ErrIsNil(c.containerApp.DeleteContainer(rc.MetaCtx, cast.ToUint64(v)))
}
}
func GetCli(rc *req.Ctx) *dkm.Client {
id := rc.PathParamInt("id")
biz.IsTrue(id > 0, "id error")
cli, err := application.GetContainerApp().GetContainerCli(rc.MetaCtx, uint64(id))
biz.ErrIsNil(err)
return cli
}

View File

@@ -1,7 +1,6 @@
package api
import (
"mayfly-go/internal/docker/dkm"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/req"
)
@@ -14,13 +13,11 @@ func (d *Docker) ReqConfs() *req.Confs {
req.NewGet("/info", d.GetDockerInfo),
}
return req.NewConfs("docker", reqs[:]...)
return req.NewConfs("docker/:id", reqs[:]...)
}
func (d *Docker) GetDockerInfo(rc *req.Ctx) {
host := rc.Query("host")
cli, err := dkm.GetCli(host)
biz.ErrIsNil(err)
cli := GetCli(rc)
info, err := cli.DockerClient.Info(rc.MetaCtx)
biz.ErrIsNil(err)
rc.ResData = info

View File

@@ -1,12 +1,22 @@
package form
import "mayfly-go/pkg/model"
type ContainerSave struct {
model.ExtraData
Id uint64 `json:"id"`
Addr string `json:"addr" binding:"required"`
Name string `json:"name" binding:"required"`
Remark string `json:"remark"`
TagCodePaths []string `json:"tagCodePaths" binding:"required"`
}
type ContainerOp struct {
Host string `json:"host"`
ContainerId string `json:"containerId" binding:"required"`
}
type ContainerCreate struct {
Host string `json:"host" binding:"required"`
ContainerID string `json:"containerId"`
Name string `json:"name" validate:"required"`
Image string `json:"image" validate:"required"`

View File

@@ -1,6 +1,5 @@
package form
type ImageOp struct {
Host string `json:"host" binding:"required"`
ImageId string `json:"imageId" binding:"required"`
}

View File

@@ -5,7 +5,6 @@ import (
"io"
"mayfly-go/internal/docker/api/form"
"mayfly-go/internal/docker/api/vo"
"mayfly-go/internal/docker/dkm"
"mayfly-go/internal/docker/imsg"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/req"
@@ -32,12 +31,11 @@ func (d *Image) ReqConfs() *req.Confs {
req.NewPost("/load", d.ImageLoad).Log(req.NewLogSaveI(imsg.LogDockerImageLoad)),
}
return req.NewConfs("docker/images", reqs[:]...)
return req.NewConfs("docker/:id/images", reqs[:]...)
}
func (d *Image) GetImages(rc *req.Ctx) {
cli, err := dkm.GetCli(rc.Query("host"))
biz.ErrIsNil(err)
cli := GetCli(rc)
is, err := cli.ImageList()
biz.ErrIsNil(err)
@@ -62,18 +60,12 @@ func (d *Image) ImageRemove(rc *req.Ctx) {
imageOp := &form.ImageOp{}
biz.ErrIsNil(rc.BindJSON(imageOp))
rc.ReqParam = collx.Kvs("host", imageOp.Host, "imageId", imageOp.ImageId)
cli, err := dkm.GetCli(imageOp.Host)
biz.ErrIsNil(err)
err = cli.ImageRemove(imageOp.ImageId)
biz.ErrIsNil(err)
rc.ReqParam = collx.Kvs("imageId", imageOp.ImageId)
cli := GetCli(rc)
biz.ErrIsNil(cli.ImageRemove(imageOp.ImageId))
}
func (d *Image) ImageLoad(rc *req.Ctx) {
host := rc.PostForm("host")
biz.NotEmpty(host, "host cannot be empty")
rc.ReqParam = host
fileheader, err := rc.FormFile("file")
biz.ErrIsNilAppendErr(err, "read form file error: %s")
@@ -81,8 +73,9 @@ func (d *Image) ImageLoad(rc *req.Ctx) {
biz.ErrIsNil(err)
defer file.Close()
cli, err := dkm.GetCli(host)
biz.ErrIsNil(err)
cli := GetCli(rc)
rc.ReqParam = cli.Server
resp, err := cli.DockerClient.ImageLoad(rc.MetaCtx, file)
biz.ErrIsNil(err)
defer resp.Body.Close()
@@ -94,14 +87,10 @@ func (d *Image) ImageLoad(rc *req.Ctx) {
}
func (d *Image) ImageExport(rc *req.Ctx) {
host := rc.Query("host")
biz.NotEmpty(host, "host cannot be empty")
tag := rc.Query("tag")
biz.NotEmpty(tag, "tag cannot be empty")
cli, err := dkm.GetCli(host)
biz.ErrIsNil(err)
cli := GetCli(rc)
reader, err := cli.DockerClient.ImageSave(rc.MetaCtx, []string{tag}, client.ImageSaveWithPlatforms())
biz.ErrIsNil(err)
defer reader.Close()

View File

@@ -0,0 +1,21 @@
package vo
import (
tagentity "mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/model"
)
type ContainerConf struct {
model.Model
model.ExtraData
tagentity.ResourceTags // 标签信息
Addr string `json:"addr"`
Code string `json:"code"`
Name string `json:"name"`
Remark string `json:"remark"`
}
func (c *ContainerConf) GetCode() string {
return c.Code
}

View File

@@ -0,0 +1,13 @@
package application
import (
"mayfly-go/pkg/ioc"
)
func InitIoc() {
ioc.Register(new(containerAppImpl), ioc.WithComponentName("ContainerApp"))
}
func GetContainerApp() Container {
return ioc.Get[Container]("ContainerApp")
}

View File

@@ -0,0 +1,144 @@
package application
import (
"context"
"mayfly-go/internal/docker/application/dto"
"mayfly-go/internal/docker/dkm"
"mayfly-go/internal/docker/domain/entity"
"mayfly-go/internal/docker/domain/repository"
"mayfly-go/internal/docker/imsg"
tagapp "mayfly-go/internal/tag/application"
tagdto "mayfly-go/internal/tag/application/dto"
tagentity "mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils/stringx"
)
type Container interface {
base.App[*entity.Container]
GetContainerPage(condition *entity.ContainerQuery, orderBy ...string) (*model.PageResult[*entity.Container], error)
// SaveContainer 保存容器配置信息
SaveContainer(context.Context, *dto.SaveContainer) error
// DeleteContainer 删除容器配置信息
DeleteContainer(context.Context, uint64) error
// GetContaienrCli 获取容器客户端
GetContainerCli(context.Context, uint64) (*dkm.Client, error)
}
type containerAppImpl struct {
base.AppImpl[*entity.Container, repository.Container]
tagApp tagapp.TagTree `inject:"T"`
}
var _ (Container) = (*containerAppImpl)(nil)
func (c *containerAppImpl) GetContainerPage(condition *entity.ContainerQuery, orderBy ...string) (*model.PageResult[*entity.Container], error) {
return c.Repo.GetContainerPage(condition, orderBy...)
}
func (c *containerAppImpl) SaveContainer(ctx context.Context, saveContainer *dto.SaveContainer) error {
container := saveContainer.Container
tagCodePaths := saveContainer.TagCodePaths
resourceType := tagentity.TagTypeContainer
oldContainer := &entity.Container{
Addr: container.Addr,
}
err := c.GetByCond(oldContainer)
if container.Id == 0 {
if err == nil {
return errorx.NewBizI(ctx, imsg.ErrContainerConfExist)
}
// 生成随机编号
container.Code = stringx.Rand(10)
return c.Tx(ctx, func(ctx context.Context) error {
if err := c.Insert(ctx, container); err != nil {
return err
}
return c.tagApp.SaveResourceTag(ctx, &tagdto.SaveResourceTag{
ResourceTag: &tagdto.ResourceTag{
Code: container.Code,
Name: container.Name,
Type: resourceType,
},
ParentTagCodePaths: tagCodePaths,
})
})
}
if err == nil && container.Id != oldContainer.Id {
return errorx.NewBizI(ctx, imsg.ErrContainerConfExist)
}
if oldContainer.Code == "" {
oldContainer, _ = c.GetById(container.Id)
}
dkm.CloseCli(oldContainer.Id)
return c.Tx(ctx, func(ctx context.Context) error {
if err := c.UpdateById(ctx, container); err != nil {
return err
}
if oldContainer.Name != container.Name {
if err := c.tagApp.UpdateTagName(ctx, tagentity.TagTypeMachine, oldContainer.Code, container.Name); err != nil {
return err
}
}
return c.tagApp.SaveResourceTag(ctx, &tagdto.SaveResourceTag{
ResourceTag: &tagdto.ResourceTag{
Code: oldContainer.Code,
Name: container.Name,
Type: resourceType,
},
ParentTagCodePaths: tagCodePaths,
})
})
}
func (c *containerAppImpl) DeleteContainer(ctx context.Context, id uint64) error {
container, err := c.GetById(id)
if err != nil {
return err
}
dkm.CloseCli(id)
return c.Tx(ctx, func(ctx context.Context) error {
if err := c.DeleteById(ctx, id); err != nil {
return err
}
return c.tagApp.SaveResourceTag(ctx, &tagdto.SaveResourceTag{
ResourceTag: &tagdto.ResourceTag{
Code: container.Code,
Type: tagentity.TagTypeContainer,
},
})
})
}
func (c *containerAppImpl) GetContainerCli(ctx context.Context, id uint64) (*dkm.Client, error) {
return dkm.GetCli(id, func(u uint64) (*dkm.ContainerServer, error) {
containerConf, err := c.GetById(u)
if err != nil {
return nil, err
}
return &dkm.ContainerServer{
Id: id,
Addr: containerConf.Addr,
}, nil
})
}

View File

@@ -0,0 +1,8 @@
package dto
import "mayfly-go/internal/docker/domain/entity"
type SaveContainer struct {
Container *entity.Container
TagCodePaths []string
}

View File

@@ -3,6 +3,7 @@ package dkm
import (
"context"
"encoding/json"
"fmt"
"io"
"mayfly-go/internal/machine/mcm"
"mayfly-go/pkg/logx"
@@ -26,13 +27,13 @@ const (
DefaultServer = "unix:///var/run/docker.sock"
)
type DockerServer struct {
Host string
Client *client.Client
type ContainerServer struct {
Id uint64
Addr string
}
type Client struct {
Server *ContainerServer
DockerClient *client.Client
}
@@ -46,12 +47,13 @@ func (c *Client) Ping() error {
}
// GetCli get docker cli
func GetCli(host string) (*Client, error) {
if host == "" {
host = DefaultServer
}
pool, err := poolGroup.GetCachePool(host, func() (*Client, error) {
return NewClient(&DockerServer{Host: host})
func GetCli(id uint64, getContainer func(uint64) (*ContainerServer, error)) (*Client, error) {
pool, err := poolGroup.GetCachePool(fmt.Sprintf("%d", id), func() (*Client, error) {
containerServer, err := getContainer(id)
if err != nil {
return nil, err
}
return NewClient(containerServer)
})
if err != nil {
return nil, err
@@ -59,18 +61,23 @@ func GetCli(host string) (*Client, error) {
return pool.Get(context.Background())
}
func CloseCli(id uint64) error {
return poolGroup.Close(fmt.Sprintf("%d", id))
}
// NewClient new docker client
func NewClient(server *DockerServer) (*Client, error) {
if server.Host == "" {
server.Host = DefaultServer
func NewClient(server *ContainerServer) (*Client, error) {
if server.Addr == "" {
server.Addr = DefaultServer
}
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithHost(server.Host), client.WithAPIVersionNegotiation())
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithHost(server.Addr), client.WithAPIVersionNegotiation())
if err != nil {
return nil, err
}
return &Client{
DockerClient: cli,
Server: server,
}, nil
}

View File

@@ -0,0 +1,14 @@
package entity
import "mayfly-go/pkg/model"
// 容器配置
type Container struct {
model.Model
model.ExtraData
Code string `json:"code" gorm:"size:32;comment:code"` // code
Name string `json:"name" gorm:"size:32"` // 名称
Addr string `json:"addr" gorm:"size:64;not null;comment:地址"` // 地址
Remark string `json:"remark" gorm:"comment:备注"` // 备注
}

View File

@@ -0,0 +1,16 @@
package entity
import "mayfly-go/pkg/model"
type ContainerQuery struct {
model.PageParam
Id uint64 `json:"id" form:"id"`
Code string `json:"code" form:"code"`
Name string `json:"name" form:"name"`
Addr string `json:"addr" form:"addr"`
TagPath string `json:"tagPath" form:"tagPath"`
Keyword string `json:"keyword" form:"keyword"`
Codes []string
}

View File

@@ -0,0 +1,14 @@
package repository
import (
"mayfly-go/internal/docker/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type Container interface {
base.Repo[*entity.Container]
// 分页获取容器配置列表
GetContainerPage(condition *entity.ContainerQuery, orderBy ...string) (*model.PageResult[*entity.Container], error)
}

View File

@@ -5,4 +5,11 @@ import "mayfly-go/pkg/i18n"
var En = map[i18n.MsgId]string{
LogDockerContainerStop: "Container - Stop",
LogDockerContainerRestart: "Container - Restart",
LogDockerContainerRemove: "Container - Remove",
LogDockerContainerCreate: "Container - Create",
LogDockerImageRemove: "Image - Remove",
LogDockerImageLoad: "Image - Load",
ErrContainerConfExist: "Container conf already exists",
}

View File

@@ -18,4 +18,6 @@ const (
LogDockerImageRemove
LogDockerImageLoad
ErrContainerConfExist
)

View File

@@ -10,4 +10,6 @@ var Zh_CN = map[i18n.MsgId]string{
LogDockerImageRemove: "镜像-删除",
LogDockerImageLoad: "镜像-导入",
ErrContainerConfExist: "容器配置已存在",
}

View File

@@ -0,0 +1,33 @@
package persistence
import (
"mayfly-go/internal/docker/domain/entity"
"mayfly-go/internal/docker/domain/repository"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type containerRepoImpl struct {
base.RepoImpl[*entity.Container]
}
func newContainerRepo() repository.Container {
return &containerRepoImpl{}
}
func (m *containerRepoImpl) GetContainerPage(condition *entity.ContainerQuery, orderBy ...string) (*model.PageResult[*entity.Container], error) {
qd := model.NewCond().
Eq("id", condition.Id).
Like("addr", condition.Addr).
Like("name", condition.Name).
In("code", condition.Codes).
Eq("code", condition.Code)
keyword := condition.Keyword
if keyword != "" {
keyword = "%" + keyword + "%"
qd.And("addr like ? or name like ? or code like ?", keyword, keyword, keyword)
}
return m.PageByCond(qd, condition.PageParam)
}

View File

@@ -0,0 +1,9 @@
package persistence
import (
"mayfly-go/pkg/ioc"
)
func InitIoc() {
ioc.Register(newContainerRepo(), ioc.WithComponentName("ContainerRepo"))
}

View File

@@ -1,7 +1,16 @@
package init
import "mayfly-go/internal/docker/api"
import (
"mayfly-go/initialize"
"mayfly-go/internal/docker/api"
"mayfly-go/internal/docker/application"
"mayfly-go/internal/docker/infra/persistence"
)
func init() {
api.InitIoc()
initialize.AddInitIocFunc(func() {
persistence.InitIoc()
application.InitIoc()
api.InitIoc()
})
}

View File

@@ -4,7 +4,7 @@ import "fmt"
const (
AppName = "mayfly-go"
Version = "v1.10.2"
Version = "v1.10.3"
)
func GetAppInfo() string {

View File

@@ -9,6 +9,7 @@ const (
ResourceTypeMongo int8 = 4
ResourceTypeAuthCert int8 = 5
ResourceTypeEsInstance int8 = 6
ResourceTypeContainer int8 = 7
// imsg起始编号
ImsgNumSys = 10000

View File

@@ -183,6 +183,10 @@ func (p *TagTree) CountTagResource(rc *req.Ctx) {
Types: collx.AsArray(entity.TagTypeMongo),
CodePathLikes: collx.AsArray(tagPath),
}).GetCodes()),
"container": len(p.tagTreeApp.GetAccountTags(accountId, &entity.TagTreeQuery{
Types: collx.AsArray(entity.TagTypeContainer),
CodePathLikes: collx.AsArray(tagPath),
}).GetCodes()),
}
}

View File

@@ -36,6 +36,7 @@ const (
TagTypeRedis TagType = TagType(consts.ResourceTypeRedis)
TagTypeMongo TagType = TagType(consts.ResourceTypeMongo)
TagTypeAuthCert TagType = TagType(consts.ResourceTypeAuthCert) // 授权凭证类型
TagTypeContainer TagType = TagType(consts.ResourceTypeContainer)
TagTypeDb TagType = 22 // 数据库名
)

View File

@@ -1,6 +1,7 @@
package migrations
import (
dockerentity "mayfly-go/internal/docker/domain/entity"
esentity "mayfly-go/internal/es/domain/entity"
flowentity "mayfly-go/internal/flow/domain/entity"
machineentity "mayfly-go/internal/machine/domain/entity"
@@ -18,6 +19,7 @@ func V1_10() []*gormigrate.Migration {
migrations = append(migrations, V1_10_0()...)
migrations = append(migrations, V1_10_1()...)
migrations = append(migrations, V1_10_2()...)
migrations = append(migrations, V1_10_3()...)
return migrations
}
@@ -273,3 +275,54 @@ func V1_10_2() []*gormigrate.Migration {
},
}
}
func V1_10_3() []*gormigrate.Migration {
return []*gormigrate.Migration{
{
ID: "20250904-v1.10.3",
Migrate: func(tx *gorm.DB) error {
tx.AutoMigrate(&dockerentity.Container{})
// 删除容器菜单
tx.Exec("update t_sys_resource set is_deleted = 1 where code = '/container'")
// 新增容器管理基本权限
tx.Exec("INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (1757145306, 94, 'Tag3fhad/glxajg23/Bbrte5UH/', 2, 1, 'menu.containerManageBase', 'container', 1757145306, 'null', 1, 'admin', 1, 'admin', '2025-09-06 15:55:06', '2025-09-06 15:56:10', 0, NULL)")
// 机器列表相关菜单权限
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/Alw1Xkq3/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/Alw1Xkq3/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/Lsew24Kx/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/Lsew24Kx/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/Keiqkx4L/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/Keiqkx4L/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/Keal2Xke/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/Keal2Xke/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/Ihfs2xaw/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/Ihfs2xaw/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/3ldkxJDx/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/3ldkxJDx/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/Ljewix43/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/Ljewix43/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/L12wix43/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/L12wix43/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/Ljewisd3/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/Ljewisd3/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/Ljeew43/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/Ljeew43/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/ODewix43/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/ODewix43/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/LIEwix43/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/LIEwix43/'")
// redis
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/IUlxia23/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/IUlxia23/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/Gxlagheg/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/Gxlagheg/'")
// db
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/TGFPA3Ez/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/TGFPA3Ez/'")
// es
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/SQNFhhhn/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/SQNFhhhn/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/XAgy5Uvp/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/XAgy5Uvp/'")
// mongo
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/xvpKk36u/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/xvpKk36u/'")
tx.Exec("Update t_sys_resource set ui_path='ocdrUNaa/3sblw1Wb/', pid=1756122788 where ui_path = 'Tag3fhad/glxajg23/3sblw1Wb/'")
return nil
},
Rollback: func(tx *gorm.DB) error {
return nil
},
},
}
}