fix(region): tags for project mapping (#15605)

This commit is contained in:
屈轩
2022-12-22 18:42:13 +08:00
committed by GitHub
parent 1fb295436e
commit e1fbdb0a78
7 changed files with 148 additions and 18 deletions
+11
View File
@@ -206,6 +206,14 @@ type CloudaccountCreateInput struct {
SubAccounts *cloudprovider.SubAccounts
ReadOnly bool `json:"read_only"`
SProjectMappingResourceInput
}
type SProjectMappingResourceInput struct {
ProjectMappingId string `json:"project_mapping_id"`
EnableProjectSync bool `json:"enable_project_sync"`
EnableResourceSync bool `json:"enable_resource_sync"`
}
type CloudaccountShareModeInput struct {
@@ -505,6 +513,9 @@ type CloudaccountProjectMappingInput struct {
// 同步策略Id, 若不传此参数则解绑
// 绑定同步策略要求当前云账号此刻未绑定其他同步策略
ProjectMappingId string `json:"project_mapping_id"`
EnableProjectSync *bool `json:"enable_project_sync"`
EnableResourceSync *bool `json:"enable_resource_sync"`
}
type SyncRangeInput struct {
+11 -4
View File
@@ -354,6 +354,11 @@ func (manager *SCloudaccountManager) ValidateCreateData(
return input, err
}
input.SProjectMappingResourceInput, err = manager.SProjectMappingResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.SProjectMappingResourceInput)
if err != nil {
return input, err
}
input.EnabledStatusInfrasResourceBaseCreateInput, err = manager.SEnabledStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusInfrasResourceBaseCreateInput)
if err != nil {
return input, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.ValidateCreateData")
@@ -2833,12 +2838,14 @@ func (self *SCloudaccount) PerformProjectMapping(ctx context.Context, userCred m
return nil, httperrors.NewInputParameterError("account %s has aleady bind project mapping %s", self.Name, self.ProjectMappingId)
}
}
// no changes
if self.ProjectMappingId == input.ProjectMappingId {
return nil, nil
}
_, err := db.Update(self, func() error {
self.ProjectMappingId = input.ProjectMappingId
if input.EnableProjectSync != nil {
self.EnableProjectSync = tristate.NewFromBool(*input.EnableProjectSync)
}
if input.EnableResourceSync != nil {
self.EnableResourceSync = tristate.NewFromBool(*input.EnableResourceSync)
}
return nil
})
if err != nil {
+75 -11
View File
@@ -119,20 +119,49 @@ type pmCache struct {
CloudaccountId string
AccountProjectMappingId string
ManagerProjectMappingId string
AccountEnableProjectSync bool
ManagerEnableProjectSync bool
AccountEnableResourceSync bool
ManagerEnableResourceSync bool
}
func (self *pmCache) GetProjectMapping() (*SProjectMapping, error) {
type sProjectMapping struct {
*SProjectMapping
EnableProjectSync bool
EnableResourceSync bool
}
func (self *sProjectMapping) IsNeedResourceSync() bool {
return self.EnableResourceSync || !self.EnableProjectSync
}
func (self *sProjectMapping) IsNeedProjectSync() bool {
return self.EnableProjectSync
}
func (self *pmCache) GetProjectMapping() (*sProjectMapping, error) {
if len(self.ManagerProjectMappingId) > 0 {
pm, err := GetRuleMapping(self.ManagerProjectMappingId)
if err != nil {
return nil, errors.Wrapf(err, "GetRuleMapping(%s)", self.ManagerProjectMappingId)
}
if pm.Enabled.IsTrue() {
return pm, nil
ret := &sProjectMapping{
SProjectMapping: pm,
EnableProjectSync: self.ManagerEnableProjectSync,
EnableResourceSync: self.ManagerEnableResourceSync,
}
return ret, nil
}
if len(self.AccountProjectMappingId) > 0 {
return GetRuleMapping(self.AccountProjectMappingId)
ret := &sProjectMapping{
EnableProjectSync: self.AccountEnableProjectSync,
EnableResourceSync: self.AccountEnableResourceSync,
}
var err error
ret.SProjectMapping, err = GetRuleMapping(self.AccountProjectMappingId)
return ret, err
}
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty project mapping id")
}
@@ -141,9 +170,18 @@ var pmCaches map[string]*pmCache = map[string]*pmCache{}
func refreshPmCaches() error {
q := CloudproviderManager.Query().SubQuery()
providers := q.Query(q.Field("cloudaccount_id"), q.Field("id"), q.Field("project_mapping_id").Label("manager_project_mapping_id"))
providers := q.Query(
q.Field("cloudaccount_id"),
q.Field("id"),
q.Field("project_mapping_id").Label("manager_project_mapping_id"),
q.Field("enable_project_sync").Label("manager_enable_project_sync"),
q.Field("enable_resource_sync").Label("manager_enable_resource_sync"),
)
sq := CloudaccountManager.Query().SubQuery()
mq := providers.LeftJoin(sq, sqlchemy.Equals(q.Field("cloudaccount_id"), sq.Field("id"))).AppendField(sq.Field("project_mapping_id").Label("account_project_mapping_id"))
mq := providers.LeftJoin(sq, sqlchemy.Equals(q.Field("cloudaccount_id"), sq.Field("id"))).
AppendField(sq.Field("project_mapping_id").Label("account_project_mapping_id")).
AppendField(sq.Field("enable_project_sync").Label("account_enable_project_sync")).
AppendField(sq.Field("enable_resource_sync").Label("account_enable_resource_sync"))
caches := []pmCache{}
err := mq.All(&caches)
if err != nil {
@@ -155,7 +193,31 @@ func refreshPmCaches() error {
return nil
}
func (self *SCloudprovider) GetProjectMapping() (*SProjectMapping, error) {
func (self *SCloudaccount) GetProjectMapping() (*sProjectMapping, error) {
cache, err := func() (*pmCache, error) {
for id := range pmCaches {
if pmCaches[id].CloudaccountId == self.Id {
return pmCaches[id], nil
}
}
err := refreshPmCaches()
if err != nil {
return nil, errors.Wrapf(err, "refreshPmCaches")
}
for id := range pmCaches {
if pmCaches[id].CloudaccountId == self.Id {
return pmCaches[id], nil
}
}
return nil, cloudprovider.ErrNotFound
}()
if err != nil {
return nil, errors.Wrapf(err, "get project mapping cache")
}
return cache.GetProjectMapping()
}
func (self *SCloudprovider) GetProjectMapping() (*sProjectMapping, error) {
cache, err := func() (*pmCache, error) {
mp, ok := pmCaches[self.Id]
if ok {
@@ -1959,12 +2021,14 @@ func (self *SCloudprovider) PerformProjectMapping(ctx context.Context, userCred
return nil, httperrors.NewInputParameterError("cloudprovider %s has aleady bind project mapping %s", self.Name, self.ProjectMappingId)
}
}
// no changes
if self.ProjectMappingId == input.ProjectMappingId {
return nil, nil
}
_, err := db.Update(self, func() error {
self.ProjectMappingId = input.ProjectMappingId
if input.EnableProjectSync != nil {
self.EnableProjectSync = tristate.NewFromBool(*input.EnableProjectSync)
}
if input.EnableResourceSync != nil {
self.EnableResourceSync = tristate.NewFromBool(*input.EnableResourceSync)
}
return nil
})
if err != nil {
+1 -1
View File
@@ -2156,7 +2156,7 @@ func SyncCloudProject(userCred mcclient.TokenCredential, model db.IVirtualModel,
if err != nil {
return nil, errors.Wrapf(err, "GetCloudaccount")
}
if rm != nil && rm.Enabled.Bool() {
if rm != nil && rm.Enabled.Bool() && rm.IsNeedResourceSync() {
extTags, err := extModel.GetTags()
if err != nil {
return nil, errors.Wrapf(err, "extModel.GetTags")
+23
View File
@@ -391,9 +391,32 @@ func (manager *SExternalProjectManager) newFromCloudProject(ctx context.Context,
project.DomainId = domainId
}
}
pm, _ := account.GetProjectMapping()
if localProject != nil {
project.DomainId = localProject.DomainId
project.ProjectId = localProject.Id
} else if pm != nil && pm.Enabled.IsTrue() && pm.IsNeedProjectSync() {
extTags, err := extProject.GetTags()
if err != nil {
return nil, errors.Wrapf(err, "extModel.GetTags")
}
if pm.Rules != nil {
for _, rule := range *pm.Rules {
domainId, projectId, newProj, isMatch := rule.IsMatchTags(extTags)
if isMatch && len(newProj) > 0 {
domainId, projectId, err = account.getOrCreateTenant(context.TODO(), newProj, "", "", "auto create from tag")
if err != nil {
log.Errorf("getOrCreateTenant(%s) error: %v", newProj, err)
continue
}
if len(domainId) > 0 && len(projectId) > 0 {
project.DomainId = domainId
project.ProjectId = projectId
break
}
}
}
}
} else if account.AutoCreateProject {
desc := fmt.Sprintf("auto create from cloud project %s (%s)", project.Name, project.ExternalId)
domainId, projectId, err := account.getOrCreateTenant(ctx, project.Name, project.DomainId, "", desc)
+20 -1
View File
@@ -20,6 +20,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/tristate"
"yunion.io/x/pkg/util/reflectutils"
"yunion.io/x/sqlchemy"
@@ -32,11 +33,29 @@ import (
)
type SProjectMappingResourceBase struct {
ProjectMappingId string `width:"36" charset:"ascii" nullable:"false" create:"optional" index:"true" list:"user" json:"project_mapping_id"`
ProjectMappingId string `width:"36" charset:"ascii" nullable:"true" create:"optional" index:"true" list:"user" json:"project_mapping_id"`
EnableProjectSync tristate.TriState `default:"false" list:"user" create:"optional"`
EnableResourceSync tristate.TriState `default:"true" list:"user" create:"optional"`
}
type SProjectMappingResourceBaseManager struct{}
func (manager *SProjectMappingResourceBaseManager) ValidateCreateData(
ctx context.Context,
userCred mcclient.TokenCredential,
ownerId mcclient.IIdentityProvider,
query jsonutils.JSONObject,
input api.SProjectMappingResourceInput,
) (api.SProjectMappingResourceInput, error) {
if len(input.ProjectMappingId) > 0 {
_, err := validators.ValidateModel(userCred, ProjectMappingManager, &input.ProjectMappingId)
if err != nil {
return input, err
}
}
return input, nil
}
func (self *SProjectMappingResourceBase) GetProjectMapping() (*SProjectMapping, error) {
pm, err := ProjectMappingManager.FetchById(self.ProjectMappingId)
if err != nil {
+7 -1
View File
@@ -130,6 +130,10 @@ type SCloudAccountCreateBaseOptions struct {
DryRun bool `help:"test create cloudaccount params"`
ShowSubAccounts bool `help:"test and show subaccount info"`
ReadOnly bool `help:"Read only account"`
ProjectMappingId string
EnableProjectSync bool
EnableResourceSync bool
}
type SVMwareCloudAccountCreateOptions struct {
@@ -1116,7 +1120,9 @@ func (opts *SubscriptionCreateOptions) Params() (jsonutils.JSONObject, error) {
type ClouaccountProjectMappingOptions struct {
SCloudAccountIdOptions
ProjectMappingId string `json:"project_mapping_id" help:"project mapping id"`
ProjectMappingId string `json:"project_mapping_id" help:"project mapping id"`
EnableProjectSync bool
EnableResourceSync bool
}
func (opts *ClouaccountProjectMappingOptions) Params() (jsonutils.JSONObject, error) {