yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aliyun/private_zone.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 "strconv" 19 20 "yunion.io/x/jsonutils" 21 "yunion.io/x/pkg/errors" 22 23 api "yunion.io/x/cloudmux/pkg/apis/compute" 24 "yunion.io/x/cloudmux/pkg/cloudprovider" 25 "yunion.io/x/cloudmux/pkg/multicloud" 26 ) 27 28 var allowedTtls = []int64{5, 10, 15, 20, 30, 60, 120, 300, 600, 1800, 3600, 43200, 86400} 29 30 type SPvtzVpc struct { 31 VpcID string `json:"VpcId"` 32 RegionName string `json:"RegionName"` 33 VpcName string `json:"VpcName"` 34 RegionID string `json:"RegionId"` 35 } 36 37 type SPvtzBindVpcs struct { 38 Vpc []SPvtzVpc `json:"Vpc"` 39 } 40 41 type SPrivateZone struct { 42 multicloud.SResourceBase 43 AliyunTags 44 client *SAliyunClient 45 46 // RequestID string `json:"RequestId"` 47 ZoneID string `json:"ZoneId"` 48 SlaveDNS string `json:"SlaveDns"` 49 ResourceGroupID string `json:"ResourceGroupId"` 50 ProxyPattern string `json:"ProxyPattern"` 51 CreateTime string `json:"CreateTime"` 52 Remark string `json:"Remark"` 53 ZoneName string `json:"ZoneName"` 54 UpdateTime string `json:"UpdateTime"` 55 UpdateTimestamp string `json:"UpdateTimestamp"` 56 RecordCount int `json:"RecordCount"` 57 CreateTimestamp int64 `json:"CreateTimestamp"` 58 BindVpcs SPvtzBindVpcs `json:"BindVpcs"` 59 IsPtr bool `json:"IsPtr"` 60 } 61 62 // list return 63 type sPrivateZones struct { 64 Zone []SPrivateZone `json:"Zone"` 65 } 66 67 type SPrivateZones struct { 68 RequestID string `json:"RequestId"` 69 PageSize int `json:"PageSize"` 70 PageNumber int `json:"PageNumber"` 71 TotalPages int `json:"TotalPages"` 72 TotalItems int `json:"TotalItems"` 73 Zones sPrivateZones `json:"Zones"` 74 } 75 76 // https://help.aliyun.com/document_detail/66243.html?spm=a2c4g.11186623.6.580.761357982tMV0Q 77 func (client *SAliyunClient) DescribeZones(pageNumber int, pageSize int) (SPrivateZones, error) { 78 sZones := SPrivateZones{} 79 params := map[string]string{} 80 params["Action"] = "DescribeZones" 81 params["PageNumber"] = strconv.Itoa(pageNumber) 82 params["PageSize"] = strconv.Itoa(pageSize) 83 resp, err := client.pvtzRequest("DescribeZones", params) 84 if err != nil { 85 return sZones, errors.Wrap(err, "DescribeZones") 86 } 87 err = resp.Unmarshal(&sZones) 88 if err != nil { 89 return sZones, errors.Wrap(err, "resp.Unmarshal") 90 } 91 return sZones, nil 92 } 93 94 // 没有vpc等详细信息 95 func (client *SAliyunClient) GetAllZones() ([]SPrivateZone, error) { 96 pageNumber := 0 97 szones := []SPrivateZone{} 98 for { 99 pageNumber++ 100 zones, err := client.DescribeZones(pageNumber, 20) 101 if err != nil { 102 return nil, errors.Wrapf(err, "client.DescribeZones(%d, 20)", pageNumber) 103 } 104 szones = append(szones, zones.Zones.Zone...) 105 if len(szones) >= zones.TotalItems { 106 break 107 } 108 } 109 return szones, nil 110 } 111 112 func (client *SAliyunClient) GetAllZonesInfo() ([]SPrivateZone, error) { 113 spvtzs := []SPrivateZone{} 114 szones, err := client.GetAllZones() 115 if err != nil { 116 return nil, errors.Wrap(err, "client.GetAllZones()") 117 } 118 for i := 0; i < len(szones); i++ { 119 spvtz, err := client.DescribeZoneInfo(szones[i].ZoneID) 120 if err != nil { 121 return nil, errors.Wrapf(err, "client.DescribeZoneInfo(%s)", szones[i].ZoneID) 122 } 123 spvtzs = append(spvtzs, *spvtz) 124 } 125 return spvtzs, nil 126 } 127 128 func (client *SAliyunClient) GetPrivateICloudDnsZones() ([]cloudprovider.ICloudDnsZone, error) { 129 izones := []cloudprovider.ICloudDnsZone{} 130 szones, err := client.GetAllZonesInfo() 131 if err != nil { 132 return nil, errors.Wrap(err, "client.GetAllZonesInfo()") 133 } 134 for i := 0; i < len(szones); i++ { 135 izones = append(izones, &szones[i]) 136 } 137 return izones, nil 138 } 139 140 func (client *SAliyunClient) DescribeZoneInfo(zoneId string) (*SPrivateZone, error) { 141 params := map[string]string{} 142 params["Action"] = "DescribeZoneInfo" 143 params["ZoneId"] = zoneId 144 resp, err := client.pvtzRequest("DescribeZoneInfo", params) 145 if err != nil { 146 return nil, errors.Wrap(err, "DescribeZoneInfo") 147 } 148 sZone := &SPrivateZone{client: client} 149 err = resp.Unmarshal(sZone) 150 if err != nil { 151 return nil, errors.Wrap(err, "resp.Unmarshal") 152 } 153 return sZone, nil 154 } 155 156 func (client *SAliyunClient) GetPrivateICloudDnsZoneById(id string) (cloudprovider.ICloudDnsZone, error) { 157 pvtzs, err := client.GetAllZones() 158 if err != nil { 159 return nil, errors.Wrap(err, "client.GetAllZones()") 160 } 161 index := -1 162 for i := 0; i < len(pvtzs); i++ { 163 if pvtzs[i].ZoneID == id { 164 index = i 165 break 166 } 167 } 168 if index < 0 || index >= len(pvtzs) { 169 return nil, cloudprovider.ErrNotFound 170 } 171 izone, err := client.DescribeZoneInfo(id) 172 if err != nil { 173 return nil, errors.Wrapf(err, "client.DescribeZoneInfo(%s)", id) 174 } 175 return izone, nil 176 } 177 178 func (client *SAliyunClient) DeleteZone(zoneId string) error { 179 params := map[string]string{} 180 params["Action"] = "DeleteZone" 181 params["ZoneId"] = zoneId 182 _, err := client.pvtzRequest("DeleteZone", params) 183 if err != nil { 184 return errors.Wrap(err, "DeleteZone") 185 } 186 return nil 187 } 188 189 func (client *SAliyunClient) AddZone(zoneName string) (string, error) { 190 params := map[string]string{} 191 params["Action"] = "AddZone" 192 params["ZoneName"] = zoneName 193 ret, err := client.pvtzRequest("AddZone", params) 194 if err != nil { 195 return "", errors.Wrap(err, "AddZone") 196 } 197 zoneId := "" 198 return zoneId, ret.Unmarshal(&zoneId, "ZoneId") 199 } 200 201 func (client *SAliyunClient) CreateZone(opts *cloudprovider.SDnsZoneCreateOptions) (*SPrivateZone, error) { 202 zoneId, err := client.AddZone(opts.Name) 203 if err != nil { 204 return nil, errors.Wrapf(err, "client.AddZone(%s)", opts.Name) 205 } 206 err = client.BindZoneVpcs(zoneId, opts.Vpcs) 207 if err != nil { 208 return nil, errors.Wrapf(err, " client.BindZoneVpcs(%s,%s)", zoneId, jsonutils.Marshal(opts.Vpcs).String()) 209 } 210 return client.DescribeZoneInfo(zoneId) 211 } 212 213 func (client *SAliyunClient) CreatePrivateICloudDnsZone(opts *cloudprovider.SDnsZoneCreateOptions) (cloudprovider.ICloudDnsZone, error) { 214 izone, err := client.CreateZone(opts) 215 if err != nil { 216 return nil, errors.Wrapf(err, "client.CreateZone(%s)", jsonutils.Marshal(opts).String()) 217 } 218 return izone, nil 219 } 220 221 func (client *SAliyunClient) BindZoneVpc(ZoneId string, vpc *cloudprovider.SPrivateZoneVpc) error { 222 params := map[string]string{} 223 params["Action"] = "BindZoneVpc" 224 params["ZoneId"] = ZoneId 225 params["Vpcs.1.RegionId"] = vpc.RegionId 226 params["Vpcs.1.VpcId"] = vpc.Id 227 _, err := client.pvtzRequest("BindZoneVpc", params) 228 if err != nil { 229 return errors.Wrap(err, "BindZoneVpc") 230 } 231 return nil 232 } 233 234 func (client *SAliyunClient) BindZoneVpcs(zoneId string, vpc []cloudprovider.SPrivateZoneVpc) error { 235 params := map[string]string{} 236 params["Action"] = "BindZoneVpc" 237 params["ZoneId"] = zoneId 238 index := "" 239 for i := 0; i < len(vpc); i++ { 240 index = strconv.Itoa(i + 1) 241 params["Vpcs."+index+".RegionId"] = vpc[i].RegionId 242 params["Vpcs."+index+".VpcId"] = vpc[i].Id 243 } 244 _, err := client.pvtzRequest("BindZoneVpc", params) 245 if err != nil { 246 return errors.Wrap(err, "BindZoneVpc") 247 } 248 return nil 249 } 250 251 func (client *SAliyunClient) UnBindZoneVpcs(zoneId string) error { 252 params := map[string]string{} 253 params["Action"] = "BindZoneVpc" 254 params["ZoneId"] = zoneId 255 _, err := client.pvtzRequest("BindZoneVpc", params) 256 if err != nil { 257 return errors.Wrap(err, "BindZoneVpc") 258 } 259 return nil 260 } 261 262 func (self *SPrivateZone) GetId() string { 263 return self.ZoneID 264 } 265 266 func (self *SPrivateZone) GetName() string { 267 return self.ZoneName 268 } 269 270 func (self *SPrivateZone) GetGlobalId() string { 271 return self.GetId() 272 } 273 274 func (self *SPrivateZone) GetStatus() string { 275 return api.DNS_ZONE_STATUS_AVAILABLE 276 } 277 278 func (self *SPrivateZone) Refresh() error { 279 szone, err := self.client.DescribeZoneInfo(self.ZoneID) 280 if err != nil { 281 return errors.Wrapf(err, "self.client.DescribeZoneInfo(%s)", self.ZoneID) 282 } 283 return jsonutils.Update(self, szone) 284 } 285 286 func (self *SPrivateZone) GetZoneType() cloudprovider.TDnsZoneType { 287 return cloudprovider.PrivateZone 288 } 289 290 func (self *SPrivateZone) GetOptions() *jsonutils.JSONDict { 291 return nil 292 } 293 294 func (self *SPrivateZone) GetICloudVpcIds() ([]string, error) { 295 var ret []string 296 for i := 0; i < len(self.BindVpcs.Vpc); i++ { 297 ret = append(ret, self.BindVpcs.Vpc[i].VpcID) 298 } 299 return ret, nil 300 } 301 302 func (self *SPrivateZone) AddVpc(vpc *cloudprovider.SPrivateZoneVpc) error { 303 vpcs := []cloudprovider.SPrivateZoneVpc{} 304 for i := 0; i < len(self.BindVpcs.Vpc); i++ { 305 vpc := cloudprovider.SPrivateZoneVpc{} 306 vpc.Id = self.BindVpcs.Vpc[i].VpcID 307 vpc.RegionId = self.BindVpcs.Vpc[i].RegionID 308 vpcs = append(vpcs, vpc) 309 } 310 vpcs = append(vpcs, *vpc) 311 return self.client.BindZoneVpcs(self.ZoneID, vpcs) 312 } 313 314 func (self *SPrivateZone) RemoveVpc(vpc *cloudprovider.SPrivateZoneVpc) error { 315 vpcs := []cloudprovider.SPrivateZoneVpc{} 316 for i := 0; i < len(self.BindVpcs.Vpc); i++ { 317 newVpc := cloudprovider.SPrivateZoneVpc{} 318 if self.BindVpcs.Vpc[i].VpcID == vpc.Id && self.BindVpcs.Vpc[i].RegionID == vpc.RegionId { 319 continue 320 } 321 newVpc.Id = self.BindVpcs.Vpc[i].VpcID 322 newVpc.RegionId = self.BindVpcs.Vpc[i].RegionID 323 vpcs = append(vpcs, newVpc) 324 } 325 return self.client.BindZoneVpcs(self.ZoneID, vpcs) 326 } 327 328 func (self *SPrivateZone) GetIDnsRecordSets() ([]cloudprovider.ICloudDnsRecordSet, error) { 329 zonerecords, err := self.client.GetAllZoneRecords(self.ZoneID) 330 if err != nil { 331 return nil, errors.Wrapf(err, "self.client.GetAllZoneRecords(%s)", self.ZoneID) 332 } 333 result := []cloudprovider.ICloudDnsRecordSet{} 334 for i := 0; i < len(zonerecords); i++ { 335 zonerecords[i].szone = self 336 result = append(result, &zonerecords[i]) 337 } 338 return result, nil 339 } 340 341 func (self *SPrivateZone) SyncDnsRecordSets(common, add, del, update []cloudprovider.DnsRecordSet) error { 342 for i := 0; i < len(del); i++ { 343 err := self.client.DeleteZoneRecord(del[i].ExternalId) 344 if err != nil { 345 return errors.Wrapf(err, "self.client.DeleteZoneRecord(%s)", del[i].ExternalId) 346 } 347 } 348 349 for i := 0; i < len(add); i++ { 350 recordId, err := self.client.AddZoneRecord(self.ZoneID, add[i]) 351 if err != nil { 352 return errors.Wrapf(err, "self.client.AddZoneRecord(%s,%s)", self.ZoneID, jsonutils.Marshal(add[i]).String()) 353 } 354 if !add[i].Enabled { 355 err = self.client.SetZoneRecordStatus(recordId, "DISABLE") 356 if err != nil { 357 return errors.Wrapf(err, "self.client.SetZoneRecordStatus(%s,%t)", recordId, add[i].Enabled) 358 } 359 } 360 } 361 362 for i := 0; i < len(update); i++ { 363 // ENABLE: 启用解析 DISABLE: 暂停解析 364 status := "ENABLE" 365 if !update[i].Enabled { 366 status = "DISABLE" 367 } 368 err := self.client.SetZoneRecordStatus(update[i].ExternalId, status) 369 if err != nil { 370 return errors.Wrapf(err, "self.client.SetZoneRecordStatus(%s,%t)", update[i].ExternalId, update[i].Enabled) 371 } 372 err = self.client.UpdateZoneRecord(update[i]) 373 if err != nil { 374 return errors.Wrapf(err, "self.client.UpdateZoneRecord(%s)", jsonutils.Marshal(update[i]).String()) 375 } 376 } 377 378 return nil 379 } 380 381 func (self *SPrivateZone) Delete() error { 382 if len(self.BindVpcs.Vpc) > 0 { 383 err := self.client.UnBindZoneVpcs(self.ZoneID) 384 if err != nil { 385 return errors.Wrapf(err, "self.client.UnBindZoneVpcs(%s)", self.ZoneID) 386 } 387 } 388 return self.client.DeleteZone(self.ZoneID) 389 } 390 391 func (self *SPrivateZone) GetDnsProductType() cloudprovider.TDnsProductType { 392 return "" 393 } 394 395 func (self *SPrivateZone) GetProperlyTTL(ttl int64) int64 { 396 if ttl < allowedTtls[0] { 397 return allowedTtls[0] 398 } 399 for i := 0; i < len(allowedTtls)-1; i++ { 400 if ttl > allowedTtls[i] && ttl < allowedTtls[i+1] { 401 return allowedTtls[i] 402 } 403 } 404 return allowedTtls[len(allowedTtls)-1] 405 }