mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 04:27:15 +08:00
fix(region): external project support domain sync
This commit is contained in:
@@ -787,6 +787,9 @@ type ICloudSku interface {
|
||||
|
||||
type ICloudProject interface {
|
||||
ICloudResource
|
||||
|
||||
GetDomainId() string
|
||||
GetDomainName() string
|
||||
}
|
||||
|
||||
type ICloudNatGateway interface {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
type SResourceGroup struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.SProjectBase
|
||||
multicloud.AliyunTags
|
||||
client *SAliyunClient
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ type GroupProperties struct {
|
||||
}
|
||||
|
||||
type SResourceGroup struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.SProjectBase
|
||||
multicloud.AzureTags
|
||||
client *SAzureClient
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
var RESOURCEPOOL_PROPS = []string{"name", "parent", "host"}
|
||||
|
||||
type SResourcePool struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.SProjectBase
|
||||
multicloud.STagBase
|
||||
SManagedObject
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
)
|
||||
|
||||
type SProject struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.SProjectBase
|
||||
multicloud.GoogleTags
|
||||
Name string
|
||||
CreateTime time.Time
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
)
|
||||
|
||||
type SProject struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.SProjectBase
|
||||
multicloud.OpenStackTags
|
||||
client *SOpenStackClient
|
||||
Description string
|
||||
|
||||
@@ -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 ""
|
||||
}
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
type SProject struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.SProjectBase
|
||||
multicloud.QcloudTags
|
||||
client *SQcloudClient
|
||||
|
||||
|
||||
@@ -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"`
|
||||
|
||||
Reference in New Issue
Block a user