feat(region): qcloud&aliyun&huawei add sslcertificate resource sync (#18570)

* feat(region): qcloud&aliyun&huawei add sslcertificate resource sync

* fix(region): move syncSslcert from syncPublicCloudProviderInfo to SyncCloudproviderResources
This commit is contained in:
Lptnyy
2023-11-10 11:54:30 +08:00
committed by GitHub
parent 3ca9dc0f51
commit 2c3d5213ba
19 changed files with 703 additions and 226 deletions
+1 -1
View File
@@ -83,7 +83,7 @@ require (
k8s.io/client-go v0.19.3
k8s.io/cluster-bootstrap v0.19.3
moul.io/http2curl/v2 v2.3.0
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20231108113200-c307a4311ac0
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20231109103941-088a0a8e9777
yunion.io/x/executor v0.0.0-20230705125604-c5ac3141db32
yunion.io/x/jsonutils v1.0.1-0.20230613121553-0f3b41e2ef19
yunion.io/x/log v1.0.1-0.20230411060016-feb3f46ab361
+2 -2
View File
@@ -1179,8 +1179,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20231108113200-c307a4311ac0 h1:hD7YP1+wTo2xVyM8qefD2kmzbgHve2woPUYJ8R0AxE8=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20231108113200-c307a4311ac0/go.mod h1:McRjoG2gaOUisB+Qa41kLCNZhr0lsCu4apEjTiphXVY=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20231109103941-088a0a8e9777 h1:DfrV/vUFKBn2RWt3o1i++91FPSFf80HmjGjL5vPxQco=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20231109103941-088a0a8e9777/go.mod h1:McRjoG2gaOUisB+Qa41kLCNZhr0lsCu4apEjTiphXVY=
yunion.io/x/executor v0.0.0-20230705125604-c5ac3141db32 h1:v7POYkQwo1XzOxBoIoRVr/k0V9Y5JyjpshlIFa9raug=
yunion.io/x/executor v0.0.0-20230705125604-c5ac3141db32/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
+24
View File
@@ -0,0 +1,24 @@
package compute
import "yunion.io/x/onecloud/pkg/apis"
// 资源创建参数, 目前仅占位
type SSLCertificateCreateInput struct {
}
// 资源返回详情
type SSLCertificateDetails struct {
apis.VirtualResourceDetails
ManagedResourceInfo
CloudregionResourceInfo
}
// 资源列表请求参数
type SSLCertificateListInput struct {
apis.VirtualResourceListInput
apis.ExternalizedResourceBaseListInput
apis.DeletePreventableResourceBaseListInput
RegionalFilterListInput
ManagedResourceListInput
}
+17
View File
@@ -2722,6 +2722,10 @@ func SyncCloudproviderResources(ctx context.Context, userCred mcclient.TokenCred
}
}
if cloudprovider.IsSupportSSLCertificate(driver) && syncRange.NeedSyncResource(cloudprovider.CLOUD_CAPABILITY_CERT) {
syncSSLCertificates(ctx, userCred, SSyncResultSet{}, provider, driver, syncRange.Xor)
}
return nil
}
@@ -2814,6 +2818,19 @@ func syncGlobalVpcs(ctx context.Context, userCred mcclient.TokenCredential, sync
return nil
}
func syncSSLCertificates(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, driver cloudprovider.ICloudProvider, xor bool) error {
iEss, err := driver.GetISSLCertificates()
if err != nil {
return err
}
result := provider.SyncSSLCertificates(ctx, userCred, iEss)
notes := fmt.Sprintf("SyncSSLCertificates for provider %s result: %s", provider.Name, result.Result())
log.Infof(notes)
provider.SyncError(result, notes, userCred)
return nil
}
func syncTablestore(
ctx context.Context,
userCred mcclient.TokenCredential,
+379
View File
@@ -0,0 +1,379 @@
package models
import (
"context"
"time"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
type SSSLCertificateManager struct {
db.SVirtualResourceBaseManager
db.SExternalizedResourceBaseManager
SDeletePreventableResourceBaseManager
SManagedResourceBaseManager
}
var SSLCertificateManager *SSSLCertificateManager
func init() {
SSLCertificateManager = &SSSLCertificateManager{
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
SSSLCertificate{},
"sslcertificates_tbl",
"sslcertificate",
"sslcertificates",
),
}
SSLCertificateManager.SetVirtualObject(SSLCertificateManager)
}
type SSSLCertificate struct {
db.SVirtualResourceBase
db.SExternalizedResourceBase
SManagedResourceBase
SDeletePreventableResourceBase
Sans string `width:"2048" charset:"utf8" nullable:"false" list:"user" create:"required"`
StartDate time.Time `nullable:"false" list:"user" json:"start_date"`
Province string `width:"2048" charset:"utf8" nullable:"false" list:"user" create:"required"`
Common string `width:"2048" charset:"utf8" nullable:"false" list:"user" create:"required"`
Country string `width:"2048" charset:"utf8" nullable:"false" list:"user" create:"required"`
Issuer string `width:"2048" charset:"utf8" nullable:"false" list:"user" create:"required"`
Expired bool `charset:"utf8" nullable:"false" list:"user" create:"required"`
IsUpload bool `charset:"utf8" nullable:"false" list:"user" create:"required"`
EndDate time.Time `nullable:"false" list:"user" json:"end_date"`
Fingerprint string `width:"128" charset:"utf8" nullable:"false" list:"user" create:"required"`
City string `width:"2048" charset:"utf8" nullable:"false" list:"user" create:"required"`
OrgName string `width:"2048" charset:"utf8" nullable:"false" list:"user" create:"required"`
Certificate string `charset:"utf8" nullable:"false" list:"user" create:"required"`
PrivateKey string `charset:"utf8" nullable:"false" list:"user" create:"required"`
}
func (s SSSLCertificate) GetExternalId() string {
return s.ExternalId
}
func (man *SSSLCertificateManager) FetchCustomizeColumns(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
objs []interface{},
fields stringutils2.SSortedStrings,
isList bool,
) []api.SSLCertificateDetails {
rows := make([]api.SSLCertificateDetails, len(objs))
virtRows := man.SVirtualResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
manRows := man.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
for i := range rows {
rows[i] = api.SSLCertificateDetails{
VirtualResourceDetails: virtRows[i],
ManagedResourceInfo: manRows[i],
}
}
return rows
}
func (man *SSSLCertificateManager) GetContextManagers() [][]db.IModelManager {
return [][]db.IModelManager{
{CloudproviderManager},
}
}
// SSLCertificate实例列表
func (man *SSSLCertificateManager) ListItemFilter(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
query api.SSLCertificateListInput,
) (*sqlchemy.SQuery, error) {
var err error
q, err = man.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query.VirtualResourceListInput)
if err != nil {
return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemFilter")
}
q, err = man.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
if err != nil {
return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
}
q, err = man.SDeletePreventableResourceBaseManager.ListItemFilter(ctx, q, userCred, query.DeletePreventableResourceBaseListInput)
if err != nil {
return nil, errors.Wrap(err, "SDeletePreventableResourceBaseManager.ListItemFilter")
}
q, err = man.SManagedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ManagedResourceListInput)
if err != nil {
return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemFilter")
}
return q, nil
}
func (man *SSSLCertificateManager) OrderByExtraFields(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
query api.SSLCertificateListInput,
) (*sqlchemy.SQuery, error) {
q, err := man.SVirtualResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.VirtualResourceListInput)
if err != nil {
return nil, errors.Wrap(err, "SVirtualResourceBaseManager.OrderByExtraFields")
}
q, err = man.SManagedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ManagedResourceListInput)
if err != nil {
return nil, errors.Wrap(err, "SManagedResourceBaseManager.OrderByExtraFields")
}
return q, nil
}
func (man *SSSLCertificateManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
q, err := man.SVirtualResourceBaseManager.QueryDistinctExtraField(q, field)
if err == nil {
return q, nil
}
q, err = man.SManagedResourceBaseManager.QueryDistinctExtraField(q, field)
if err == nil {
return q, nil
}
return q, httperrors.ErrNotFound
}
func (man *SSSLCertificateManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.SSLCertificateCreateInput) (api.SSLCertificateCreateInput, error) {
return input, httperrors.NewNotImplementedError("Not Implemented")
}
func (r *SCloudprovider) GetSSLCertificates() ([]SSSLCertificate, error) {
q := SSLCertificateManager.Query().Equals("manager_id", r.Id)
ret := make([]SSSLCertificate, 0)
err := db.FetchModelObjects(SSLCertificateManager, q, &ret)
if err != nil {
return nil, errors.Wrapf(err, "db.FetchModelObjects")
}
return ret, nil
}
func (r *SCloudprovider) SyncSSLCertificates(
ctx context.Context,
userCred mcclient.TokenCredential,
exts []cloudprovider.ICloudSSLCertificate,
) compare.SyncResult {
// 加锁防止重入
lockman.LockRawObject(ctx, SSLCertificateManager.KeywordPlural(), r.Id)
defer lockman.ReleaseRawObject(ctx, SSLCertificateManager.KeywordPlural(), r.Id)
result := compare.SyncResult{}
dbEss, err := r.GetSSLCertificates()
if err != nil {
result.Error(err)
return result
}
removed := make([]SSSLCertificate, 0)
commondb := make([]SSSLCertificate, 0)
commonext := make([]cloudprovider.ICloudSSLCertificate, 0)
added := make([]cloudprovider.ICloudSSLCertificate, 0)
// 本地和云上资源列表进行比对
err = compare.CompareSets(dbEss, exts, &removed, &commondb, &commonext, &added)
if err != nil {
result.Error(err)
return result
}
// 删除云上没有的资源
for i := 0; i < len(removed); i++ {
err := removed[i].syncRemoveCloudSSLCertificate(ctx, userCred)
if err != nil {
result.DeleteError(err)
continue
}
result.Delete()
}
// 和云上资源属性进行同步
for i := 0; i < len(commondb); i++ {
err := commondb[i].SyncWithCloudSSLCertificate(ctx, userCred, commonext[i])
if err != nil {
result.UpdateError(err)
continue
}
result.Update()
}
// 创建本地没有的云上资源
for i := 0; i < len(added); i++ {
_, err := r.newFromCloudSSLCertificate(ctx, userCred, added[i])
if err != nil {
result.AddError(err)
continue
}
result.Add()
}
return result
}
func (s *SSSLCertificate) syncRemoveCloudSSLCertificate(ctx context.Context, userCred mcclient.TokenCredential) error {
err := s.RealDelete(ctx, userCred)
if err != nil {
return err
}
notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
Obj: s,
Action: notifyclient.ActionSyncDelete,
})
return nil
}
func (s *SSSLCertificate) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
return s.SVirtualResourceBase.Delete(ctx, userCred)
}
// 同步资源属性
func (s *SSSLCertificate) SyncWithCloudSSLCertificate(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudSSLCertificate) error {
diff, err := db.UpdateWithLock(ctx, s, func() error {
s.ExternalId = ext.GetGlobalId()
s.Status = ext.GetStatus()
s.Name = ext.GetName()
s.Sans = ext.GetSans()
s.StartDate = ext.GetStartDate()
s.Province = ext.GetProvince()
s.Common = ext.GetCommon()
s.Country = ext.GetCountry()
s.Issuer = ext.GetIssuer()
s.Expired = ext.GetExpired()
s.IsUpload = ext.GetIsUpload()
s.EndDate = ext.GetEndDate()
s.Fingerprint = ext.GetFingerprint()
s.City = ext.GetCity()
s.OrgName = ext.GetOrgName()
s.Certificate = ext.GetCert()
s.PrivateKey = ext.GetKey()
return nil
})
if err != nil {
return errors.Wrapf(err, "db.Update")
}
if len(diff) > 0 {
notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
Obj: s,
Action: notifyclient.ActionSyncUpdate,
})
}
_ = syncVirtualResourceMetadata(ctx, userCred, s, ext)
//_ = syncMetadata(ctx, userCred, s, ext)
if provider := s.GetCloudprovider(); provider != nil {
SyncCloudProject(ctx, userCred, s, provider.GetOwnerId(), ext, provider.Id)
}
db.OpsLog.LogSyncUpdate(s, diff, userCred)
return nil
}
func (r *SCloudprovider) newFromCloudSSLCertificate(
ctx context.Context,
userCred mcclient.TokenCredential,
ext cloudprovider.ICloudSSLCertificate,
) (*SSSLCertificate, error) {
s := SSSLCertificate{}
s.SetModelManager(SSLCertificateManager, &s)
s.ExternalId = ext.GetGlobalId()
s.ManagerId = r.Id
s.IsEmulated = ext.IsEmulated()
s.Status = ext.GetStatus()
s.Name = ext.GetName()
s.Sans = ext.GetSans()
s.StartDate = ext.GetStartDate()
s.Province = ext.GetProvince()
s.Common = ext.GetCommon()
s.Country = ext.GetCountry()
s.Issuer = ext.GetIssuer()
s.Expired = ext.GetExpired()
s.IsUpload = ext.GetIsUpload()
s.EndDate = ext.GetEndDate()
s.Fingerprint = ext.GetFingerprint()
s.City = ext.GetCity()
s.OrgName = ext.GetOrgName()
s.Certificate = ext.GetCert()
s.PrivateKey = ext.GetKey()
if createdAt := ext.GetCreatedAt(); !createdAt.IsZero() {
s.CreatedAt = createdAt
}
var err error
err = func() error {
// 这里加锁是为了防止名称重复
lockman.LockRawObject(ctx, SSLCertificateManager.Keyword(), "name")
defer lockman.ReleaseRawObject(ctx, SSLCertificateManager.Keyword(), "name")
s.Name, err = db.GenerateName(ctx, SSLCertificateManager, r.GetOwnerId(), ext.GetName())
if err != nil {
return errors.Wrapf(err, "db.GenerateName")
}
return SSLCertificateManager.TableSpec().Insert(ctx, &s)
}()
if err != nil {
return nil, errors.Wrapf(err, "newFromCloudSSLCertificate.Insert")
}
notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
Obj: &s,
Action: notifyclient.ActionSyncCreate,
})
// 同步标签
_ = syncVirtualResourceMetadata(ctx, userCred, &s, ext)
// 同步项目归属
SyncCloudProject(ctx, userCred, &s, r.GetOwnerId(), ext, r.Id)
db.OpsLog.LogEvent(&s, db.ACT_CREATE, s.GetShortDesc(ctx), userCred)
return &s, nil
}
func (man *SSSLCertificateManager) ListItemExportKeys(ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
keys stringutils2.SSortedStrings,
) (*sqlchemy.SQuery, error) {
var err error
q, err = man.SVirtualResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
if err != nil {
return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemExportKeys")
}
if keys.ContainsAny(man.SManagedResourceBaseManager.GetExportKeys()...) {
q, err = man.SManagedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
if err != nil {
return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemExportKeys")
}
}
return q, nil
}
+2
View File
@@ -243,6 +243,8 @@ func InitHandlers(app *appsrv.Application) {
models.ModelartsPoolSkuManager,
models.MiscResourceManager,
models.SSLCertificateManager,
} {
db.RegisterModelManager(manager)
handler := db.NewModelHandler(manager)
+1 -1
View File
@@ -1438,7 +1438,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
# sigs.k8s.io/yaml v1.2.0
## explicit; go 1.12
sigs.k8s.io/yaml
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20231108113200-c307a4311ac0
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20231109103941-088a0a8e9777
## explicit; go 1.18
yunion.io/x/cloudmux/pkg/apis
yunion.io/x/cloudmux/pkg/apis/billing
+6
View File
@@ -319,6 +319,8 @@ type ICloudProvider interface {
CreateICloudCDNDomain(opts *CdnCreateOptions) (ICloudCDNDomain, error)
GetMetrics(opts *MetricListOptions) ([]MetricValues, error)
GetISSLCertificates() ([]ICloudSSLCertificate, error)
}
func IsSupportCapability(prod ICloudProvider, capa string) bool {
@@ -644,6 +646,10 @@ func (self *SBaseProvider) GetIModelartsPoolSku() ([]ICloudModelartsPoolSku, err
return nil, errors.Wrapf(ErrNotImplemented, "GetIModelartsPoolSku")
}
func (self *SBaseProvider) GetISSLCertificates() ([]ICloudSSLCertificate, error) {
return nil, errors.Wrapf(ErrNotImplemented, "GetISSLCertificates")
}
func NewBaseProvider(factory ICloudProviderFactory) SBaseProvider {
return SBaseProvider{factory: factory}
}
-2
View File
@@ -203,8 +203,6 @@ type ICloudRegion interface {
GetIModelartsPoolSku() ([]ICloudModelartsPoolSku, error)
GetIMiscResources() ([]ICloudMiscResource, error)
GetISSLCertificates() ([]ICloudSSLCertificate, error)
}
type ICloudZone interface {
+44
View File
@@ -961,6 +961,50 @@ func (self *SAliyunClient) GetIProjects() ([]cloudprovider.ICloudProject, error)
return ret, nil
}
func (self *SAliyunClient) scRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
client, err := self.getSdkClient(ALIYUN_DEFAULT_REGION)
if err != nil {
return nil, err
}
domain := "cas.aliyuncs.com"
return jsonRequest(client, domain, ALIYUN_CAS_API_VERSION, apiName, params, self.debug)
}
func (self *SAliyunClient) GetISSLCertificates() ([]cloudprovider.ICloudSSLCertificate, error) {
ret := make([]SSSLCertificate, 0)
for {
part, total, err := self.GetSSLCertificates(100, len(ret)/100+1)
if err != nil {
return nil, errors.Wrapf(err, "GetSSLCertificates")
}
ret = append(ret, part...)
if len(ret) >= total {
break
}
}
result := make([]cloudprovider.ICloudSSLCertificate, 0)
for i := range ret {
if !ret[i].BuyInAliyun {
continue
}
ret[i].client = self
result = append(result, &ret[i])
}
return result, nil
}
func (self *SAliyunClient) GetISSLCertificate(certId string) (cloudprovider.ICloudSSLCertificate, error) {
var res cloudprovider.ICloudSSLCertificate
res, err := self.GetSSLCertificate(certId)
if err != nil {
return nil, errors.Wrapf(err, "GetSSLCertificate")
}
return res, nil
}
func (region *SAliyunClient) GetCapabilities() []string {
caps := []string{
cloudprovider.CLOUD_CAPABILITY_PROJECT,
@@ -527,3 +527,11 @@ func (self *SAliyunProvider) GetICloudCDNDomainByName(name string) (cloudprovide
func (self *SAliyunProvider) GetMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) {
return self.client.GetMetrics(opts)
}
func (self *SAliyunProvider) GetISSLCertificates() ([]cloudprovider.ICloudSSLCertificate, error) {
return self.client.GetISSLCertificates()
}
func (self *SAliyunProvider) GetISSLCertificate(certId string) (cloudprovider.ICloudSSLCertificate, error) {
return self.client.GetISSLCertificate(certId)
}
+13 -37
View File
@@ -5,7 +5,6 @@ import (
"strconv"
"time"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/cloudmux/pkg/multicloud"
"yunion.io/x/pkg/errors"
)
@@ -13,7 +12,7 @@ import (
type SSSLCertificate struct {
multicloud.SVirtualResourceBase
AliyunTags
region *SRegion
client *SAliyunClient
Sans string // 证书的SANSubject Alternative Name)扩展属性,表示证书关联的其他域名、IP地址等
Id int // 证书ID
@@ -116,45 +115,22 @@ func (s *SSSLCertificate) GetKey() string {
func (s *SSSLCertificate) GetDetails() (*SSSLCertificate, error) {
if !s.detailsInitd {
cert, err := s.region.GetCertificate(s.GetId())
cert, err := s.client.GetISSLCertificate(s.GetId())
if err != nil {
return nil, err
}
s.detailsInitd = true
s.Cert = cert.Cert
s.Key = cert.Key
_cert, ok := cert.(*SSSLCertificate)
if !ok {
return nil, errors.Wrapf(err, "cert.(*SSSLCertificate)")
}
s.Cert = _cert.Cert
s.Key = _cert.Key
}
return s, nil
}
// GetISSLCertificates 获取证书资源列表
func (r *SRegion) GetISSLCertificates() ([]cloudprovider.ICloudSSLCertificate, error) {
ret := make([]SSSLCertificate, 0)
for {
part, total, err := r.GetSSLCertificates(100, len(ret)/100+1)
if err != nil {
return nil, errors.Wrapf(err, "GetSSLCertificates")
}
ret = append(ret, part...)
if len(ret) >= total {
break
}
}
result := make([]cloudprovider.ICloudSSLCertificate, 0)
for i := range ret {
if !ret[i].BuyInAliyun {
continue
}
ret[i].region = r
result = append(result, &ret[i])
}
return result, nil
}
func (r *SRegion) GetSSLCertificates(size, page int) ([]SSSLCertificate, int, error) {
func (self *SAliyunClient) GetSSLCertificates(size, page int) ([]SSSLCertificate, int, error) {
if size < 1 || size > 100 {
size = 100
}
@@ -166,7 +142,7 @@ func (r *SRegion) GetSSLCertificates(size, page int) ([]SSSLCertificate, int, er
"ShowSize": fmt.Sprintf("%d", size),
"CurrentPage": fmt.Sprintf("%d", page),
}
resp, err := r.scRequest("DescribeUserCertificateList", params)
resp, err := self.scRequest("DescribeUserCertificateList", params)
if err != nil {
return nil, 0, errors.Wrapf(err, "DescribeUserCertificateList")
}
@@ -181,11 +157,11 @@ func (r *SRegion) GetSSLCertificates(size, page int) ([]SSSLCertificate, int, er
return ret, int(totalCount), nil
}
func (r *SRegion) GetCertificate(certId string) (*SSSLCertificate, error) {
func (self *SAliyunClient) GetSSLCertificate(certId string) (*SSSLCertificate, error) {
params := map[string]string{
"CertId": fmt.Sprintf("%s", certId),
}
resp, err := r.scRequest("DescribeUserCertificateDetail", params)
resp, err := self.scRequest("DescribeUserCertificateDetail", params)
if err != nil {
return nil, errors.Wrap(err, "DescribeUserCertificateDetail")
}
@@ -195,7 +171,7 @@ func (r *SRegion) GetCertificate(certId string) (*SSSLCertificate, error) {
if err != nil {
return nil, errors.Wrap(err, "Unmarshal")
}
cert.region = r
cert.client = self
return cert, nil
}
+47 -5
View File
@@ -57,8 +57,9 @@ const (
HUAWEI_INTERNATIONAL_CLOUDENV = "InternationalCloud"
HUAWEI_CHINA_CLOUDENV = "ChinaCloud"
HUAWEI_DEFAULT_REGION = "cn-north-1"
HUAWEI_API_VERSION = "2018-12-25"
HUAWEI_DEFAULT_REGION = "cn-north-1"
HUAWEI_CERT_DEFAULT_REGION = "cn-north-4"
HUAWEI_API_VERSION = "2018-12-25"
SERVICE_IAM = "iam"
SERVICE_ELB = "elb"
@@ -126,8 +127,9 @@ type SHuaweiClient struct {
signer auth.Signer
isMainProject bool // whether the project is the main project in the region
clientRegion string
isMainProject bool // whether the project is the main project in the region
isSyncCertProject bool
clientRegion string
userId string
ownerId string
@@ -483,6 +485,9 @@ func (self *SHuaweiClient) fetchRegions() error {
self.isMainProject = true
}
}
if project.Name == HUAWEI_CERT_DEFAULT_REGION {
self.isSyncCertProject = true
}
} else {
filtedRegions = self.regions
}
@@ -796,6 +801,41 @@ func (self *SHuaweiClient) queryDomainBalances(domainId string) ([]SBalance, err
return balances, nil
}
func (self *SHuaweiClient) GetISSLCertificates() ([]cloudprovider.ICloudSSLCertificate, error) {
ret := make([]SSSLCertificate, 0)
offset := 0
for {
part, total, err := self.GetSSLCertificates(50, offset)
if err != nil {
return nil, errors.Wrapf(err, "GetSSLCertificates")
}
ret = append(ret, part...)
if len(ret) >= total {
break
}
offset += 50
}
result := make([]cloudprovider.ICloudSSLCertificate, 0)
for i := range ret {
ret[i].client = self
result = append(result, &ret[i])
}
return result, nil
}
func (self *SHuaweiClient) GetISSLCertificate(certId string) (cloudprovider.ICloudSSLCertificate, error) {
var res cloudprovider.ICloudSSLCertificate
res, err := self.GetSSLCertificate(certId)
if err != nil {
return nil, errors.Wrapf(err, "GetSSLCertificate")
}
return res, nil
}
func (self *SHuaweiClient) GetVersion() string {
return HUAWEI_API_VERSION
}
@@ -830,7 +870,6 @@ func (self *SHuaweiClient) GetCapabilities() []string {
cloudprovider.CLOUD_CAPABILITY_QUOTA + cloudprovider.READ_ONLY_SUFFIX,
cloudprovider.CLOUD_CAPABILITY_MODELARTES,
cloudprovider.CLOUD_CAPABILITY_VPC_PEER,
cloudprovider.CLOUD_CAPABILITY_CERT,
}
// huawei objectstore is shared across projects(subscriptions)
// to avoid multiple project access the same bucket
@@ -838,6 +877,9 @@ func (self *SHuaweiClient) GetCapabilities() []string {
if self.isMainProject {
caps = append(caps, cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE)
}
if self.isSyncCertProject {
caps = append(caps, cloudprovider.CLOUD_CAPABILITY_CERT)
}
return caps
}
@@ -311,3 +311,11 @@ func (self *SHuaweiProvider) GetMetrics(opts *cloudprovider.MetricListOptions) (
}
return metrics, nil
}
func (self *SHuaweiProvider) GetISSLCertificates() ([]cloudprovider.ICloudSSLCertificate, error) {
return self.client.GetISSLCertificates()
}
func (self *SHuaweiProvider) GetISSLCertificate(certId string) (cloudprovider.ICloudSSLCertificate, error) {
return self.client.GetISSLCertificate(certId)
}
+13 -38
View File
@@ -9,7 +9,6 @@ import (
"net/url"
"time"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/cloudmux/pkg/multicloud"
"yunion.io/x/pkg/errors"
)
@@ -17,7 +16,7 @@ import (
type SSSLCertificate struct {
multicloud.SVirtualResourceBase
HuaweiTags
region *SRegion
client *SHuaweiClient
Id string // 证书ID
Name string // 证书名称
@@ -138,45 +137,22 @@ func (s *SSSLCertificate) GetKey() string {
func (s *SSSLCertificate) GetDetails() (*SSSLCertificate, error) {
if !s.detailsInitd {
cert, err := s.region.GetCertificate(s.GetId())
cert, err := s.client.GetISSLCertificate(s.GetId())
if err != nil {
return nil, err
}
s.detailsInitd = true
s.Certificate = cert.Certificate
s.PrivateKey = cert.PrivateKey
_cert, ok := cert.(*SSSLCertificate)
if !ok {
return nil, errors.Wrapf(err, "cert.(*SSSLCertificate)")
}
s.Certificate = _cert.Certificate
s.PrivateKey = _cert.PrivateKey
}
return s, nil
}
// GetISSLCertificates 获取证书资源列表
func (r *SRegion) GetISSLCertificates() ([]cloudprovider.ICloudSSLCertificate, error) {
ret := make([]SSSLCertificate, 0)
offset := 0
for {
part, total, err := r.GetSSLCertificates(50, offset)
if err != nil {
return nil, errors.Wrapf(err, "GetSSLCertificates")
}
ret = append(ret, part...)
if len(ret) >= total {
break
}
offset += 50
}
result := make([]cloudprovider.ICloudSSLCertificate, 0)
for i := range ret {
ret[i].region = r
result = append(result, &ret[i])
}
return result, nil
}
func (r *SRegion) GetSSLCertificates(size, offset int) ([]SSSLCertificate, int, error) {
func (r *SHuaweiClient) GetSSLCertificates(size, offset int) ([]SSSLCertificate, int, error) {
if size < 1 || size > 50 {
size = 50
}
@@ -190,7 +166,7 @@ func (r *SRegion) GetSSLCertificates(size, offset int) ([]SSSLCertificate, int,
"sort_key": []string{"certExpiredTime"},
"sort_dir": []string{"DESC"},
}
resp, err := r.client.sslcertList(r.ID, "scm/certificates", params)
resp, err := r.sslcertList(HUAWEI_CERT_DEFAULT_REGION, "scm/certificates", params)
if err != nil {
return nil, 0, errors.Wrapf(err, "CertificateList")
}
@@ -205,8 +181,8 @@ func (r *SRegion) GetSSLCertificates(size, offset int) ([]SSSLCertificate, int,
return ret, int(totalCount), nil
}
func (r *SRegion) GetCertificate(certId string) (*SSSLCertificate, error) {
resp, err := r.client.sslcertExport(r.ID, "scm/certificates", certId)
func (r *SHuaweiClient) GetSSLCertificate(certId string) (*SSSLCertificate, error) {
resp, err := r.sslcertExport(HUAWEI_CERT_DEFAULT_REGION, "scm/certificates", certId)
if err != nil {
return nil, errors.Wrap(err, "DescribeCertificateDetail")
}
@@ -216,7 +192,6 @@ func (r *SRegion) GetCertificate(certId string) (*SSSLCertificate, error) {
if err != nil {
return nil, errors.Wrap(err, "Unmarshal")
}
cert.region = r
cert.client = r
return cert, nil
}
+120 -136
View File
@@ -53,7 +53,7 @@ type projectInfo struct {
type SCertificate struct {
multicloud.SResourceBase
QcloudTags
region *SRegion
client *SQcloudClient
CertificateID string `json:"CertificateId"`
CertificateType string `json:"CertificateType"`
@@ -88,7 +88,11 @@ type SCertificate struct {
func (self *SCertificate) GetDetails() (*SCertificate, error) {
if !self.detailsInitd {
cert, err := self.region.GetCertificate(self.GetId())
var (
cert *SCertificate
err error
)
cert, err = self.client.GetCertificate(self.GetId())
if err != nil {
return nil, err
}
@@ -127,7 +131,7 @@ func (self *SCertificate) Sync(name, privateKey, publickKey string) error {
}
func (self *SCertificate) Delete() error {
return self.region.DeleteCertificate(self.GetId())
return self.client.DeleteCertificate(self.GetId())
}
func (self *SCertificate) GetId() string {
@@ -155,7 +159,7 @@ func (self *SCertificate) GetStatus() string {
}
func (self *SCertificate) Refresh() error {
cert, err := self.region.GetCertificate(self.GetId())
cert, err := self.client.GetCertificate(self.GetId())
if err != nil {
return errors.Wrap(err, "GetCertificate")
}
@@ -242,11 +246,113 @@ func (self *SCertificate) GetIsUpload() bool {
return false
}
// ssl.tencentcloudapi.com
/*
状态值 0审核中1已通过2审核失败3已过期4已添加 DNS 解析记录5OV/EV 证书待提交资料6订单取消中7已取消8已提交资料 待上传确认函
*/
func (self *SRegion) GetCertificates(projectId, certificateStatus, searchKey string) ([]SCertificate, error) {
// https://cloud.tencent.com/document/product/400/41674
func (self *SQcloudClient) GetCertificate(certId string) (*SCertificate, error) {
params := map[string]string{
"CertificateId": certId,
}
resp, err := self.sslRequest("DescribeCertificateDetail", params)
if err != nil {
return nil, errors.Wrap(err, "DescribeCertificateDetail")
}
cert := &SCertificate{client: self}
err = resp.Unmarshal(cert)
if err != nil {
return nil, errors.Wrap(err, "Unmarshal")
}
return cert, nil
}
// https://cloud.tencent.com/document/product/400/41665
// 返回证书ID
func (self *SQcloudClient) CreateCertificate(projectId, publicKey, privateKey, certType, desc string) (string, error) {
params := map[string]string{
"CertificatePublicKey": publicKey,
"CertificateType": certType,
"Alias": desc,
}
if len(privateKey) > 0 {
params["CertificatePrivateKey"] = privateKey
} else {
if certType == "SVR" {
return "", fmt.Errorf("certificate private key required while certificate type is SVR")
}
}
if len(projectId) > 0 {
params["ProjectId"] = projectId
}
resp, err := self.sslRequest("UploadCertificate", params)
if err != nil {
return "", err
}
return resp.GetString("CertificateId")
}
// https://cloud.tencent.com/document/product/400/41675
func (self *SQcloudClient) DeleteCertificate(id string) error {
if len(id) == 0 {
return fmt.Errorf("DelteCertificate certificate id should not be empty")
}
params := map[string]string{"CertificateId": id}
resp, err := self.sslRequest("DeleteCertificate", params)
if err != nil {
return errors.Wrap(err, "DeleteCertificate")
}
if deleted, _ := resp.Bool("DeleteResult"); deleted {
return nil
}
return fmt.Errorf("DeleteCertificate %s", resp)
}
func (self *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) {
certs, err := self.client.GetCertificates("", "", "")
if err != nil {
return nil, errors.Wrap(err, "GetCertificates")
}
icerts := make([]cloudprovider.ICloudLoadbalancerCertificate, len(certs))
for i := range certs {
icerts[i] = &certs[i]
}
return icerts, nil
}
func (self *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) {
cert, err := self.client.GetCertificate(certId)
if err != nil {
return nil, errors.Wrap(err, "GetCertificate")
}
return cert, nil
}
// todo:目前onecloud端只能指定服务器端证书。需要兼容客户端证书?
// todo:支持指定Project。
// todo: 已过期的证书不能上传也不能关联资源
func (self *SRegion) CreateILoadBalancerCertificate(input *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) {
certId, err := self.client.CreateCertificate("", input.Certificate, input.PrivateKey, "SVR", input.Name)
if err != nil {
return nil, err
}
cert, err := self.client.GetCertificate(certId)
if err != nil {
return nil, errors.Wrapf(err, "GetCertificate")
}
return cert, nil
}
func (self *SQcloudClient) GetCertificates(projectId, certificateStatus, searchKey string) ([]SCertificate, error) {
params := map[string]string{}
params["Limit"] = "100"
if len(projectId) > 0 {
@@ -282,135 +388,13 @@ func (self *SRegion) GetCertificates(projectId, certificateStatus, searchKey str
return nil, errors.Wrap(err, "Unmarshal.TotalCount")
}
certs = append(certs, _certs...)
offset += 100
}
for i := range _certs {
_certs[i].client = self
certs = append(certs, _certs[i])
}
for i := range certs {
certs[i].region = self
offset += 100
}
return certs, nil
}
// https://cloud.tencent.com/document/product/400/41674
func (self *SRegion) GetCertificate(certId string) (*SCertificate, error) {
params := map[string]string{
"CertificateId": certId,
}
resp, err := self.sslRequest("DescribeCertificateDetail", params)
if err != nil {
return nil, errors.Wrap(err, "DescribeCertificateDetail")
}
cert := &SCertificate{}
err = resp.Unmarshal(cert)
if err != nil {
return nil, errors.Wrap(err, "Unmarshal")
}
cert.region = self
return cert, nil
}
// https://cloud.tencent.com/document/product/400/41665
// 返回证书ID
func (self *SRegion) CreateCertificate(projectId, publicKey, privateKey, certType, desc string) (string, error) {
params := map[string]string{
"CertificatePublicKey": publicKey,
"CertificateType": certType,
"Alias": desc,
}
if len(privateKey) > 0 {
params["CertificatePrivateKey"] = privateKey
} else {
if certType == "SVR" {
return "", fmt.Errorf("certificate private key required while certificate type is SVR")
}
}
if len(projectId) > 0 {
params["ProjectId"] = projectId
}
resp, err := self.sslRequest("UploadCertificate", params)
if err != nil {
return "", err
}
return resp.GetString("CertificateId")
}
// https://cloud.tencent.com/document/product/400/41675
func (self *SRegion) DeleteCertificate(id string) error {
if len(id) == 0 {
return fmt.Errorf("DelteCertificate certificate id should not be empty")
}
params := map[string]string{"CertificateId": id}
resp, err := self.sslRequest("DeleteCertificate", params)
if err != nil {
return errors.Wrap(err, "DeleteCertificate")
}
if deleted, _ := resp.Bool("DeleteResult"); deleted {
return nil
} else {
return fmt.Errorf("DeleteCertificate %s", resp)
}
}
func (self *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) {
certs, err := self.GetCertificates("", "", "")
if err != nil {
return nil, errors.Wrap(err, "GetCertificates")
}
icerts := make([]cloudprovider.ICloudLoadbalancerCertificate, len(certs))
for i := range certs {
icerts[i] = &certs[i]
}
return icerts, nil
}
func (self *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) {
cert, err := self.GetCertificate(certId)
if err != nil {
return nil, errors.Wrap(err, "GetCertificate")
}
return cert, nil
}
// todo:目前onecloud端只能指定服务器端证书。需要兼容客户端证书?
// todo:支持指定Project。
// todo: 已过期的证书不能上传也不能关联资源
func (self *SRegion) CreateILoadBalancerCertificate(input *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) {
certId, err := self.CreateCertificate("", input.Certificate, input.PrivateKey, "SVR", input.Name)
if err != nil {
return nil, err
}
cert, err := self.GetCertificate(certId)
if err != nil {
return nil, errors.Wrapf(err, "GetCertificate")
}
return cert, nil
}
// GetISSLCertificates 获取证书资源列表
func (self *SRegion) GetISSLCertificates() ([]cloudprovider.ICloudSSLCertificate, error) {
rs, err := self.GetCertificates("", "", "")
if err != nil {
return nil, err
}
result := make([]cloudprovider.ICloudSSLCertificate, 0)
for i := range rs {
result = append(result, &rs[i])
}
return result, nil
}
@@ -466,3 +466,7 @@ func (self *SQcloudProvider) CreateICloudCDNDomain(opts *cloudprovider.CdnCreate
func (self *SQcloudProvider) GetMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) {
return self.client.GetMetrics(opts)
}
func (self *SQcloudProvider) GetISSLCertificates() ([]cloudprovider.ICloudSSLCertificate, error) {
return self.client.GetISSLCertificates()
}
+14
View File
@@ -982,6 +982,20 @@ func (client *SQcloudClient) GetIProjects() ([]cloudprovider.ICloudProject, erro
return iprojects, nil
}
func (self *SQcloudClient) GetISSLCertificates() ([]cloudprovider.ICloudSSLCertificate, error) {
rs, err := self.GetCertificates("", "", "")
if err != nil {
return nil, err
}
result := make([]cloudprovider.ICloudSSLCertificate, 0)
for i := range rs {
rs[i].client = self
result = append(result, &rs[i])
}
return result, nil
}
func (self *SQcloudClient) GetCapabilities() []string {
caps := []string{
cloudprovider.CLOUD_CAPABILITY_PROJECT,
-4
View File
@@ -512,10 +512,6 @@ func (self *SRegion) sqlserverRequest(apiName string, params map[string]string)
return self.client.sqlserverRequest(apiName, params)
}
func (self *SRegion) sslRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
return self.client.sslRequest(apiName, params)
}
func (self *SRegion) kafkaRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
params["Region"] = self.Region
return self.client.kafkaRequest(apiName, params)