fix(region): external project support domain sync

This commit is contained in:
Qu Xuan
2021-09-22 20:27:21 +08:00
parent a24d7deaa2
commit 5a87ca7c90
15 changed files with 117 additions and 16 deletions
+3
View File
@@ -787,6 +787,9 @@ type ICloudSku interface {
type ICloudProject interface {
ICloudResource
GetDomainId() string
GetDomainName() string
}
type ICloudNatGateway interface {
+7 -4
View File
@@ -419,20 +419,23 @@ func createTenant(ctx context.Context, name, domainId, desc string) (string, str
return domainId, projectId, nil
}
func (self *SCloudaccount) getOrCreateTenant(ctx context.Context, name, projectId, desc string) (string, string, error) {
func (self *SCloudaccount) getOrCreateTenant(ctx context.Context, name, domainId, projectId, desc string) (string, string, error) {
if len(domainId) == 0 {
domainId = self.DomainId
}
tenant, err := getTenant(ctx, projectId, name)
if err != nil {
if errors.Cause(err) != sql.ErrNoRows {
return "", "", errors.Wrapf(err, "getTenan")
}
return createTenant(ctx, name, self.DomainId, desc)
return createTenant(ctx, name, domainId, desc)
}
share := self.GetSharedInfo()
if tenant.DomainId == self.DomainId || (share.PublicScope == rbacutils.ScopeSystem ||
(share.PublicScope == rbacutils.ScopeDomain && utils.IsInStringArray(tenant.DomainId, share.SharedDomains))) {
return tenant.DomainId, tenant.Id, nil
}
return createTenant(ctx, name, self.DomainId, desc)
return createTenant(ctx, name, domainId, desc)
}
func (self *SCloudprovider) syncProject(ctx context.Context, userCred mcclient.TokenCredential) error {
@@ -442,7 +445,7 @@ func (self *SCloudprovider) syncProject(ctx context.Context, userCred mcclient.T
}
desc := fmt.Sprintf("auto create from cloud provider %s (%s)", self.Name, self.Id)
domainId, projectId, err := account.getOrCreateTenant(ctx, self.Name, self.ProjectId, desc)
domainId, projectId, err := account.getOrCreateTenant(ctx, self.Name, "", self.ProjectId, desc)
if err != nil {
return errors.Wrap(err, "getOrCreateTenant")
}
+1 -1
View File
@@ -1549,7 +1549,7 @@ func SyncCloudProject(userCred mcclient.TokenCredential, model db.IVirtualModel,
domainId, projectId, newProj, isMatch := rule.IsMatchTags(extTags)
if isMatch {
if len(newProj) > 0 {
domainId, projectId, err = account.getOrCreateTenant(context.TODO(), newProj, "", "auto create from tag")
domainId, projectId, err = account.getOrCreateTenant(context.TODO(), newProj, "", "", "auto create from tag")
if err != nil {
return nil, errors.Wrapf(err, "getOrCreateTenant(%s)", newProj)
}
+61 -2
View File
@@ -26,6 +26,7 @@ import (
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
@@ -66,6 +67,7 @@ type SExternalProject struct {
db.SExternalizedResourceBase
SManagedResourceBase
ExternalDomainId string `width:"36" charset:"ascii" nullable:"true" list:"user"`
// 归属云账号ID
CloudaccountId string `width:"36" charset:"ascii" nullable:"false" list:"user"`
}
@@ -211,7 +213,7 @@ func (self *SExternalProject) SyncWithCloudProject(ctx context.Context, userCred
self.DomainId = account.DomainId
if account.AutoCreateProject {
desc := fmt.Sprintf("auto create from cloud project %s (%s)", self.Name, self.ExternalId)
domainId, projectId, err := account.getOrCreateTenant(ctx, self.Name, "", desc)
domainId, projectId, err := account.getOrCreateTenant(ctx, self.Name, "", "", desc)
if err != nil {
log.Errorf("failed to get or create tenant %s(%s) %v", self.Name, self.ExternalId, err)
} else {
@@ -262,6 +264,53 @@ func (self *SExternalProject) SyncWithCloudProject(ctx context.Context, userCred
return nil
}
func (self *SCloudaccount) getOrCreateDomain(ctx context.Context, userCred mcclient.TokenCredential, id, name string) (string, error) {
lockman.LockRawObject(ctx, self.Id, CloudaccountManager.Keyword())
defer lockman.ReleaseRawObject(ctx, self.Id, CloudaccountManager.Keyword())
domainId := ""
domain, err := db.TenantCacheManager.FetchDomainByIdOrName(ctx, name)
if err != nil {
if errors.Cause(err) != sql.ErrNoRows {
return "", errors.Wrapf(err, "FetchDomainByIdOrName")
}
s := auth.GetAdminSession(ctx, options.Options.Region, "")
params := jsonutils.NewDict()
params.Add(jsonutils.NewString(name), "generate_name")
desc := fmt.Sprintf("auto create from cloud project %s (%s)", id, name)
params.Add(jsonutils.NewString(desc), "description")
resp, err := modules.Domains.Create(s, params)
if err != nil {
return "", errors.Wrap(err, "Projects.Create")
}
domainId, err = resp.GetString("id")
if err != nil {
return "", errors.Wrapf(err, "resp.GetString")
}
} else {
domainId = domain.Id
}
share := self.GetSharedInfo()
if share.PublicScope == rbacutils.ScopeSystem {
return domainId, nil
}
input := api.CloudaccountPerformPublicInput{}
input.ShareMode = string(rbacutils.ScopeSystem)
input.PerformPublicDomainInput = apis.PerformPublicDomainInput{
Scope: string(rbacutils.ScopeDomain),
SharedDomains: append(share.SharedDomains, domainId),
SharedDomainIds: append(share.SharedDomains, domainId),
}
_, err = self.SInfrasResourceBase.PerformPublic(ctx, userCred, jsonutils.NewDict(), input.PerformPublicDomainInput)
if err != nil {
return "", errors.Wrapf(err, "PerformPublic")
}
return domainId, self.setShareMode(userCred, input.ShareMode)
}
func (manager *SExternalProjectManager) newFromCloudProject(ctx context.Context, userCred mcclient.TokenCredential, account *SCloudaccount, localProject *db.STenant, extProject cloudprovider.ICloudProject) (*SExternalProject, error) {
project := SExternalProject{}
project.SetModelManager(manager, &project)
@@ -273,12 +322,22 @@ func (manager *SExternalProjectManager) newFromCloudProject(ctx context.Context,
project.CloudaccountId = account.Id
project.DomainId = account.DomainId
project.ProjectId = account.ProjectId
project.ExternalDomainId = extProject.GetDomainId()
domainName := extProject.GetDomainName()
if len(project.ExternalDomainId) > 0 && len(domainName) > 0 {
domainId, err := account.getOrCreateDomain(ctx, userCred, project.ExternalDomainId, domainName)
if err != nil {
log.Errorf("getOrCreateDomain for project %s error: %v", account.Name, err)
} else {
project.DomainId = domainId
}
}
if localProject != nil {
project.DomainId = localProject.DomainId
project.ProjectId = localProject.Id
} 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, "", desc)
domainId, projectId, err := account.getOrCreateTenant(ctx, project.Name, project.DomainId, "", desc)
if err != nil {
log.Errorf("failed to get or create tenant %s(%s) %v", project.Name, project.ExternalId, err)
} else {
+1 -1
View File
@@ -27,7 +27,7 @@ import (
)
type SResourceGroup struct {
multicloud.SResourceBase
multicloud.SProjectBase
multicloud.AliyunTags
client *SAliyunClient
+8
View File
@@ -58,6 +58,14 @@ func (self *SResourceGroup) GetId() string {
return self.Id
}
func (self *SResourceGroup) GetDomainName() string {
return self.OrganizationName
}
func (self *SResourceGroup) GetDomainId() string {
return self.OrganizationId
}
func (self *SResourceGroup) GetName() string {
return self.ResourceGroupName
}
+1 -1
View File
@@ -30,7 +30,7 @@ type GroupProperties struct {
}
type SResourceGroup struct {
multicloud.SResourceBase
multicloud.SProjectBase
multicloud.AzureTags
client *SAzureClient
+1 -1
View File
@@ -27,7 +27,7 @@ import (
var RESOURCEPOOL_PROPS = []string{"name", "parent", "host"}
type SResourcePool struct {
multicloud.SResourceBase
multicloud.SProjectBase
multicloud.STagBase
SManagedObject
}
+1 -1
View File
@@ -24,7 +24,7 @@ import (
)
type SProject struct {
multicloud.SResourceBase
multicloud.SProjectBase
multicloud.GoogleTags
Name string
CreateTime time.Time
+1 -1
View File
@@ -28,7 +28,7 @@ import (
// https://support.huaweicloud.com/api-em/zh-cn_topic_0121230880.html
type SEnterpriseProject struct {
multicloud.SResourceBase
multicloud.SProjectBase
multicloud.HuaweiTags
Id string
+1 -1
View File
@@ -28,7 +28,7 @@ import (
// https://support.huaweicloud.com/api-em/zh-cn_topic_0121230880.html
type SEnterpriseProject struct {
multicloud.SResourceBase
multicloud.SProjectBase
multicloud.HuaweiTags
Id string
+1 -1
View File
@@ -28,7 +28,7 @@ import (
)
type SProject struct {
multicloud.SResourceBase
multicloud.SProjectBase
multicloud.OpenStackTags
client *SOpenStackClient
Description string
+28
View File
@@ -0,0 +1,28 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package multicloud
type SProjectBase struct {
SResourceBase
STagBase
}
func (self *SProjectBase) GetDomainName() string {
return ""
}
func (self *SProjectBase) GetDomainId() string {
return ""
}
+1 -1
View File
@@ -27,7 +27,7 @@ import (
)
type SProject struct {
multicloud.SResourceBase
multicloud.SProjectBase
multicloud.QcloudTags
client *SQcloudClient
+1 -1
View File
@@ -20,7 +20,7 @@ import (
// https://docs.ucloud.cn/api/summary/get_project_list
type SProject struct {
multicloud.SResourceBase
multicloud.SProjectBase
multicloud.UcloudTags
ProjectID string `json:"ProjectId"`
ProjectName string `json:"ProjectName"`