| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200 |
- // 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 qcloud
- import (
- "bytes"
- "context"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "strconv"
- "strings"
- "time"
- "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
- sdkerrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
- tchttp "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/http"
- "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
- "github.com/tencentyun/cos-go-sdk-v5"
- "github.com/tencentyun/cos-go-sdk-v5/debug"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/httputils"
- "yunion.io/x/pkg/util/timeutils"
- "yunion.io/x/pkg/utils"
- api "yunion.io/x/cloudmux/pkg/apis/compute"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- )
- const (
- CLOUD_PROVIDER_QCLOUD = api.CLOUD_PROVIDER_QCLOUD
- CLOUD_PROVIDER_QCLOUD_CN = "腾讯云"
- CLOUD_PROVIDER_QCLOUD_EN = "QCloud"
- QCLOUD_DEFAULT_REGION = "ap-beijing"
- QCLOUD_API_VERSION = "2017-03-12"
- QCLOUD_CLB_API_VERSION = "2018-03-17"
- QCLOUD_BILLING_API_VERSION = "2018-07-09"
- QCLOUD_AUDIT_API_VERSION = "2019-03-19"
- QCLOUD_CAM_API_VERSION = "2019-01-16"
- QCLOUD_CDB_API_VERSION = "2017-03-20"
- QCLOUD_MARIADB_API_VERSION = "2017-03-12"
- QCLOUD_POSTGRES_API_VERSION = "2017-03-12"
- QCLOUD_SQLSERVER_API_VERSION = "2018-03-28"
- QCLOUD_REDIS_API_VERSION = "2018-04-12"
- QCLOUD_MEMCACHED_API_VERSION = "2019-03-18"
- QCLOUD_SSL_API_VERSION = "2019-12-05"
- QCLOUD_CDN_API_VERSION = "2018-06-06"
- QCLOUD_MONGODB_API_VERSION = "2019-07-25"
- QCLOUD_ES_API_VERSION = "2018-04-16"
- QCLOUD_DCDB_API_VERSION = "2018-04-11"
- QCLOUD_KAFKA_API_VERSION = "2019-08-19"
- QCLOUD_TKE_API_VERSION = "2018-05-25"
- QCLOUD_DNS_API_VERSION = "2021-03-23"
- QCLOUD_STS_API_VERSION = "2018-08-13"
- QCLOUD_TAG_API_VERSION = "2018-08-13"
- QCLOUD_WAF_API_VERSION = "2018-01-25"
- QCLOUD_ORG_API_VERSION = "2021-03-31"
- )
- type QcloudClientConfig struct {
- cpcfg cloudprovider.ProviderConfig
- secretId string
- secretKey string
- accountId string
- appId string
- debug bool
- }
- func NewQcloudClientConfig(secretId, secretKey string) *QcloudClientConfig {
- cfg := &QcloudClientConfig{
- secretId: secretId,
- secretKey: secretKey,
- }
- return cfg
- }
- func (cfg *QcloudClientConfig) CloudproviderConfig(cpcfg cloudprovider.ProviderConfig) *QcloudClientConfig {
- cfg.cpcfg = cpcfg
- return cfg
- }
- func (cfg *QcloudClientConfig) AccountId(accountId string) *QcloudClientConfig {
- cfg.accountId = accountId
- return cfg
- }
- func (cfg *QcloudClientConfig) Debug(debug bool) *QcloudClientConfig {
- cfg.debug = debug
- return cfg
- }
- type SQcloudClient struct {
- *QcloudClientConfig
- masterAccountId string
- masterAppId string
- ownerId string
- ownerName string
- appId string
- iregions []cloudprovider.ICloudRegion
- ibuckets []cloudprovider.ICloudBucket
- }
- func NewQcloudClient(cfg *QcloudClientConfig) (*SQcloudClient, error) {
- client := SQcloudClient{
- QcloudClientConfig: cfg,
- }
- caller, err := client.GetCallerIdentity()
- if err != nil {
- return nil, errors.Wrapf(err, "GetCallerIdentity")
- }
- client.masterAppId, err = client.GetAppId()
- if err != nil {
- return nil, errors.Wrapf(err, "GetAppId")
- }
- client.masterAccountId = caller.AccountId
- err = client.fetchRegions()
- if err != nil {
- return nil, errors.Wrap(err, "fetchRegions")
- }
- return &client, nil
- }
- // 默认接口请求频率限制:20次/秒
- // 部分接口支持金融区地域。由于金融区和非金融区是隔离不互通的,因此当公共参数 Region 为金融区地域(例如 ap-shanghai-fsi)时,需要同时指定带金融区地域的域名,最好和 Region 的地域保持一致,例如:clb.ap-shanghai-fsi.tencentcloudapi.com
- // https://cloud.tencent.com/document/product/416/6479
- func apiDomain(product string, params map[string]string) string {
- regionId, _ := params["Region"]
- return apiDomainByRegion(product, regionId)
- }
- func apiDomainByRegion(product, regionId string) string {
- if strings.HasSuffix(regionId, "-fsi") {
- return product + "." + regionId + ".tencentcloudapi.com"
- } else {
- return product + ".tencentcloudapi.com"
- }
- }
- func jsonRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool, retry bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("cvm", params)
- return _jsonRequest(client, domain, QCLOUD_API_VERSION, apiName, params, updateFunc, debug, retry)
- }
- func tkeRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := "tke.tencentcloudapi.com"
- return _jsonRequest(client, domain, QCLOUD_TKE_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- func vpcRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("vpc", params)
- return _jsonRequest(client, domain, QCLOUD_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- func orgRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := "organization.tencentcloudapi.com"
- return _jsonRequest(client, domain, QCLOUD_ORG_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- func auditRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("cloudaudit", params)
- return _jsonRequest(client, domain, QCLOUD_AUDIT_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- func cbsRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("cbs", params)
- return _jsonRequest(client, domain, QCLOUD_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // es
- func esRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("es", params)
- return _jsonRequest(client, domain, QCLOUD_ES_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // waf
- func wafRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("waf", params)
- return _jsonRequest(client, domain, QCLOUD_WAF_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // kafka
- func kafkaRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("ckafka", params)
- return _jsonRequest(client, domain, QCLOUD_KAFKA_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // redis
- func redisRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("redis", params)
- return _jsonRequest(client, domain, QCLOUD_REDIS_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // tdsql
- func dcdbRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("dcdb", params)
- return _jsonRequest(client, domain, QCLOUD_DCDB_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // mongodb
- func mongodbRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("mongodb", params)
- return _jsonRequest(client, domain, QCLOUD_MONGODB_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // memcached
- func memcachedRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("memcached", params)
- return _jsonRequest(client, domain, QCLOUD_MEMCACHED_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // loadbalancer服务 api 3.0
- func clbRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("clb", params)
- return _jsonRequest(client, domain, QCLOUD_CLB_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // cdb
- func cdbRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("cdb", params)
- return _jsonRequest(client, domain, QCLOUD_CDB_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // mariadb
- func mariadbRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("mariadb", params)
- return _jsonRequest(client, domain, QCLOUD_MARIADB_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // postgres
- func postgresRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("postgres", params)
- return _jsonRequest(client, domain, QCLOUD_POSTGRES_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // sqlserver
- func sqlserverRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := apiDomain("sqlserver", params)
- return _jsonRequest(client, domain, QCLOUD_SQLSERVER_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // ssl 证书服务
- func sslRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := "ssl.tencentcloudapi.com"
- return _jsonRequest(client, domain, QCLOUD_SSL_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- // dnspod 解析服务
- func dnsRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := "dnspod.tencentcloudapi.com"
- return _jsonRequest(client, domain, QCLOUD_DNS_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- func billingRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := "billing.tencentcloudapi.com"
- return _jsonRequest(client, domain, QCLOUD_BILLING_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- func camRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := "cam.tencentcloudapi.com"
- return _jsonRequest(client, domain, QCLOUD_CAM_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- func monitorRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string),
- debug bool) (jsonutils.JSONObject, error) {
- domain := "monitor.tencentcloudapi.com"
- return _jsonRequest(client, domain, QCLOUD_API_VERSION_METRICS, apiName, params, updateFunc, debug, true)
- }
- func cdnRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string),
- debug bool) (jsonutils.JSONObject, error) {
- domain := "cdn.tencentcloudapi.com"
- return _jsonRequest(client, domain, QCLOUD_CDN_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- func stsRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string),
- debug bool) (jsonutils.JSONObject, error) {
- domain := "sts.tencentcloudapi.com"
- return _jsonRequest(client, domain, QCLOUD_STS_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- type qcloudResponse interface {
- tchttp.Response
- GetResponse() *interface{}
- }
- // 3.0版本通用response
- type QcloudResponse struct {
- *tchttp.BaseResponse
- Response *interface{} `json:"Response"`
- }
- func (r *QcloudResponse) GetResponse() *interface{} {
- return r.Response
- }
- func _jsonRequest(client *common.Client, domain string, version string, apiName string, params map[string]string, updateFun func(string, string), debug bool, retry bool) (jsonutils.JSONObject, error) {
- req := &tchttp.BaseRequest{}
- _profile := profile.NewClientProfile()
- _profile.SignMethod = common.SHA256
- client.WithProfile(_profile)
- service := strings.Split(domain, ".")[0]
- req.Init().WithApiInfo(service, version, apiName)
- req.SetDomain(domain)
- for k, v := range params {
- if strings.HasSuffix(k, "Ids.0") && len(v) == 0 {
- return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s = %s", k, v)
- }
- req.GetParams()[k] = v
- }
- resp := &QcloudResponse{
- BaseResponse: &tchttp.BaseResponse{},
- }
- ret, err := _baseJsonRequest(client, req, resp, apiName, debug, retry)
- if err != nil {
- if errors.Cause(err) == cloudprovider.ErrNoPermission && updateFun != nil {
- updateFun(service, apiName)
- }
- return nil, err
- }
- return ret, nil
- }
- func _baseJsonRequest(client *common.Client, req tchttp.Request, resp qcloudResponse, apiName string, debug bool, retry bool) (jsonutils.JSONObject, error) {
- tryMax := 1
- if retry {
- tryMax = 3
- }
- var err error
- for i := 1; i <= tryMax; i++ {
- err = client.Send(req, resp)
- if err == nil {
- break
- }
- needRetry := false
- e, ok := err.(*sdkerrors.TencentCloudSDKError)
- if ok {
- if strings.HasPrefix(e.Code, "UnauthorizedOperation.") ||
- strings.HasPrefix(e.Code, "AuthFailure.") ||
- utils.IsInStringArray(e.Code, []string{
- "SecretidNotAuthAccessResource",
- "UnauthorizedOperation",
- "InvalidParameter.PermissionDenied",
- "AuthFailure",
- }) {
- return nil, errors.Wrapf(cloudprovider.ErrNoPermission, "%s", err.Error())
- }
- if utils.IsInStringArray(e.Code, []string{
- "AuthFailure.SecretIdNotFound",
- "AuthFailure.SignatureFailure",
- }) {
- return nil, errors.Wrapf(cloudprovider.ErrInvalidAccessKey, "%s", err.Error())
- }
- if utils.IsInStringArray(e.Code, []string{
- "InvalidParameter.RoleNotExist",
- "ResourceNotFound",
- "FailedOperation.CertificateNotFound",
- "ResourceNotFound.OrganizationNotExist",
- }) {
- return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", err.Error())
- }
- if utils.IsInStringArray(e.Code, []string{
- "InvalidParameterValue.ZoneNotSupported",
- "UnsupportedRegion",
- }) {
- return nil, cloudprovider.ErrNotSupported
- }
- if e.Code == "InvalidParameterValue" && apiName == "GetMonitorData" && strings.Contains(e.Message, "the instance has been destroyed") {
- return nil, cloudprovider.ErrNotFound
- }
- if utils.IsInStringArray(e.Code, []string{
- "InternalError",
- "MutexOperation.TaskRunning", // Code=DesOperation.MutexTaskRunning, Message=Mutex task is running, please try later
- "InvalidInstance.NotSupported", // Code=InvalidInstance.NotSupported, Message=The request does not support the instances `ins-bg54517v` which are in operation or in a special state., 重装系统后立即关机有可能会引发 Code=InvalidInstance.NotSupported 错误, 重试可以避免任务失败
- "InvalidAddressId.StatusNotPermit", // Code=InvalidAddressId.StatusNotPermit, Message=The status `"UNBINDING"` for AddressId `"eip-m3kix9kx"` is not permit to do this operation., EIP删除需要重试
- "RequestLimitExceeded",
- "OperationDenied.InstanceOperationInProgress", // 调整配置后开机 Code=OperationDenied.InstanceOperationInProgress, Message=实例`['ins-nksicizg']`操作进行中,请等待, RequestId=c9951005-b22c-43c1-84aa-d923d49addcf
- }) {
- needRetry = true
- }
- }
- if !needRetry {
- for _, msg := range []string{
- "EOF",
- "TLS handshake timeout",
- "try later",
- "i/o timeout",
- } {
- if strings.Contains(err.Error(), msg) {
- needRetry = true
- break
- }
- }
- }
- if needRetry {
- log.Errorf("request url %s\nparams: %s\nerror: %v\ntry after %d seconds", req.GetDomain(), jsonutils.Marshal(req.GetParams()).PrettyString(), err, i*10)
- time.Sleep(time.Second * time.Duration(i*10))
- continue
- }
- log.Errorf("request url: %s\nparams: %s\nresponse: %v\nerror: %v", req.GetDomain(), jsonutils.Marshal(req.GetParams()).PrettyString(), resp.GetResponse(), err)
- return nil, err
- }
- if debug {
- log.Debugf("request: %s", req.GetParams())
- response := resp.GetResponse()
- if response != nil {
- log.Debugf("response: %s", jsonutils.Marshal(response).PrettyString())
- }
- }
- if err != nil {
- return nil, err
- }
- return jsonutils.Marshal(resp.GetResponse()), nil
- }
- func (client *SQcloudClient) GetRegions() []SRegion {
- regions := make([]SRegion, len(client.iregions))
- for i := 0; i < len(regions); i++ {
- region := client.iregions[i].(*SRegion)
- regions[i] = *region
- }
- return regions
- }
- func (client *SQcloudClient) getDefaultClient(params map[string]string) (*common.Client, error) {
- regionId := QCLOUD_DEFAULT_REGION
- if len(params) > 0 {
- if region, ok := params["Region"]; ok {
- regionId = region
- }
- }
- return client.getSdkClient(regionId)
- }
- func (client *SQcloudClient) isSubAccount() bool {
- return len(client.accountId) > 0 &&
- client.accountId != client.masterAccountId && len(client.masterAccountId) > 0 &&
- client.accountId != client.masterAppId && len(client.masterAppId) > 0
- }
- func (client *SQcloudClient) getSdkClient(regionId string) (*common.Client, error) {
- cli, err := common.NewClientWithSecretId(client.secretId, client.secretKey, regionId)
- if err != nil {
- return nil, err
- }
- if client.isSubAccount() {
- arn := fmt.Sprintf("qcs::cam::uin/%s:roleName/%s", client.accountId, "OrganizationAccessControlRole")
- sts := common.DefaultRoleArnProvider(client.secretId, client.secretKey, arn)
- cli, err = cli.WithProvider(sts)
- if err != nil {
- return nil, errors.Wrapf(err, "WithProvider")
- }
- }
- httpClient := client.cpcfg.AdaptiveTimeoutHttpClient()
- ts, _ := httpClient.Transport.(*http.Transport)
- cli.WithHttpTransport(cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response) error, error) {
- body, err := io.ReadAll(req.Body)
- if err != nil {
- return nil, errors.Wrapf(err, "ioutil.ReadAll")
- }
- req.Body = io.NopCloser(bytes.NewBuffer(body))
- params, err := url.ParseQuery(string(body))
- if err != nil {
- return nil, errors.Wrapf(err, "ParseQuery(%s)", string(body))
- }
- service := strings.Split(req.URL.Host, ".")[0]
- action := params.Get("Action")
- respCheck := func(resp *http.Response) error {
- if resp.ContentLength <= 0 {
- return nil
- }
- body, err := io.ReadAll(resp.Body)
- if err != nil {
- return errors.Wrapf(err, "ioutil.ReadAll")
- }
- resp.Body = io.NopCloser(bytes.NewBuffer(body))
- obj, _ := jsonutils.Parse(body)
- code := ""
- if obj != nil {
- code, _ = obj.GetString("Response", "Error", "Code")
- }
- if client.cpcfg.UpdatePermission != nil && code == "UnauthorizedOperation" {
- client.cpcfg.UpdatePermission(service, action)
- }
- return nil
- }
- if client.cpcfg.ReadOnly {
- for _, prefix := range []string{"Get", "List", "Describe", "LookUpEvents"} {
- if strings.HasPrefix(action, prefix) {
- return respCheck, nil
- }
- }
- return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s", action)
- }
- return respCheck, nil
- }))
- return cli, nil
- }
- func (client *SQcloudClient) tkeRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return tkeRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) vpcRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return vpcRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) orgRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return orgRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) auditRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return auditRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) cbsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return cbsRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) tagRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return tagRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func tagRequest(client *common.Client, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) {
- domain := "tag.tencentcloudapi.com"
- return _jsonRequest(client, domain, QCLOUD_TAG_API_VERSION, apiName, params, updateFunc, debug, true)
- }
- func (client *SQcloudClient) clbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return clbRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) cdbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return cdbRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) esRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return esRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) wafRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return wafRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) kafkaRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return kafkaRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) redisRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return redisRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) dcdbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return dcdbRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) mongodbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return mongodbRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) memcachedRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return memcachedRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) mariadbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return mariadbRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) postgresRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return postgresRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) sqlserverRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return sqlserverRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) sslRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return sslRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) dnsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return dnsRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) billingRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return billingRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) camRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return camRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) cdnRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return cdnRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) stsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return stsRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug)
- }
- func (client *SQcloudClient) jsonRequest(apiName string, params map[string]string, retry bool) (jsonutils.JSONObject, error) {
- cli, err := client.getDefaultClient(params)
- if err != nil {
- return nil, err
- }
- return jsonRequest(cli, apiName, params, client.cpcfg.UpdatePermission, client.debug, retry)
- }
- func (client *SQcloudClient) fetchRegions() error {
- body, err := client.jsonRequest("DescribeRegions", nil, true)
- if err != nil {
- log.Errorf("fetchRegions fail %s", err)
- return err
- }
- regions := make([]SRegion, 0)
- err = body.Unmarshal(®ions, "RegionSet")
- if err != nil {
- log.Errorf("unmarshal json error %s", err)
- return err
- }
- client.iregions = make([]cloudprovider.ICloudRegion, len(regions))
- for i := 0; i < len(regions); i++ {
- regions[i].client = client
- client.iregions[i] = ®ions[i]
- }
- return nil
- }
- func (client *SQcloudClient) getCosClient(bucket *SBucket) (*cos.Client, error) {
- var baseUrl *cos.BaseURL
- if bucket != nil {
- u, _ := url.Parse(bucket.getBucketUrl())
- baseUrl = &cos.BaseURL{
- BucketURL: u,
- }
- }
- ts := &http.Transport{
- Proxy: client.cpcfg.ProxyFunc,
- }
- cosClient := cos.NewClient(
- baseUrl,
- &http.Client{
- Transport: &cos.AuthorizationTransport{
- SecretID: client.secretId,
- SecretKey: client.secretKey,
- Transport: &debug.DebugRequestTransport{
- RequestHeader: client.debug,
- RequestBody: client.debug,
- ResponseHeader: client.debug,
- ResponseBody: client.debug,
- Transport: cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response) error, error) {
- method, path := req.Method, req.URL.Path
- respCheck := func(resp *http.Response) error {
- if resp.StatusCode == 403 {
- if client.cpcfg.UpdatePermission != nil {
- client.cpcfg.UpdatePermission("cos", fmt.Sprintf("%s %s", method, path))
- }
- }
- return nil
- }
- if client.cpcfg.ReadOnly {
- if req.Method == "GET" || req.Method == "HEAD" {
- return respCheck, nil
- }
- return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path)
- }
- return respCheck, nil
- }),
- },
- },
- },
- )
- return cosClient, nil
- }
- func (self *SQcloudClient) invalidateIBuckets() {
- self.ibuckets = nil
- }
- func (self *SQcloudClient) getIBuckets() ([]cloudprovider.ICloudBucket, error) {
- if self.isSubAccount() {
- return nil, fmt.Errorf("cos not support sub account sync")
- }
- if self.ibuckets == nil {
- err := self.fetchBuckets()
- if err != nil {
- return nil, errors.Wrap(err, "fetchBuckets")
- }
- }
- return self.ibuckets, nil
- }
- func (client *SQcloudClient) verifyAppId() error {
- region, err := client.getDefaultRegion()
- if err != nil {
- return errors.Wrap(err, "getDefaultRegion")
- }
- bucket := SBucket{
- region: region,
- Name: "yuniondocument",
- }
- cli, err := client.getCosClient(&bucket)
- if err != nil {
- return errors.Wrap(err, "getCosClient")
- }
- resp, err := cli.Bucket.Head(context.Background())
- if resp != nil {
- defer httputils.CloseResponse(resp.Response)
- if resp.StatusCode < 400 || resp.StatusCode == 404 {
- return nil
- }
- return errors.Error(fmt.Sprintf("invalid AppId: %d", resp.StatusCode))
- }
- return errors.Wrap(err, "Head")
- }
- func (client *SQcloudClient) getOwnerName() string {
- if len(client.ownerName) > 0 {
- return client.ownerName
- }
- coscli, err := client.getCosClient(nil)
- if err != nil {
- return ""
- }
- s, _, err := coscli.Service.Get(context.Background())
- if err != nil {
- return ""
- }
- client.ownerId = s.Owner.ID
- client.ownerName = s.Owner.DisplayName
- return client.ownerName
- }
- func (client *SQcloudClient) fetchBuckets() error {
- coscli, err := client.getCosClient(nil)
- if err != nil {
- return errors.Wrap(err, "GetCosClient")
- }
- s, _, err := coscli.Service.Get(context.Background())
- if err != nil {
- return errors.Wrap(err, "coscli.Service.Get")
- }
- client.ownerId = s.Owner.ID
- client.ownerName = s.Owner.DisplayName
- ret := make([]cloudprovider.ICloudBucket, 0)
- for i := range s.Buckets {
- bInfo := s.Buckets[i]
- createAt, _ := timeutils.ParseTimeStr(bInfo.CreationDate)
- slashPos := strings.LastIndexByte(bInfo.Name, '-')
- appId := bInfo.Name[slashPos+1:]
- _appId, _ := client.GetAppId()
- if appId != _appId {
- log.Errorf("[%s %s] Inconsistent appId: %s expect %s", bInfo.Name, bInfo.Region, appId, _appId)
- }
- name := bInfo.Name[:slashPos]
- region, err := client.getIRegionByRegionId(bInfo.Region)
- var zone *SZone = nil
- if err != nil {
- log.Errorf("fail to find region %s", bInfo.Region)
- // possibly a zone, try zone
- regionStr := func() string {
- info := strings.Split(bInfo.Region, "-")
- if num, _ := strconv.Atoi(info[len(info)-1]); num > 0 {
- return strings.TrimSuffix(bInfo.Region, fmt.Sprintf("-%d", num))
- }
- return bInfo.Region
- }()
- region, err = client.getIRegionByRegionId(regionStr)
- if err != nil {
- log.Errorf("fail to find region %s", regionStr)
- continue
- }
- zoneId := bInfo.Region
- zone, err = region.(*SRegion).getZoneById(bInfo.Region)
- if err != nil {
- log.Errorf("fail to find zone %s", zoneId)
- continue
- }
- zoneId = zone.GetId()
- log.Debugf("find zonal bucket %s", zoneId)
- }
- b := SBucket{
- region: region.(*SRegion),
- appId: appId,
- Name: name,
- Location: bInfo.Region,
- CreateDate: createAt,
- }
- if zone != nil {
- b.zone = zone
- }
- ret = append(ret, &b)
- }
- client.ibuckets = ret
- return nil
- }
- func (client *SQcloudClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
- nodes, err := client.DescribeOrganizationMembers()
- if err != nil && errors.Cause(err) != cloudprovider.ErrNotFound && errors.Cause(err) != cloudprovider.ErrNoPermission {
- return nil, err
- }
- subAccount := cloudprovider.SSubAccount{}
- subAccount.Id = client.GetAccountId()
- subAccount.Name = client.cpcfg.Name
- subAccount.Account = client.secretId
- if len(client.appId) > 0 { // 兼容旧版本账号,避免订阅删除
- subAccount.Account = fmt.Sprintf("%s/%s", client.secretId, client.appId)
- }
- subAccount.HealthStatus = api.CLOUD_PROVIDER_HEALTH_NORMAL
- subAccount.DefaultProjectId = "0"
- ret := []cloudprovider.SSubAccount{subAccount}
- for _, node := range nodes {
- uin := fmt.Sprintf("%d", node.MemberUin)
- if len(subAccount.Id) > 0 && uin != subAccount.Id {
- account := cloudprovider.SSubAccount{}
- account.Id = uin
- account.Name = node.Name
- account.Account = fmt.Sprintf("%s/%s", client.secretId, uin)
- account.HealthStatus = api.CLOUD_PROVIDER_HEALTH_NORMAL
- account.DefaultProjectId = "0"
- ret = append(ret, account)
- }
- }
- return ret, nil
- }
- func (self *SQcloudClient) GetAccountId() string {
- if len(self.ownerId) == 0 {
- caller, err := self.GetCallerIdentity()
- if err == nil {
- self.ownerId = caller.AccountId
- }
- }
- return self.ownerId
- }
- func (client *SQcloudClient) GetIamLoginUrl() string {
- return fmt.Sprintf("https://cloud.tencent.com/login/subAccount")
- }
- func (client *SQcloudClient) GetIRegions() ([]cloudprovider.ICloudRegion, error) {
- return client.iregions, nil
- }
- func (client *SQcloudClient) getDefaultRegion() (*SRegion, error) {
- iregion, err := client.getIRegionByRegionId(QCLOUD_DEFAULT_REGION)
- if err != nil {
- return nil, errors.Wrap(err, "getIRegionByRegionId")
- }
- return iregion.(*SRegion), nil
- }
- func (client *SQcloudClient) getIRegionByRegionId(id string) (cloudprovider.ICloudRegion, error) {
- for i := 0; i < len(client.iregions); i++ {
- if client.iregions[i].GetId() == id {
- return client.iregions[i], nil
- }
- }
- return nil, cloudprovider.ErrNotFound
- }
- func (client *SQcloudClient) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) {
- for i := 0; i < len(client.iregions); i++ {
- if client.iregions[i].GetGlobalId() == id {
- return client.iregions[i], nil
- }
- }
- return nil, cloudprovider.ErrNotFound
- }
- func (client *SQcloudClient) GetRegion(regionId string) *SRegion {
- for i := 0; i < len(client.iregions); i++ {
- if client.iregions[i].GetId() == regionId {
- return client.iregions[i].(*SRegion)
- }
- }
- return nil
- }
- func (client *SQcloudClient) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
- for i := 0; i < len(client.iregions); i++ {
- ihost, err := client.iregions[i].GetIHostById(id)
- if err == nil {
- return ihost, nil
- } else if errors.Cause(err) != cloudprovider.ErrNotFound {
- return nil, err
- }
- }
- return nil, cloudprovider.ErrNotFound
- }
- func (client *SQcloudClient) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
- for i := 0; i < len(client.iregions); i++ {
- ihost, err := client.iregions[i].GetIVpcById(id)
- if err == nil {
- return ihost, nil
- } else if errors.Cause(err) != cloudprovider.ErrNotFound {
- return nil, err
- }
- }
- return nil, cloudprovider.ErrNotFound
- }
- func (client *SQcloudClient) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
- for i := 0; i < len(client.iregions); i++ {
- ihost, err := client.iregions[i].GetIStorageById(id)
- if err == nil {
- return ihost, nil
- } else if errors.Cause(err) != cloudprovider.ErrNotFound {
- return nil, err
- }
- }
- return nil, cloudprovider.ErrNotFound
- }
- type SAccountBalance struct {
- Balance float64
- Uin int64
- Currency string
- CashAccountBalance float64
- CreditAmount float64
- CreditBalance float64
- FreezeAmount float64
- }
- func (client *SQcloudClient) QueryAccountBalance() (*SAccountBalance, error) {
- body, err := client.billingRequest("DescribeAccountBalance", nil)
- if err != nil {
- if isError(err, []string{"UnauthorizedOperation.NotFinanceAuth"}) {
- return nil, cloudprovider.ErrNoBalancePermission
- }
- return nil, errors.Wrapf(err, "DescribeAccountBalance")
- }
- balance := &SAccountBalance{Currency: "CNY"}
- err = body.Unmarshal(balance)
- if err != nil {
- return nil, err
- }
- amount := balance.Balance / 100.0
- if balance.CreditAmount > 0 {
- amount = (balance.CashAccountBalance + balance.CreditAmount + balance.Balance - balance.FreezeAmount) / 100.0
- }
- balance.Balance = amount
- if balance.Uin >= 200000000000 {
- balance.Currency = "USD"
- }
- return balance, nil
- }
- type SBillSummary struct {
- Ready int `json:"Ready"`
- SummaryDetail []SBillSummaryItem `json:"SummaryDetail"`
- TotalAmount float64 `json:"TotalAmount"`
- }
- type SBillSummaryItem struct {
- Business []jsonutils.JSONObject `json:"Business"`
- CashPayAmount float64 `json:"CashPayAmount"`
- GroupKey string `json:"GroupKey"`
- GroupValue string `json:"GroupValue"`
- IncentivePayAmount float64 `json:"IncentivePayAmount"`
- RealTotalCost float64 `json:"RealTotalCost"`
- TotalCost float64 `json:"TotalCost"`
- TransferPayAmount float64 `json:"TransferPayAmount"`
- VoucherPayAmount float64 `json:"VoucherPayAmount"`
- }
- func (client *SQcloudClient) DescribeBillSummary(month string, uin string) (*SBillSummary, error) {
- params := make(map[string]string)
- params["Month"] = month
- params["GroupType"] = "business"
- if len(uin) > 0 {
- params["Uin"] = uin
- }
- body, err := client.billingRequest("DescribeBillSummary", params)
- if err != nil {
- return nil, errors.Wrapf(err, "DescribeBillSummary")
- }
- summary := SBillSummary{}
- err = body.Unmarshal(&summary)
- if err != nil {
- return nil, errors.Wrapf(err, "body.Unmarshal")
- }
- for _, item := range summary.SummaryDetail {
- summary.TotalAmount += item.RealTotalCost
- }
- return &summary, nil
- }
- func (client *SQcloudClient) GetIProjects() ([]cloudprovider.ICloudProject, error) {
- projects := []SProject{}
- for {
- part, total, err := client.GetProjects(len(projects), 1000)
- if err != nil {
- return nil, errors.Wrap(err, "GetProjects")
- }
- projects = append(projects, part...)
- if len(projects) >= total || len(part) == 0 {
- break
- }
- }
- projects = append(projects, SProject{ProjectId: "0", ProjectName: "默认项目"})
- iprojects := []cloudprovider.ICloudProject{}
- for i := 0; i < len(projects); i++ {
- projects[i].client = client
- iprojects = append(iprojects, &projects[i])
- }
- return iprojects, nil
- }
- func (client *SQcloudClient) GetAppId() (string, error) {
- if len(client.appId) > 0 {
- return client.appId, nil
- }
- resp, err := client.camRequest("GetUserAppId", map[string]string{})
- if err != nil {
- return "", errors.Wrapf(err, "GetUserAppId")
- }
- client.appId, err = resp.GetString("AppId")
- return client.appId, err
- }
- 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 (client *SQcloudClient) GetCapabilities() []string {
- caps := []string{
- cloudprovider.CLOUD_CAPABILITY_PROJECT,
- cloudprovider.CLOUD_CAPABILITY_COMPUTE,
- cloudprovider.CLOUD_CAPABILITY_NETWORK,
- cloudprovider.CLOUD_CAPABILITY_SECURITY_GROUP,
- cloudprovider.CLOUD_CAPABILITY_EIP,
- cloudprovider.CLOUD_CAPABILITY_LOADBALANCER,
- cloudprovider.CLOUD_CAPABILITY_RDS,
- cloudprovider.CLOUD_CAPABILITY_CACHE,
- cloudprovider.CLOUD_CAPABILITY_EVENT,
- cloudprovider.CLOUD_CAPABILITY_CLOUDID,
- cloudprovider.CLOUD_CAPABILITY_DNSZONE,
- cloudprovider.CLOUD_CAPABILITY_PUBLIC_IP,
- cloudprovider.CLOUD_CAPABILITY_SAML_AUTH,
- cloudprovider.CLOUD_CAPABILITY_QUOTA + cloudprovider.READ_ONLY_SUFFIX,
- cloudprovider.CLOUD_CAPABILITY_MONGO_DB + cloudprovider.READ_ONLY_SUFFIX,
- cloudprovider.CLOUD_CAPABILITY_ES + cloudprovider.READ_ONLY_SUFFIX,
- cloudprovider.CLOUD_CAPABILITY_KAFKA + cloudprovider.READ_ONLY_SUFFIX,
- cloudprovider.CLOUD_CAPABILITY_CDN + cloudprovider.READ_ONLY_SUFFIX,
- cloudprovider.CLOUD_CAPABILITY_CONTAINER + cloudprovider.READ_ONLY_SUFFIX,
- cloudprovider.CLOUD_CAPABILITY_CERT,
- cloudprovider.CLOUD_CAPABILITY_NAT + cloudprovider.READ_ONLY_SUFFIX,
- cloudprovider.CLOUD_CAPABILITY_SNAPSHOT_POLICY,
- cloudprovider.CLOUD_CAPABILITY_WAF + cloudprovider.READ_ONLY_SUFFIX,
- }
- // 官方cos sdk 未支持sts
- if !client.isSubAccount() {
- caps = append(caps, cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE)
- }
- return caps
- }
|