yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aliyun/resource_tags.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package aliyun 16 17 import ( 18 "fmt" 19 "strings" 20 21 "yunion.io/x/jsonutils" 22 "yunion.io/x/pkg/errors" 23 "yunion.io/x/pkg/utils" 24 25 "yunion.io/x/cloudmux/pkg/cloudprovider" 26 ) 27 28 func (self *SRegion) tagRequest(serviceType, action string, params map[string]string) (jsonutils.JSONObject, error) { 29 switch serviceType { 30 case ALIYUN_SERVICE_ECS: 31 return self.ecsRequest(action, params) 32 case ALIYUN_SERVICE_VPC: 33 return self.vpcRequest(action, params) 34 case ALIYUN_SERVICE_RDS: 35 return self.rdsRequest(action, params) 36 case ALIYUN_SERVICE_SLB: 37 return self.lbRequest(action, params) 38 case ALIYUN_SERVICE_KVS: 39 return self.kvsRequest(action, params) 40 case ALIYUN_SERVICE_NAS: 41 return self.nasRequest(action, params) 42 case ALIYUN_SERVICE_MONGO_DB: 43 return self.mongodbRequest(action, params) 44 case ALIYUN_SERVICE_CDN: 45 return self.client.cdnRequest(action, params) 46 default: 47 return nil, fmt.Errorf("invalid service type") 48 } 49 } 50 51 // 资源类型。取值范围: 52 // disk, instance, image, securitygroup, snapshot 53 func (self *SRegion) ListTags(serviceType string, resourceType string, resourceId string) ([]SAliyunTag, error) { 54 tags := []SAliyunTag{} 55 params := make(map[string]string) 56 params["RegionId"] = self.RegionId 57 params["ResourceType"] = resourceType 58 params["ResourceId.1"] = resourceId 59 nextToken := "" 60 for { 61 if len(nextToken) > 0 { 62 params["NextToken"] = nextToken 63 } 64 resp, err := self.tagRequest(serviceType, "ListTagResources", params) 65 if err != nil { 66 return nil, errors.Wrapf(err, "%s ListTagResources %s", serviceType, params) 67 } 68 part := []SAliyunTag{} 69 err = resp.Unmarshal(&part, "TagResources", "TagResource") 70 if err != nil { 71 return nil, errors.Wrapf(err, "resp.Unmarshal") 72 } 73 tags = append(tags, part...) 74 nextToken, _ = resp.GetString("NextToken") 75 if len(nextToken) == 0 { 76 break 77 } 78 } 79 return tags, nil 80 } 81 82 func (self *SRegion) UntagResource(serviceType string, resourceType string, resId string, keys []string) error { 83 if len(resId) == 0 || len(keys) == 0 { 84 return nil 85 } 86 87 params := map[string]string{ 88 "RegionId": self.RegionId, 89 "ResourceId.1": resId, 90 "ResourceType": resourceType, 91 } 92 for i, key := range keys { 93 params[fmt.Sprintf("TagKey.%d", i+1)] = key 94 } 95 96 _, err := self.tagRequest(serviceType, "UntagResources", params) 97 return errors.Wrapf(err, "UntagResources %s", params) 98 } 99 100 func (self *SRegion) SetResourceTags(serviceType string, resourceType string, resId string, tags map[string]string, replace bool) error { 101 _, _tags, err := self.ListSysAndUserTags(serviceType, resourceType, resId) 102 if err != nil { 103 return errors.Wrapf(err, "ListTags") 104 } 105 keys, upperKeys := []string{}, []string{} 106 for k := range tags { 107 keys = append(keys, k) 108 upperKeys = append(upperKeys, strings.ToUpper(k)) 109 } 110 if replace { 111 if len(tags) > 0 { 112 removeKeys := []string{} 113 for k := range _tags { 114 if !utils.IsInStringArray(k, keys) { 115 removeKeys = append(removeKeys, k) 116 } 117 } 118 if len(removeKeys) > 0 { 119 err := self.UntagResource(serviceType, resourceType, resId, removeKeys) 120 if err != nil { 121 return errors.Wrapf(err, "UntagResource") 122 } 123 } 124 } 125 } else { 126 removeKeys := []string{} 127 for k := range _tags { 128 if !utils.IsInStringArray(k, keys) && utils.IsInStringArray(strings.ToUpper(k), upperKeys) { 129 removeKeys = append(removeKeys, k) 130 } 131 } 132 if len(removeKeys) > 0 { 133 err := self.UntagResource(serviceType, resourceType, resId, removeKeys) 134 if err != nil { 135 return errors.Wrapf(err, "UntagResource") 136 } 137 } 138 } 139 return self.TagResource(serviceType, resourceType, resId, tags) 140 } 141 142 func (self *SRegion) TagResource(serviceType string, resourceType string, resourceId string, tags map[string]string) error { 143 if len(tags) > 20 { 144 return errors.Wrap(cloudprovider.ErrNotSupported, "tags count exceed 20 for one request") 145 } 146 params := make(map[string]string) 147 params["RegionId"] = self.RegionId 148 params["ResourceType"] = resourceType 149 params["ResourceId.1"] = resourceId 150 i := 0 151 for k, v := range tags { 152 if strings.HasPrefix(k, "aliyun") || 153 strings.HasPrefix(k, "acs:") || 154 strings.HasPrefix(k, "http://") || 155 strings.HasPrefix(k, "https://") || 156 strings.HasPrefix(v, "http://") || 157 strings.HasPrefix(v, "https://") || 158 strings.HasPrefix(v, "acs:") { 159 continue 160 } 161 params[fmt.Sprintf("Tag.%d.Key", i+1)] = k 162 params[fmt.Sprintf("Tag.%d.Value", i+1)] = v 163 i++ 164 } 165 action := "TagResources" 166 if len(tags) == 0 { 167 action = "UntagResources" 168 params["All"] = "true" 169 } 170 _, err := self.tagRequest(serviceType, action, params) 171 if err != nil { 172 return errors.Wrapf(err, "%s %s %s", action, resourceId, params) 173 } 174 return nil 175 } 176 177 func (self *SRegion) ListSysAndUserTags(serviceType string, resourceType string, resourceId string) (map[string]string, map[string]string, error) { 178 tags, err := self.ListTags(serviceType, resourceType, resourceId) 179 if err != nil { 180 return nil, nil, errors.Wrapf(err, "ListTags(%s, %s)", resourceType, resourceId) 181 } 182 sys, user := map[string]string{}, map[string]string{} 183 for _, tag := range tags { 184 if strings.HasPrefix(tag.TagKey, "aliyun") || strings.HasPrefix(tag.TagKey, "acs:") { 185 sys[tag.TagKey] = tag.TagValue 186 continue 187 } 188 user[tag.TagKey] = tag.TagValue 189 } 190 return sys, user, nil 191 }