mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
fix(region): tags for project mapping (#15605)
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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,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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user