Skip to content

Commit

Permalink
feat: add biz topo iam instance selection
Browse files Browse the repository at this point in the history
--story=118997780
  • Loading branch information
wcy00000000000000 committed Aug 5, 2024
1 parent 20d7cd8 commit 933af9d
Show file tree
Hide file tree
Showing 10 changed files with 305 additions and 49 deletions.
24 changes: 16 additions & 8 deletions src/ac/iam/initial_instance_selections.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,6 @@ func GenerateStaticInstanceSelections() []InstanceSelection {
ResourceTypeChain: []ResourceChain{
// select the business at first.
businessChain,
// {
// SystemID: SystemIDCMDB,
// ID: Set,
// },
// {
// SystemID: SystemIDCMDB,
// ID: Module,
// },
// then select the host instances.
{
SystemID: SystemIDCMDB,
Expand Down Expand Up @@ -296,5 +288,21 @@ func GenerateStaticInstanceSelections() []InstanceSelection {
ID: GeneralCache,
}},
},
// only for other system's biz topo instance selection usage, not related to actions
{
ID: BizTopoSelection,
Name: "业务拓扑",
NameEn: "Business Topology",
ResourceTypeChain: []ResourceChain{
businessChain,
{
SystemID: SystemIDCMDB,
ID: Set,
}, {
SystemID: SystemIDCMDB,
ID: Module,
},
},
},
}
}
58 changes: 30 additions & 28 deletions src/ac/iam/initial_resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ var ResourceTypeIDMap = map[TypeID]string{
BizProcessServiceTemplate: "服务模板",
FieldGroupingTemplate: "字段组合模板",
GeneralCache: "通用缓存",
Set: "集群",
Module: "模块",
}

// GenerateResourceTypes generate all the resource types registered to IAM.
Expand Down Expand Up @@ -210,34 +212,34 @@ func genBusinessResources() []ResourceType {
},
Version: 1,
},
// only for host topology usage, not related to actions
// {
// ID: Set,
// Name: ResourceTypeIDMap[Set],
// NameEn: "Set",
// Description: "集群列表",
// DescriptionEn: "all the sets in blueking cmdb.",
// Parents: []Parent{businessParent},
// ProviderConfig: ResourceConfig{
// Path: "/auth/v3/find/resource",
// },
// Version: 1,
// },
// {
// ID: Module,
// Name: ResourceTypeIDMap[Module],
// NameEn: "Module",
// Description: "模块列表",
// DescriptionEn: "all the modules in blueking cmdb.",
// Parents: []Parent{{
// SystemID: SystemIDCMDB,
// ResourceID: Set,
// }},
// ProviderConfig: ResourceConfig{
// Path: "/auth/v3/find/resource",
// },
// Version: 1,
// },
// only for biz topology usage, not related to actions
{
ID: Set,
Name: ResourceTypeIDMap[Set],
NameEn: "Set",
Description: "业务拓扑集群",
DescriptionEn: "business topology set",
Parents: []Parent{businessParent},
ProviderConfig: ResourceConfig{
Path: "/auth/v3/find/resource",
},
Version: 1,
},
{
ID: Module,
Name: ResourceTypeIDMap[Module],
NameEn: "Module",
Description: "业务拓扑模块",
DescriptionEn: "business topology module",
Parents: []Parent{{
SystemID: SystemIDCMDB,
ResourceID: Set,
}},
ProviderConfig: ResourceConfig{
Path: "/auth/v3/find/resource",
},
Version: 1,
},
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/ac/iam/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ const (
// GeneralCache defines general resource cache auth type
GeneralCache TypeID = "general_cache"

// Set is set auth type
Set TypeID = "set"
// Module is module auth type
Module TypeID = "module"

// SkipType TODO
// for resource type, which is not need to be authorized
SkipType TypeID = "skip_type"
Expand Down Expand Up @@ -743,6 +748,8 @@ const (
SysHostRscPoolDirectorySelection InstanceSelectionID = "sys_host_rsc_pool_directory"
// GeneralCacheSelection general resource cache instance selection id
GeneralCacheSelection InstanceSelectionID = "general_cache"
// BizTopoSelection is biz topo instance selection id
BizTopoSelection InstanceSelectionID = "biz_topo"
)

// InstanceSelection TODO
Expand Down
1 change: 1 addition & 0 deletions src/common/metadata/inst.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type SetInst struct {
SetEnv string `bson:"bk_set_env" json:"bk_set_env" mapstructure:"bk_set_env"`
SetTemplateID int64 `bson:"set_template_id" json:"set_template_id" mapstructure:"set_template_id"`
ParentID int64 `bson:"bk_parent_id" json:"bk_parent_id" mapstructure:"bk_parent_id"`
Default int `bson:"default" json:"default" field:"default" mapstructure:"default"`

Creator string `field:"creator" json:"creator,omitempty" bson:"creator" mapstructure:"creator"`
CreateTime Time `field:"create_time" json:"create_time,omitempty" bson:"create_time" mapstructure:"create_time"`
Expand Down
14 changes: 14 additions & 0 deletions src/common/metadata/instance_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,17 @@ type ProcInstanceData struct {
Count int `json:"count"`
Info []Process `json:"info"`
}

// ResponseMainlineInst mainline instance response
// 只有主线模型实例的企业版本部分属性,使用前请注意
type ResponseMainlineInst struct {
BaseResp `json:",inline"`
Data MainlineInstData `json:"data"`
}

// MainlineInstData mainline instance data
// 只有主线模型实例的企业版本部分属性,使用前请注意
type MainlineInstData struct {
Count int `json:"count"`
Info []MainlineInstInfo `json:"info"`
}
219 changes: 219 additions & 0 deletions src/scene_server/auth_server/logics/list_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,3 +476,222 @@ func (lgc *Logics) ValidateListInstanceRequest(kit *rest.Kit, req *types.PullRes
}
return &filter, nil
}

// ListSetInstance list biz topo set instances
func (lgc *Logics) ListSetInstance(kit *rest.Kit, resourceType iam.TypeID, filter *types.ListInstanceFilter,
page types.Page) (*types.ListInstanceResult, error) {

if filter == nil || filter.Parent == nil || filter.Parent.Type != iam.Business {
return &types.ListInstanceResult{Count: 0, Results: make([]types.InstanceResource, 0)}, nil
}

bizID, err := strconv.ParseInt(filter.Parent.ID, 10, 64)
if err != nil {
blog.Errorf("parse filter.parent.id %s failed, err: %v, rid: %s", filter.Parent.ID, err, kit.Rid)
return &types.ListInstanceResult{Count: 0, Results: make([]types.InstanceResource, 0)}, nil
}

// read mainline object association and construct mainline topo relation map
queryCond := &metadata.QueryCondition{
Condition: map[string]interface{}{common.AssociationKindIDField: common.AssociationKindMainline},
Fields: []string{common.BKObjIDField, common.BKAsstObjIDField},
}
mlAsstRsp, err := lgc.CoreAPI.CoreService().Association().ReadModelAssociation(kit.Ctx, kit.Header, queryCond)
if err != nil {
blog.Errorf("search mainline association failed, err: %v, cond: %+v, rid: %s", err, queryCond, kit.Rid)
return nil, err
}
topoChildMap, topoParentMap := make(map[string]string), make(map[string]string)
for _, asst := range mlAsstRsp.Info {
if asst.ObjectID == common.BKInnerObjIDHost || asst.ObjectID == common.BKInnerObjIDModule {
continue
}
topoChildMap[asst.AsstObjID] = asst.ObjectID
topoParentMap[asst.ObjectID] = asst.AsstObjID
}

// generate set cond by biz id and keyword
cond := make(mapstr.MapStr)
if len(filter.Keyword) != 0 {
cond, err = lgc.genSetKeywordCond(kit, bizID, topoChildMap, filter.Keyword)
if err != nil {
return nil, err
}
}

cond[common.BKAppIDField] = bizID
setCond := &metadata.QueryCondition{
Condition: cond,
Fields: []string{common.BKSetIDField, common.BKSetNameField, common.BKParentIDField, common.BKDefaultField},
Page: metadata.BasePage{
Limit: int(page.Limit),
Start: int(page.Offset),
},
}

return lgc.listSetInstance(kit, setCond, topoParentMap)
}

func (lgc *Logics) genSetKeywordCond(kit *rest.Kit, bizID int64, topoChildMap map[string]string, keyword string) (
map[string]interface{}, error) {

// filter all mainline instances that matches the keyword
cond := mapstr.MapStr{
common.BKInstNameField: mapstr.MapStr{
common.BKDBLIKE: keyword,
common.BKDBOPTIONS: "i",
},
common.BKAppIDField: bizID,
}

for obj := topoChildMap[common.BKInnerObjIDApp]; obj != common.BKInnerObjIDSet; obj = topoChildMap[obj] {
instReq := &metadata.QueryCondition{
Condition: cond,
Fields: []string{common.BKInstIDField},
Page: metadata.BasePage{Limit: common.BKNoLimit},
}

instResp := new(metadata.ResponseMainlineInst)
err := lgc.CoreAPI.CoreService().Instance().ReadInstanceStruct(kit.Ctx, kit.Header, obj, instReq, instResp)
if err != nil {
blog.Errorf("search %s inst failed, err: %v, cond: %+v, rid: %s", obj, err, instReq, kit.Rid)
return nil, err
}
if err = instResp.CCError(); err != nil {
blog.Errorf("search %s inst failed, err: %v, cond: %+v, rid: %s", obj, err, instReq, kit.Rid)
return nil, err
}

parentIDs := make([]int64, 0)
for _, inst := range instResp.Data.Info {
parentIDs = append(parentIDs, inst.InstID)
}

cond = mapstr.MapStr{
common.GetInstNameField(topoChildMap[obj]): mapstr.MapStr{
common.BKDBLIKE: keyword,
common.BKDBOPTIONS: "i",
},
}

if len(parentIDs) != 0 {
cond = mapstr.MapStr{
common.BKDBOR: []mapstr.MapStr{
{common.BKParentIDField: mapstr.MapStr{common.BKDBIN: util.IntArrayUnique(parentIDs)}},
cond,
},
}
}
}

return cond, nil
}

func (lgc *Logics) listSetInstance(kit *rest.Kit, setCond *metadata.QueryCondition, topoParentMap map[string]string) (
*types.ListInstanceResult, error) {

// search set
setResp := new(metadata.ResponseSetInstance)
if err := lgc.CoreAPI.CoreService().Instance().ReadInstanceStruct(kit.Ctx, kit.Header, common.BKInnerObjIDSet,
setCond, setResp); err != nil {
blog.Errorf("search set failed, err: %v, cond: %+v, rid: %s", err, setCond, kit.Rid)
return nil, err
}
if err := setResp.CCError(); err != nil {
blog.Errorf("search set failed, err: %v, cond: %+v, rid: %s", err, setCond, kit.Rid)
return nil, err
}

parentIDs := make([]int64, 0)
for _, set := range setResp.Data.Info {
if set.Default != common.DefaultResSetFlag {
parentIDs = append(parentIDs, set.ParentID)
}
}

// get set parent mainline instance info
objInstMap := make(map[string]map[int64]metadata.MainlineInstInfo)
for obj := topoParentMap[common.BKInnerObjIDSet]; obj != common.BKInnerObjIDApp; obj = topoParentMap[obj] {
objInstMap[obj] = make(map[int64]metadata.MainlineInstInfo)
if len(parentIDs) == 0 {
break
}
parentIDs = util.IntArrayUnique(parentIDs)

instCond := &metadata.QueryCondition{
Condition: mapstr.MapStr{common.BKInstIDField: mapstr.MapStr{common.BKDBIN: parentIDs}},
Fields: []string{common.BKInstIDField, common.BKInstNameField, common.BKParentIDField},
Page: metadata.BasePage{Limit: len(parentIDs)},
}

instResp := new(metadata.ResponseMainlineInst)
err := lgc.CoreAPI.CoreService().Instance().ReadInstanceStruct(kit.Ctx, kit.Header, obj, instCond, instResp)
if err != nil {
blog.Errorf("search %s inst failed, err: %v, cond: %+v, rid: %s", obj, err, instCond, kit.Rid)
return nil, err
}
if err = instResp.CCError(); err != nil {
blog.Errorf("search %s inst failed, err: %v, cond: %+v, rid: %s", obj, err, instCond, kit.Rid)
return nil, err
}

parentIDs = make([]int64, 0)
for _, inst := range instResp.Data.Info {
parentIDs = append(parentIDs, inst.ParentID)
objInstMap[obj][inst.InstID] = inst
}
}

// add mainline topo path to set display name
instances := make([]types.InstanceResource, len(setResp.Data.Info))
for i, set := range setResp.Data.Info {
instances[i] = types.InstanceResource{
ID: strconv.FormatInt(set.SetID, 10),
DisplayName: set.SetName,
}

// default set do not need to add mainline topo path
if set.Default == common.DefaultResSetFlag {
continue
}

parentID := set.ParentID
for obj := topoParentMap[common.BKInnerObjIDSet]; obj != common.BKInnerObjIDApp; obj = topoParentMap[obj] {
instInfo, exists := objInstMap[obj][parentID]
if !exists {
break
}
instances[i].DisplayName = instInfo.InstName + " / " + instances[i].DisplayName
parentID = instInfo.ParentID
}
}

return &types.ListInstanceResult{Count: int64(setResp.Data.Count), Results: instances}, nil
}

// ListModuleInstance list biz topo module instances
func (lgc *Logics) ListModuleInstance(kit *rest.Kit, resourceType iam.TypeID, filter *types.ListInstanceFilter,
page types.Page) (*types.ListInstanceResult, error) {

if filter == nil || filter.Parent == nil || filter.Parent.Type != iam.Set {
return &types.ListInstanceResult{Count: 0, Results: make([]types.InstanceResource, 0)}, nil
}

setID, err := strconv.ParseInt(filter.Parent.ID, 10, 64)
if err != nil {
blog.Errorf("parse filter.parent.id %s failed, err: %v, rid: %s", filter.Parent.ID, err, kit.Rid)
return &types.ListInstanceResult{Count: 0, Results: make([]types.InstanceResource, 0)}, nil
}

cond := map[string]interface{}{
common.BKSetIDField: setID,
}

if len(filter.Keyword) != 0 {
cond[common.BKModuleNameField] = map[string]interface{}{
common.BKDBLIKE: filter.Keyword,
common.BKDBOPTIONS: "i",
}
}
return lgc.listInstance(kit, cond, resourceType, page)
}
Loading

0 comments on commit 933af9d

Please sign in to comment.