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  }