mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
fix: optimzed tag sync
This commit is contained in:
@@ -16,7 +16,6 @@ package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -291,22 +290,11 @@ func (model *SStandaloneAnonResourceBase) SetCloudMetadataAll(ctx context.Contex
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SetAll")
|
||||
}
|
||||
userTags, err := model.GetAllUserMetadata()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "model.GetAllUserMetadata()")
|
||||
userTags := map[string]interface{}{}
|
||||
for k, v := range dictstore {
|
||||
userTags[strings.Replace(k, CLOUD_TAG_PREFIX, USER_TAG_PREFIX, 1)] = v
|
||||
}
|
||||
cloudTags, err := model.GetAllCloudMetadata()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "model.GetAllCloudMetadata()")
|
||||
}
|
||||
if !reflect.DeepEqual(userTags, cloudTags) {
|
||||
cloudTags2 := make(map[string]interface{})
|
||||
for k, v := range cloudTags {
|
||||
cloudTags2[USER_TAG_PREFIX+k] = v
|
||||
}
|
||||
return model.SetUserMetadataAll(ctx, cloudTags2, userCred)
|
||||
}
|
||||
return nil
|
||||
return Metadata.SetAll(ctx, model, userTags, userCred, USER_TAG_PREFIX)
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) SetSysCloudMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
|
||||
@@ -1235,21 +1235,20 @@ func (self *SManagedVirtualizedGuestDriver) RequestRemoteUpdate(ctx context.Cont
|
||||
}
|
||||
tags, err := guest.GetAllUserMetadata()
|
||||
if err != nil {
|
||||
log.Errorf("GetAllUserMetadata fail %s", err)
|
||||
} else {
|
||||
tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags}
|
||||
err := iVM.SetTags(tags, replaceTags)
|
||||
if err != nil {
|
||||
logclient.AddSimpleActionLog(guest, logclient.ACT_UPDATE_TAGS, err, userCred, false)
|
||||
return errors.Wrap(err, "iVM.SetMetadata")
|
||||
}
|
||||
logclient.AddSimpleActionLog(guest, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true)
|
||||
// sync back cloud metadata
|
||||
iVM.Refresh()
|
||||
err = models.SyncVirtualResourceMetadata(ctx, userCred, guest, iVM)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "syncVirtualResourceMetadata")
|
||||
}
|
||||
return errors.Wrapf(err, "GetAllUserMetadata")
|
||||
}
|
||||
tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags}
|
||||
err = iVM.SetTags(tags, replaceTags)
|
||||
if err != nil {
|
||||
logclient.AddSimpleActionLog(guest, logclient.ACT_UPDATE_TAGS, err, userCred, false)
|
||||
return errors.Wrap(err, "iVM.SetTags")
|
||||
}
|
||||
logclient.AddSimpleActionLog(guest, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true)
|
||||
// sync back cloud metadata
|
||||
iVM.Refresh()
|
||||
err = models.SyncVirtualResourceMetadata(ctx, userCred, guest, iVM)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "syncVirtualResourceMetadata")
|
||||
}
|
||||
|
||||
err = iVM.UpdateVM(ctx, guest.Name)
|
||||
|
||||
@@ -335,17 +335,16 @@ func (self *SManagedVirtualizationRegionDriver) RequestRemoteUpdateLoadbalancer(
|
||||
return nil, errors.Wrap(err, "iLoadbalancer.GetTags()")
|
||||
}
|
||||
tags, err := lb.GetAllUserMetadata()
|
||||
tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags}
|
||||
if err != nil {
|
||||
log.Errorf("GetAllUserMetadata fail %s", err)
|
||||
} else {
|
||||
err := iLoadbalancer.SetTags(tags, replaceTags)
|
||||
if err != nil {
|
||||
logclient.AddActionLogWithStartable(task, lb, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, false)
|
||||
return nil, errors.Wrap(err, "iLoadbalancer.SetMetadata")
|
||||
}
|
||||
logclient.AddActionLogWithStartable(task, lb, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true)
|
||||
return nil, errors.Wrapf(err, "lb.GetAllUserMetadata")
|
||||
}
|
||||
tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags}
|
||||
err = iLoadbalancer.SetTags(tags, replaceTags)
|
||||
if err != nil {
|
||||
logclient.AddActionLogWithStartable(task, lb, logclient.ACT_UPDATE_TAGS, err, userCred, false)
|
||||
return nil, errors.Wrap(err, "iLoadbalancer.SetMetadata")
|
||||
}
|
||||
logclient.AddActionLogWithStartable(task, lb, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true)
|
||||
return nil, nil
|
||||
})
|
||||
return nil
|
||||
@@ -2632,8 +2631,8 @@ func (self *SManagedVirtualizationRegionDriver) RequestRemoteUpdateDBInstance(ct
|
||||
tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags}
|
||||
err = iRds.SetTags(tags, replaceTags)
|
||||
if err != nil {
|
||||
logclient.AddActionLogWithStartable(task, instance, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, false)
|
||||
return nil, errors.Wrap(err, "iRds.SetMetadata")
|
||||
logclient.AddActionLogWithStartable(task, instance, logclient.ACT_UPDATE_TAGS, err, userCred, false)
|
||||
return nil, errors.Wrap(err, "iRds.SetTags")
|
||||
}
|
||||
logclient.AddActionLogWithStartable(task, instance, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true)
|
||||
return nil, nil
|
||||
@@ -3025,17 +3024,16 @@ func (self *SManagedVirtualizationRegionDriver) RequestRemoteUpdateElasticcache(
|
||||
return nil, errors.Wrap(err, "iElasticcache.GetTags()")
|
||||
}
|
||||
tags, err := elasticcache.GetAllUserMetadata()
|
||||
tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags}
|
||||
if err != nil {
|
||||
log.Errorf("GetAllUserMetadata fail %s", err)
|
||||
} else {
|
||||
err := iElasticcache.SetTags(tags, replaceTags)
|
||||
if err != nil {
|
||||
logclient.AddActionLogWithStartable(task, elasticcache, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, false)
|
||||
return nil, errors.Wrap(err, "iElasticcache.SetMetadata")
|
||||
}
|
||||
logclient.AddActionLogWithStartable(task, elasticcache, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true)
|
||||
return nil, errors.Wrapf(err, "GetAllUserMetadata")
|
||||
}
|
||||
tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags}
|
||||
err = iElasticcache.SetTags(tags, replaceTags)
|
||||
if err != nil {
|
||||
logclient.AddActionLogWithStartable(task, elasticcache, logclient.ACT_UPDATE_TAGS, err, userCred, false)
|
||||
return nil, errors.Wrap(err, "iElasticcache.SetTags")
|
||||
}
|
||||
logclient.AddActionLogWithStartable(task, elasticcache, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true)
|
||||
return nil, nil
|
||||
})
|
||||
return nil
|
||||
|
||||
@@ -63,6 +63,12 @@ const (
|
||||
ALIYUN_CBN_API_VERSION = "2017-09-12"
|
||||
ALIYUN_CDN_API_VERSION = "2018-05-10"
|
||||
ALIYUN_IMS_API_VERSION = "2019-08-15"
|
||||
|
||||
ALIYUN_SERVICE_ECS = "ecs"
|
||||
ALIYUN_SERVICE_VPC = "vpc"
|
||||
ALIYUN_SERVICE_RDS = "rds"
|
||||
ALIYUN_SERVICE_SLB = "slb"
|
||||
ALIYUN_SERVICE_KVS = "kvs"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -708,7 +708,7 @@ func (region *SRegion) CreateIDBInstance(desc *cloudprovider.SManagedDBInstanceC
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, `resp.GetString("DBInstanceId")`)
|
||||
}
|
||||
region.SetResourceTags("rds", "INSTANCE", []string{instanceId}, desc.Tags, false)
|
||||
region.SetResourceTags(ALIYUN_SERVICE_RDS, "INSTANCE", instanceId, desc.Tags, false)
|
||||
return region.GetIDBInstanceById(instanceId)
|
||||
}
|
||||
|
||||
@@ -847,31 +847,18 @@ func (region *SRegion) RenewDBInstance(instanceId string, bc billing.SBillingCyc
|
||||
return err
|
||||
}
|
||||
|
||||
func (rds *SDBInstance) GetMetadata() *jsonutils.JSONDict {
|
||||
data := jsonutils.NewDict()
|
||||
tags, err := rds.region.ListResourceTags("rds", "INSTANCE", []string{rds.GetId()})
|
||||
if err != nil {
|
||||
log.Errorf(`[err:%s]rds.region.FetchResourceTags("slb", "instance", []string{rds.GetId()})`, err.Error())
|
||||
return nil
|
||||
}
|
||||
if _, ok := tags[rds.GetId()]; !ok {
|
||||
return nil
|
||||
}
|
||||
data.Update(jsonutils.Marshal(tags[rds.GetId()]))
|
||||
return data
|
||||
}
|
||||
|
||||
func (rds *SDBInstance) GetTags() (map[string]string, error) {
|
||||
tags, err := rds.region.ListResourceTags("rds", "INSTANCE", []string{rds.GetId()})
|
||||
tags, err := rds.region.ListTags(ALIYUN_SERVICE_RDS, "INSTANCE", rds.GetId())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, `rds.region.ListResourceTags`)
|
||||
return nil, errors.Wrap(err, `rds.region.ListTags`)
|
||||
}
|
||||
if _, ok := tags[rds.GetId()]; !ok {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
ret := map[string]string{}
|
||||
for _, tag := range tags {
|
||||
ret[tag.TagKey] = tag.TagValue
|
||||
}
|
||||
return *tags[rds.GetId()], nil
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (rds *SDBInstance) SetTags(tags map[string]string, replace bool) error {
|
||||
return rds.region.SetResourceTags("rds", "INSTANCE", []string{rds.GetId()}, tags, replace)
|
||||
return rds.region.SetResourceTags(ALIYUN_SERVICE_RDS, "INSTANCE", rds.GetId(), tags, replace)
|
||||
}
|
||||
|
||||
@@ -653,7 +653,7 @@ func (self *SRegion) CreateIElasticcaches(ec *cloudprovider.SCloudElasticCacheIn
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "region.CreateIElasticcaches")
|
||||
}
|
||||
self.SetResourceTags("kvs", "INSTANCE", []string{ret.InstanceID}, ec.Tags, false)
|
||||
self.SetResourceTags(ALIYUN_SERVICE_KVS, "INSTANCE", ret.InstanceID, ec.Tags, true)
|
||||
|
||||
ret.region = self
|
||||
return ret, nil
|
||||
@@ -925,34 +925,20 @@ func (self *SElasticcache) GetICloudElasticcacheBackup(backupId string) (cloudpr
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (instance *SElasticcache) GetMetadata() *jsonutils.JSONDict {
|
||||
data := jsonutils.NewDict()
|
||||
tags, err := instance.region.ListResourceTags("kvs", "INSTANCE", []string{instance.GetId()})
|
||||
if err != nil {
|
||||
log.Errorf(`[err:%s]instance.region.FetchResourceTags("kvs", "instance", []string{instance.GetId()})`, err.Error())
|
||||
return nil
|
||||
}
|
||||
if _, ok := tags[instance.GetId()]; !ok {
|
||||
return nil
|
||||
}
|
||||
data.Update(jsonutils.Marshal(tags[instance.GetId()]))
|
||||
return data
|
||||
}
|
||||
|
||||
func (instance *SElasticcache) GetTags() (map[string]string, error) {
|
||||
tags, err := instance.region.ListResourceTags("kvs", "INSTANCE", []string{instance.GetId()})
|
||||
tags, err := instance.region.ListTags(ALIYUN_SERVICE_KVS, "INSTANCE", instance.GetId())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "instance.region.ListResourceTags")
|
||||
return nil, errors.Wrap(err, "instance.region.ListTags")
|
||||
}
|
||||
if _, ok := tags[instance.GetId()]; !ok {
|
||||
log.Debugf("SElasticcache.GetTags %s, tags %#v", instance.GetId(), tags)
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
ret := map[string]string{}
|
||||
for _, tag := range tags {
|
||||
ret[tag.TagKey] = tag.TagValue
|
||||
}
|
||||
return *tags[instance.GetId()], nil
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (instance *SElasticcache) SetTags(tags map[string]string, replace bool) error {
|
||||
return instance.region.SetResourceTags("kvs", "INSTANCE", []string{instance.GetId()}, tags, replace)
|
||||
return instance.region.SetResourceTags(ALIYUN_SERVICE_KVS, "INSTANCE", instance.GetId(), tags, replace)
|
||||
}
|
||||
|
||||
func (self *SElasticcache) UpdateSecurityGroups(secgroupIds []string) error {
|
||||
|
||||
@@ -129,6 +129,9 @@ type SInstance struct {
|
||||
VlanId string
|
||||
VpcAttributes SVpcAttributes
|
||||
ZoneId string
|
||||
|
||||
sys map[string]string
|
||||
user map[string]string
|
||||
}
|
||||
|
||||
// {"AutoReleaseTime":"","ClusterId":"","Cpu":1,"CreationTime":"2018-05-23T07:58Z","DedicatedHostAttribute":{"DedicatedHostId":"","DedicatedHostName":""},"Description":"","DeviceAvailable":true,"EipAddress":{"AllocationId":"","InternetChargeType":"","IpAddress":""},"ExpiredTime":"2018-05-30T16:00Z","GPUAmount":0,"GPUSpec":"","HostName":"iZ2ze57isp1ali72tzkjowZ","ImageId":"centos_7_04_64_20G_alibase_201701015.vhd","InnerIpAddress":{"IpAddress":[]},"InstanceChargeType":"PrePaid","InstanceId":"i-2ze57isp1ali72tzkjow","InstanceName":"gaoxianqi-test-7days","InstanceNetworkType":"vpc","InstanceType":"ecs.t5-lc2m1.nano","InstanceTypeFamily":"ecs.t5","InternetChargeType":"PayByBandwidth","InternetMaxBandwidthIn":-1,"InternetMaxBandwidthOut":0,"IoOptimized":true,"Memory":512,"NetworkInterfaces":{"NetworkInterface":[{"MacAddress":"00:16:3e:10:f0:c9","NetworkInterfaceId":"eni-2zecqsagtpztl6x5hu2r","PrimaryIpAddress":"192.168.220.214"}]},"OSName":"CentOS 7.4 64位","OSType":"linux","OperationLocks":{"LockReason":[]},"PublicIpAddress":{"IpAddress":[]},"Recyclable":false,"RegionId":"cn-beijing","ResourceGroupId":"","SaleCycle":"Week","SecurityGroupIds":{"SecurityGroupId":["sg-2zecqsagtpztl6x9zynl"]},"SerialNumber":"df05d9b4-df3d-4400-88d1-5f843f0dd088","SpotPriceLimit":0.000000,"SpotStrategy":"NoSpot","StartTime":"2018-05-23T07:58Z","Status":"Running","StoppedMode":"Not-applicable","VlanId":"","VpcAttributes":{"NatIpAddress":"","PrivateIpAddress":{"IpAddress":["192.168.220.214"]},"VSwitchId":"vsw-2ze9cqwza4upoyujq1thd","VpcId":"vpc-2zer4jy8ix3i8f0coc5uw"},"ZoneId":"cn-beijing-f"}
|
||||
@@ -166,56 +169,9 @@ func (self *SRegion) GetInstances(zoneId string, ids []string, offset int, limit
|
||||
return instances, int(total), nil
|
||||
}
|
||||
|
||||
func (self *SRegion) fetchTags(resourceType string, resourceId string) (*jsonutils.JSONDict, error) {
|
||||
// 资源类型。取值范围:
|
||||
// disk
|
||||
// instance
|
||||
// image
|
||||
// securitygroup
|
||||
// snapshot
|
||||
var page int64 = 1
|
||||
var pageSize int64 = 50
|
||||
params := make(map[string]string)
|
||||
params["RegionId"] = self.RegionId
|
||||
params["ResourceType"] = resourceType
|
||||
params["ResourceId"] = resourceId
|
||||
params["PageSize"] = fmt.Sprintf("%d", pageSize)
|
||||
params["PageNumber"] = fmt.Sprintf("%d", page)
|
||||
ret, err := self.ecsRequest("DescribeTags", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tags := jsonutils.NewDict()
|
||||
result, _ := ret.GetArray("Tags", "Tag")
|
||||
for _, item := range result {
|
||||
k, _ := item.GetString("TagKey")
|
||||
v, _ := item.Get("TagValue")
|
||||
if len(k) > 0 {
|
||||
tags.Set(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
total, _ := ret.Int("TotalCount")
|
||||
for ; total > page*pageSize; page++ {
|
||||
params["PageSize"] = fmt.Sprintf("%d", pageSize)
|
||||
params["PageNumber"] = fmt.Sprintf("%d", page)
|
||||
ret, err := self.ecsRequest("DescribeTags", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result, _ := ret.GetArray("Tags", "Tag")
|
||||
for _, item := range result {
|
||||
k, _ := item.GetString("TagKey")
|
||||
v, _ := item.Get("TagValue")
|
||||
if len(k) > 0 {
|
||||
tags.Set(k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tags, nil
|
||||
type SAliyunTag struct {
|
||||
TagKey string
|
||||
TagValue string
|
||||
}
|
||||
|
||||
func (self *SInstance) GetSecurityGroupIds() ([]string, error) {
|
||||
@@ -233,11 +189,11 @@ func (self *SInstance) GetMetadata() *jsonutils.JSONDict {
|
||||
priceKey := fmt.Sprintf("%s::%s::%s::%s::%s", self.RegionId, self.InstanceType, self.InstanceNetworkType, self.OSType, optimized)
|
||||
data.Add(jsonutils.NewString(priceKey), "price_key")
|
||||
|
||||
tags, err := self.host.zone.region.fetchTags("instance", self.InstanceId)
|
||||
_, tags, err := self.fetchTags()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
data.Update(tags)
|
||||
data.Update(jsonutils.Marshal(tags))
|
||||
|
||||
data.Add(jsonutils.NewString(self.host.zone.GetGlobalId()), "zone_ext_id")
|
||||
if len(self.ImageId) > 0 {
|
||||
@@ -270,20 +226,31 @@ func (self *SInstance) GetSysTags() map[string]string {
|
||||
}
|
||||
}
|
||||
}
|
||||
sys, _, _ := self.fetchTags()
|
||||
for k, v := range sys {
|
||||
data[k] = v
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (self *SInstance) GetTags() (map[string]string, error) {
|
||||
tags, err := self.host.zone.region.fetchTags("instance", self.InstanceId)
|
||||
_, tags, err := self.fetchTags()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "self.host.zone.region.fetchTags")
|
||||
return nil, errors.Wrap(err, "self.fetchTags")
|
||||
}
|
||||
data := map[string]string{}
|
||||
err = tags.Unmarshal(&data)
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) fetchTags() (map[string]string, map[string]string, error) {
|
||||
if self.sys != nil || self.user != nil {
|
||||
return self.sys, self.user, nil
|
||||
}
|
||||
var err error
|
||||
self.sys, self.user, err = self.host.zone.region.ListSysAndUserTags(ALIYUN_SERVICE_ECS, "instance", self.InstanceId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "tags.Unmarshal")
|
||||
return nil, nil, errors.Wrapf(err, "ListSysAndUserTags")
|
||||
}
|
||||
return data, nil
|
||||
return self.sys, self.user, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetIHost() cloudprovider.ICloudHost {
|
||||
@@ -442,6 +409,7 @@ func (self *SInstance) GetStatus() string {
|
||||
}
|
||||
|
||||
func (self *SInstance) Refresh() error {
|
||||
self.sys, self.user = nil, nil
|
||||
new, err := self.host.zone.region.GetInstance(self.InstanceId)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1143,7 +1111,7 @@ func (self *SInstance) SetAutoRenew(autoRenew bool) error {
|
||||
}
|
||||
|
||||
func (self *SInstance) SetTags(tags map[string]string, replace bool) error {
|
||||
return self.host.zone.region.SetResourceTags("ecs", "instance", []string{self.InstanceId}, tags, replace)
|
||||
return self.host.zone.region.SetResourceTags(ALIYUN_SERVICE_ECS, "instance", self.InstanceId, tags, replace)
|
||||
}
|
||||
|
||||
func (self *SRegion) SaveImage(instanceId string, opts *cloudprovider.SaveImageOptions) (*SImage, error) {
|
||||
|
||||
@@ -103,29 +103,16 @@ func (lb *SLoadbalancer) GetStatus() string {
|
||||
return api.LB_STATUS_DISABLED
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) GetMetadata() *jsonutils.JSONDict {
|
||||
data := jsonutils.NewDict()
|
||||
tags, err := lb.region.ListResourceTags("slb", "instance", []string{lb.GetId()})
|
||||
if err != nil {
|
||||
log.Errorf(`[err:%s]lb.region.FetchResourceTags("slb", "instance", []string{lb.GetId()})`, err.Error())
|
||||
return nil
|
||||
}
|
||||
if _, ok := tags[lb.GetId()]; !ok {
|
||||
return nil
|
||||
}
|
||||
data.Update(jsonutils.Marshal(tags[lb.GetId()]))
|
||||
return data
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) GetTags() (map[string]string, error) {
|
||||
tags, err := lb.region.ListResourceTags("slb", "instance", []string{lb.GetId()})
|
||||
tags, err := lb.region.ListTags(ALIYUN_SERVICE_SLB, "instance", lb.GetId())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "lb.region.ListResourceTags")
|
||||
return nil, errors.Wrap(err, "lb.region.ListTags")
|
||||
}
|
||||
if _, ok := tags[lb.GetId()]; !ok {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
ret := map[string]string{}
|
||||
for _, tag := range tags {
|
||||
ret[tag.TagKey] = tag.TagValue
|
||||
}
|
||||
return *tags[lb.GetId()], nil
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) GetAddress() string {
|
||||
@@ -424,7 +411,7 @@ func (lb *SLoadbalancer) GetProjectId() string {
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) SetTags(tags map[string]string, replace bool) error {
|
||||
return lb.region.SetResourceTags("slb", "instance", []string{lb.LoadBalancerId}, tags, replace)
|
||||
return lb.region.SetResourceTags(ALIYUN_SERVICE_SLB, "instance", lb.LoadBalancerId, tags, replace)
|
||||
}
|
||||
|
||||
// mapping aliyun finance zoneId to aliyun finance ecs zoneId
|
||||
|
||||
@@ -166,21 +166,6 @@ func (self *SRegion) kvsRequest(action string, params map[string]string) (jsonut
|
||||
return jsonRequest(client, "r-kvstore.aliyuncs.com", ALIYUN_API_VERSION_KVS, action, params, self.client.debug)
|
||||
}
|
||||
|
||||
func (self *SRegion) tagRequest(serviceType string, action string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
switch serviceType {
|
||||
case "ecs":
|
||||
return self.ecsRequest(action, params)
|
||||
case "rds":
|
||||
return self.rdsRequest(action, params)
|
||||
case "slb":
|
||||
return self.lbRequest(action, params)
|
||||
case "kvs":
|
||||
return self.kvsRequest(action, params)
|
||||
default:
|
||||
return nil, errors.Wrapf(errors.ErrNotSupported, "not support %service tag", serviceType)
|
||||
}
|
||||
}
|
||||
|
||||
type LBRegion struct {
|
||||
RegionEndpoint string
|
||||
RegionId string
|
||||
@@ -969,7 +954,7 @@ func (region *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbala
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
region.SetResourceTags("slb", "instance", []string{loadBalancerID}, loadbalancer.Tags, false)
|
||||
region.SetResourceTags(ALIYUN_SERVICE_SLB, "instance", loadBalancerID, loadbalancer.Tags, false)
|
||||
iLoadbalancer, err := region.GetLoadbalancerDetail(loadBalancerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -16,6 +16,7 @@ package aliyun
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
@@ -23,222 +24,138 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type STagResource struct {
|
||||
ResourceType string `json:"ResourceType"`
|
||||
TagValue string `json:"TagValue"`
|
||||
ResourceID string `json:"ResourceId"`
|
||||
TagKey string `json:"TagKey"`
|
||||
func (self *SRegion) tagRequest(serviceType, action string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
switch serviceType {
|
||||
case ALIYUN_SERVICE_ECS:
|
||||
return self.ecsRequest(action, params)
|
||||
case ALIYUN_SERVICE_VPC:
|
||||
return self.vpcRequest(action, params)
|
||||
case ALIYUN_SERVICE_RDS:
|
||||
return self.rdsRequest(action, params)
|
||||
case ALIYUN_SERVICE_SLB:
|
||||
return self.lbRequest(action, params)
|
||||
case ALIYUN_SERVICE_KVS:
|
||||
return self.kvsRequest(action, params)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid service type")
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) rawListTagResources(serviceType string, resourceType string, resIds []string, token string) ([]STagResource, string, error) {
|
||||
if len(resIds) > 50 {
|
||||
return nil, "", errors.Wrap(cloudprovider.ErrNotSupported, "resource count exceed 50 for one request")
|
||||
}
|
||||
// 资源类型。取值范围:
|
||||
// disk, instance, image, securitygroup, snapshot
|
||||
func (self *SRegion) ListTags(serviceType string, resourceType string, resourceId string) ([]SAliyunTag, error) {
|
||||
tags := []SAliyunTag{}
|
||||
params := make(map[string]string)
|
||||
params["RegionId"] = self.RegionId
|
||||
params["ResourceType"] = resourceType
|
||||
for i := range resIds {
|
||||
params[fmt.Sprintf("ResourceId.%d", i+1)] = resIds[i]
|
||||
}
|
||||
if len(token) != 0 {
|
||||
params["NextToken"] = token
|
||||
}
|
||||
ret, err := self.tagRequest(serviceType, "ListTagResources", params)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrapf(err, `self.tagRequest(%s,"ListTagResources", %s)`, serviceType, jsonutils.Marshal(params).String())
|
||||
}
|
||||
tagResources := []STagResource{}
|
||||
err = ret.Unmarshal(&tagResources, "TagResources", "TagResource")
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrapf(err, "(%s).Unmarshal(&tagResources)", ret.String())
|
||||
}
|
||||
nextToken, _ := ret.GetString("NextToken")
|
||||
return tagResources, nextToken, nil
|
||||
}
|
||||
|
||||
func splitStringSlice(resIds []string, stride int) [][]string {
|
||||
result := [][]string{}
|
||||
i := 0
|
||||
for i < len(resIds)/stride {
|
||||
result = append(result, resIds[i*stride:i*stride+stride])
|
||||
i++
|
||||
}
|
||||
remainder := len(resIds) % stride
|
||||
if remainder != 0 {
|
||||
result = append(result, resIds[i*stride:i*stride+remainder])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func splitTags(tags map[string]string, stride int) []map[string]string {
|
||||
tagsGroups := []map[string]string{}
|
||||
tagsGroup := map[string]string{}
|
||||
for k, v := range tags {
|
||||
tagsGroup[k] = v
|
||||
if len(tagsGroup) == stride {
|
||||
tagsGroups = append(tagsGroups, tagsGroup)
|
||||
tagsGroup = map[string]string{}
|
||||
params["ResourceId.1"] = resourceId
|
||||
params["PageSize"] = "50"
|
||||
var page int = 1
|
||||
for {
|
||||
params["PageNumber"] = fmt.Sprintf("%d", page)
|
||||
resp, err := self.tagRequest(serviceType, "DescribeTags", params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "%s DescribeTags %s", serviceType, params)
|
||||
}
|
||||
}
|
||||
if len(tagsGroup) > 0 {
|
||||
tagsGroups = append(tagsGroups, tagsGroup)
|
||||
}
|
||||
return tagsGroups
|
||||
}
|
||||
|
||||
func (self *SRegion) ListResourceTags(serviceType string, resourceType string, resIds []string) (map[string]*map[string]string, error) {
|
||||
tags := make(map[string]*map[string]string)
|
||||
tagReources := []STagResource{}
|
||||
nextToken := ""
|
||||
resIdsGroups := splitStringSlice(resIds, 50)
|
||||
for i := range resIdsGroups {
|
||||
for {
|
||||
_tagResource, nextToken, err := self.rawListTagResources(serviceType, resourceType, resIdsGroups[i], nextToken)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "self.rawListTagResources(%s,%s,%s)", resourceType, resIds, nextToken)
|
||||
}
|
||||
tagReources = append(tagReources, _tagResource...)
|
||||
if len(_tagResource) == 0 || len(nextToken) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
part := []SAliyunTag{}
|
||||
err = resp.Unmarshal(&part, "Tags", "Tag")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
}
|
||||
for _, r := range tagReources {
|
||||
if tagMapPtr, ok := tags[r.ResourceID]; !ok {
|
||||
tagMap := map[string]string{
|
||||
r.TagKey: r.TagValue,
|
||||
}
|
||||
tags[r.ResourceID] = &tagMap
|
||||
} else {
|
||||
tagMap := *tagMapPtr
|
||||
tagMap[r.TagKey] = r.TagValue
|
||||
tags = append(tags, part...)
|
||||
total, _ := resp.Int("TotalCount")
|
||||
if len(tags) >= int(total) {
|
||||
break
|
||||
}
|
||||
page++
|
||||
}
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) rawTagResources(serviceType string, resourceType string, resIds []string, tags map[string]string) error {
|
||||
if len(resIds) > 50 {
|
||||
return errors.Wrap(cloudprovider.ErrNotSupported, "resource count exceed 50 for one request")
|
||||
func (self *SRegion) UntagResource(serviceType string, resourceType string, resId string, keys []string) error {
|
||||
if len(resId) == 0 || len(keys) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"ResourceId.1": resId,
|
||||
"ResourceType": resourceType,
|
||||
}
|
||||
for i, key := range keys {
|
||||
params[fmt.Sprintf("TagKey.%d", i+1)] = key
|
||||
}
|
||||
|
||||
_, err := self.tagRequest(serviceType, "UntagResources", params)
|
||||
return errors.Wrapf(err, "UntagResources %s", params)
|
||||
}
|
||||
|
||||
func (self *SRegion) SetResourceTags(serviceType string, resourceType string, resId string, tags map[string]string, replace bool) error {
|
||||
err := self.TagResource(serviceType, resourceType, resId, tags)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "TagResource")
|
||||
}
|
||||
if !replace {
|
||||
return nil
|
||||
}
|
||||
_, _tags, err := self.ListSysAndUserTags(serviceType, resourceType, resId)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "ListTags")
|
||||
}
|
||||
tagMaps := map[string]string{}
|
||||
for k, v := range tags {
|
||||
tagMaps[strings.ToLower(k)] = v
|
||||
}
|
||||
keys := []string{}
|
||||
for k, _ := range _tags {
|
||||
if _, ok := tagMaps[strings.ToLower(k)]; !ok {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
}
|
||||
return self.UntagResource(serviceType, resourceType, resId, keys)
|
||||
}
|
||||
|
||||
func (self *SRegion) TagResource(serviceType string, resourceType string, resourceId string, tags map[string]string) error {
|
||||
if len(tags) > 20 {
|
||||
return errors.Wrap(cloudprovider.ErrNotSupported, "tags count exceed 20 for one request")
|
||||
}
|
||||
params := make(map[string]string)
|
||||
params["ResourceType"] = resourceType
|
||||
for i := range resIds {
|
||||
params[fmt.Sprintf("ResourceId.%d", i+1)] = resIds[i]
|
||||
}
|
||||
params["ResourceId.1"] = resourceId
|
||||
i := 0
|
||||
for k, v := range tags {
|
||||
if strings.HasPrefix(k, "aliyun") ||
|
||||
strings.HasPrefix(k, "acs:") ||
|
||||
strings.HasPrefix(k, "http://") ||
|
||||
strings.HasPrefix(k, "https://") ||
|
||||
strings.HasPrefix(v, "http://") ||
|
||||
strings.HasPrefix(v, "https://") ||
|
||||
strings.HasPrefix(v, "acs:") {
|
||||
continue
|
||||
}
|
||||
params[fmt.Sprintf("Tag.%d.Key", i+1)] = k
|
||||
params[fmt.Sprintf("Tag.%d.Value", i+1)] = v
|
||||
i++
|
||||
}
|
||||
_, err := self.tagRequest(serviceType, "TagResources", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, `self.tagRequest(%s,"TagResources", %s)`, serviceType, jsonutils.Marshal(params).String())
|
||||
return errors.Wrapf(err, "TagResources %s %s", resourceId, params)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) TagResources(serviceType string, resourceType string, resIds []string, tags map[string]string) error {
|
||||
if len(resIds) == 0 || len(tags) == 0 {
|
||||
return nil
|
||||
}
|
||||
resIdsGroups := splitStringSlice(resIds, 50)
|
||||
tagsGroups := splitTags(tags, 20)
|
||||
for i := range resIdsGroups {
|
||||
for j := range tagsGroups {
|
||||
err := self.rawTagResources(serviceType, resourceType, resIdsGroups[i], tagsGroups[j])
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "self.rawTagResources(resourceType, resIdsGroups[i], tagsGroups[i])")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) rawUntagResources(serviceType string, resourceType string, resIds []string, tags []string) error {
|
||||
if len(resIds) > 50 {
|
||||
return errors.Wrap(cloudprovider.ErrNotSupported, "resource count exceed 50 for one request")
|
||||
}
|
||||
if len(tags) > 20 {
|
||||
return errors.Wrap(cloudprovider.ErrNotSupported, "tags count exceed 20 for one request")
|
||||
}
|
||||
params := make(map[string]string)
|
||||
params["ResourceType"] = resourceType
|
||||
for i := range resIds {
|
||||
params[fmt.Sprintf("ResourceId.%d", i+1)] = resIds[i]
|
||||
}
|
||||
for i := range tags {
|
||||
params[fmt.Sprintf("TagKey.%d", i+1)] = tags[i]
|
||||
}
|
||||
_, err := self.tagRequest(serviceType, "UntagResources", params)
|
||||
func (self *SRegion) ListSysAndUserTags(serviceType string, resourceType string, resourceId string) (map[string]string, map[string]string, error) {
|
||||
tags, err := self.ListTags(serviceType, resourceType, resourceId)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, `self.tagRequest(%s,"UntagResources", %s)`, serviceType, jsonutils.Marshal(params).String())
|
||||
return nil, nil, errors.Wrapf(err, "ListTags(%s, %s)", resourceType, resourceId)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) UntagResources(serviceType string, resourceType string, resIds []string, tags []string) error {
|
||||
if len(resIds) == 0 || len(tags) == 0 {
|
||||
return nil
|
||||
}
|
||||
resIdsGroups := splitStringSlice(resIds, 50)
|
||||
tagsGroups := splitStringSlice(tags, 20)
|
||||
for i := range resIdsGroups {
|
||||
for j := range tagsGroups {
|
||||
err := self.rawUntagResources(serviceType, resourceType, resIdsGroups[i], tagsGroups[j])
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "self.rawTagResources(resourceType, resIdsGroups[i], tagsGroups[i])")
|
||||
}
|
||||
sys, user := map[string]string{}, map[string]string{}
|
||||
for _, tag := range tags {
|
||||
if strings.HasPrefix(tag.TagKey, "aliyun") || strings.HasPrefix(tag.TagKey, "acs:") {
|
||||
sys[tag.TagKey] = tag.TagValue
|
||||
continue
|
||||
}
|
||||
user[tag.TagKey] = tag.TagValue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) SetResourceTags(serviceType string, resourceType string, resIds []string, tags map[string]string, replace bool) error {
|
||||
oldTags, err := self.ListResourceTags(serviceType, resourceType, resIds)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "self.ListResourceTags(%s,%s)", resourceType, resIds)
|
||||
}
|
||||
for i := range resIds {
|
||||
_, ok := oldTags[resIds[i]]
|
||||
if !ok {
|
||||
err := self.TagResources(serviceType, resourceType, []string{resIds[i]}, tags)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "self.TagResources(resourceType, []string{resIds[i]}, tags)")
|
||||
}
|
||||
} else {
|
||||
oldResourceTags := *oldTags[resIds[i]]
|
||||
addTags := map[string]string{}
|
||||
for k, v := range tags {
|
||||
if _, ok := oldResourceTags[k]; !ok {
|
||||
addTags[k] = v
|
||||
} else {
|
||||
if oldResourceTags[k] != v {
|
||||
addTags[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
delTags := []string{}
|
||||
if replace {
|
||||
for k := range oldResourceTags {
|
||||
if _, ok := tags[k]; !ok {
|
||||
delTags = append(delTags, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
err := self.UntagResources(serviceType, resourceType, []string{resIds[i]}, delTags)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "self.UntagResources(resourceType, []string{resIds[i]}, delTags)")
|
||||
}
|
||||
err = self.TagResources(serviceType, resourceType, []string{resIds[i]}, addTags)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "self.TagResources(resourceType, []string{resIds[i]}, addTags)")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return sys, user, nil
|
||||
}
|
||||
|
||||
@@ -15,45 +15,63 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/multicloud/aliyun"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type TagGetOptions struct {
|
||||
SERVICE string `help:"service, eg. ecs"`
|
||||
RESTYPE string `help:"resource type, eg. instance"`
|
||||
ID []string `help:"resource Id, eg. ins-123xxx"`
|
||||
SERVICE string `help:"service, eg. ecs" choices:"ecs|kvs|rds|vpc|slb"`
|
||||
RESTYPE string `help:"resource type, eg. instance"`
|
||||
ID string `help:"resource Id, eg. ins-123xxx"`
|
||||
}
|
||||
shellutils.R(&TagGetOptions{}, "tag-show", "show tag of a specific resource", func(cli *aliyun.SRegion, args *TagGetOptions) error {
|
||||
tags, err := cli.ListResourceTags(args.SERVICE, args.RESTYPE, args.ID)
|
||||
shellutils.R(&TagGetOptions{}, "tag-list", "List tag of a specific resource", func(cli *aliyun.SRegion, args *TagGetOptions) error {
|
||||
tags, err := cli.ListTags(args.SERVICE, args.RESTYPE, args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for id, tag := range tags {
|
||||
fmt.Println(id, *tag)
|
||||
}
|
||||
printObject(tags)
|
||||
return nil
|
||||
})
|
||||
|
||||
type TagOptions struct {
|
||||
TagGetOptions
|
||||
KEY string
|
||||
VALUE string
|
||||
}
|
||||
shellutils.R(&TagOptions{}, "tag-resource", "set tags of a specific resource", func(cli *aliyun.SRegion, args *TagOptions) error {
|
||||
return cli.TagResource(args.SERVICE, args.RESTYPE, args.ID, map[string]string{args.KEY: args.VALUE})
|
||||
})
|
||||
|
||||
type UnTagOptions struct {
|
||||
TagGetOptions
|
||||
KEY []string
|
||||
}
|
||||
|
||||
shellutils.R(&UnTagOptions{}, "untag-resource", "un tags of a specific resource", func(cli *aliyun.SRegion, args *UnTagOptions) error {
|
||||
return cli.UntagResource(args.SERVICE, args.RESTYPE, args.ID, args.KEY)
|
||||
})
|
||||
|
||||
type TagSetOptions struct {
|
||||
TagGetOptions
|
||||
Tag []string `help:"tag to set, key:value"`
|
||||
Replace bool `help:"replace all tags"`
|
||||
VALUES []string
|
||||
Replace bool
|
||||
}
|
||||
|
||||
shellutils.R(&TagSetOptions{}, "tag-set", "set tags of a specific resource", func(cli *aliyun.SRegion, args *TagSetOptions) error {
|
||||
tags := make(map[string]string)
|
||||
for _, t := range args.Tag {
|
||||
parts := strings.Split(t, ":")
|
||||
tags[parts[0]] = parts[1]
|
||||
tags := map[string]string{}
|
||||
for _, value := range args.VALUES {
|
||||
v := strings.Split(value, ":")
|
||||
if len(v) != 2 {
|
||||
return errors.Errorf("invalid tag %s", value)
|
||||
}
|
||||
tags[v[0]] = v[1]
|
||||
}
|
||||
err := cli.SetResourceTags(args.SERVICE, args.RESTYPE, args.ID, tags, args.Replace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return cli.SetResourceTags(args.SERVICE, args.RESTYPE, args.ID, tags, args.Replace)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user