diff --git a/devcloud/mcenter/apps/label/impl/label.go b/devcloud/mcenter/apps/label/impl/label.go index f716935..8fa0fc7 100644 --- a/devcloud/mcenter/apps/label/impl/label.go +++ b/devcloud/mcenter/apps/label/impl/label.go @@ -4,8 +4,10 @@ import ( "context" "122.51.31.227/go-course/go18/devcloud/mcenter/apps/label" + "github.com/infraboard/mcube/v2/exception" "github.com/infraboard/mcube/v2/ioc/config/datasource" "github.com/infraboard/mcube/v2/types" + "gorm.io/gorm" ) // CreateLabel implements label.Service. @@ -46,13 +48,23 @@ func (i *LabelServiceImpl) QueryLabel(ctx context.Context, in *label.QueryLabelR return set, nil } -// DeleteLabel implements label.Service. -func (i *LabelServiceImpl) DeleteLabel(ctx context.Context, in *label.DeleteLabelRequest) (*label.Label, error) { - panic("unimplemented") -} - // DescribeLabel implements label.Service. func (i *LabelServiceImpl) DescribeLabel(ctx context.Context, in *label.DescribeLabelRequest) (*label.Label, error) { + query := datasource.DBFromCtx(ctx) + + ins := &label.Label{} + if err := query.Where("id = ?", in.Id).First(ins).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, exception.NewNotFound("label %s not found", in.Id) + } + return nil, err + } + + return ins, nil +} + +// DeleteLabel implements label.Service. +func (i *LabelServiceImpl) DeleteLabel(ctx context.Context, in *label.DeleteLabelRequest) (*label.Label, error) { panic("unimplemented") } diff --git a/devcloud/mcenter/apps/label/impl/label_test.go b/devcloud/mcenter/apps/label/impl/label_test.go index 22b406d..cb67b0e 100644 --- a/devcloud/mcenter/apps/label/impl/label_test.go +++ b/devcloud/mcenter/apps/label/impl/label_test.go @@ -8,12 +8,16 @@ import ( func TestCreateLabel(t *testing.T) { req := label.NewCreateLabelRequest() - req.Key = "tech" - req.KeyDesc = "技术部" + req.Key = "team" + req.KeyDesc = "小组" req.ValueType = label.VALUE_TYPE_ENUM req.AddEnumOption(&label.EnumOption{ Label: "开发一组", Value: "dev01", + Children: []*label.EnumOption{ + {Label: "后端开发", Value: "dev01.backend_developer"}, + {Label: "前端开发", Value: "dev01.web_developer"}, + }, }) ins, err := svc.CreateLabel(ctx, req) @@ -22,3 +26,12 @@ func TestCreateLabel(t *testing.T) { } t.Log(ins) } + +func TestQueryLabel(t *testing.T) { + req := label.NewQueryLabelRequest() + set, err := svc.QueryLabel(ctx, req) + if err != nil { + t.Fatal(err) + } + t.Log(set) +} diff --git a/devcloud/mcenter/apps/label/model.go b/devcloud/mcenter/apps/label/model.go index bb32516..8a9447d 100644 --- a/devcloud/mcenter/apps/label/model.go +++ b/devcloud/mcenter/apps/label/model.go @@ -11,8 +11,8 @@ func NewLabel(spc *CreateLabelRequest) (*Label, error) { return nil, err } return &Label{ - ResourceMeta: *apps.NewResourceMeta(), - Spec: spc, + ResourceMeta: *apps.NewResourceMeta(), + CreateLabelRequest: *spc, }, nil } @@ -20,7 +20,7 @@ type Label struct { // 基础数据 apps.ResourceMeta // 空间定义 - Spec *CreateLabelRequest `json:"spec" bson:",inline" gorm:"embedded"` + CreateLabelRequest `bson:",inline" gorm:"embedded"` } func (l *Label) TableName() string { @@ -65,13 +65,14 @@ type CreateCreateLabelSpec struct { // 适用于那些资源 Resources []string `json:"resources" bson:"resources" gorm:"column:resources;type:json;serializer:json;" description:"适用于那些资源" optional:"true"` - // 标签的键, 标签的Key不允许修改, 带前缀的 tech.dev.frontend01 tech.dev.backend01 + // 标签的键, 标签的Key不允许修改 Key string `json:"key" bson:"key" gorm:"column:key;type:varchar(255)" validate:"required"` // 标签的键的描述 KeyDesc string `json:"key_desc" bson:"key_desc" gorm:"column:key_desc;type:varchar(255)" validate:"required"` // 标签的颜色 Color string `json:"color" bson:"color" gorm:"column:color;type:varchar(100)"` + // 标签的值相关信息, tech.dev.frontend01 tech.dev.backend01 // 值类型 ValueType VALUE_TYPE `json:"value_type" gorm:"column:value_type;type:varchar(20)" bson:"value_type"` // 标签默认值 @@ -83,7 +84,7 @@ type CreateCreateLabelSpec struct { // 枚举值的选项 EnumOptions []*EnumOption `json:"enum_options,omitempty" bson:"enum_options" gorm:"column:enum_options;type:json;serializer:json;"` // 基于Http枚举的配置 - HttpEnumConfig HttpEnumConfig `json:"http_enum_config,omitempty" gorm:"embedded" bson:"http_enum_config"` + HttpEnumConfig HttpEnumConfig `json:"http_enum_config" gorm:"embedded" bson:"http_enum_config"` // 值的样例 Example string `json:"example" bson:"example" gorm:"column:example;type:text"` @@ -98,6 +99,8 @@ type EnumOption struct { Input string `json:"input" bson:"input" validate:"required"` // 选项的值, 根据parent.input + children.input 自动生成 Value string `json:"value" bson:"value"` + // 是否禁止选中, 和前端UI组件配合使用 + Disabled bool `json:"disabled" bson:"disabled"` // 标签的颜色 Color string `json:"color" bson:"color"` // 是否废弃 diff --git a/devcloud/mcenter/apps/policy/model.go b/devcloud/mcenter/apps/policy/model.go index 460f46e..f4e2001 100644 --- a/devcloud/mcenter/apps/policy/model.go +++ b/devcloud/mcenter/apps/policy/model.go @@ -1,6 +1,7 @@ package policy import ( + "strings" "time" "122.51.31.227/go-course/go18/devcloud/mcenter/apps/namespace" @@ -104,8 +105,18 @@ func (r ResourceScope) GormResourceFilter(query *gorm.DB) *gorm.DB { // 构建"标签值匹配"条件 var valueMatches []clause.Expression for _, val := range values { - valueMatches = append(valueMatches, - datatypes.JSONQuery("label").Equals(val, key)) + if strings.Contains(val, "%") { + // 如果值包含通配符%,使用LIKE条件 + valueMatches = append(valueMatches, + clause.Expr{ + SQL: "JSON_UNQUOTE(JSON_EXTRACT(label, ?)) LIKE ?", + Vars: []any{"$." + key, val}, + }) + } else { + // 否则使用精确匹配 + valueMatches = append(valueMatches, + datatypes.JSONQuery("label").Equals(val, key)) + } } // 组合条件:标签不存在 OR 标签值匹配 diff --git a/devcloud/mpaas/apps/application/impl/application_test.go b/devcloud/mpaas/apps/application/impl/application_test.go index ea33398..197369b 100644 --- a/devcloud/mpaas/apps/application/impl/application_test.go +++ b/devcloud/mpaas/apps/application/impl/application_test.go @@ -14,7 +14,7 @@ func TestCreateApplication(t *testing.T) { req.CodeRepository = application.CodeRepository{ SshUrl: "git@122.51.31.227:go-course/go18.git", } - req.SetLabel("team", "golang_dev_group_01") + req.SetLabel("team", "dev01.web_developer") ins, err := svc.CreateApplication(ctx, req) if err != nil { t.Fatal(err) @@ -25,7 +25,8 @@ func TestCreateApplication(t *testing.T) { // SELECT * FROM `applications` WHERE (NOT JSON_EXTRACT(`label`,'$.team') IS NOT NULL OR JSON_EXTRACT(`label`,'$.team') = 'golang_dev_group_01') ORDER BY created_at desc LIMIT 20 func TestQueryApplication(t *testing.T) { req := application.NewQueryApplicationRequest() - req.SetScope("team", []string{"golang_dev_group_01"}) + // dev01.% + req.SetScope("team", []string{"%"}) // req.SetScope("env", []string{"prod"}) ins, err := svc.QueryApplication(ctx, req) if err != nil {