| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- // 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 aws
- import (
- "strings"
- "time"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/stringutils"
- api "yunion.io/x/cloudmux/pkg/apis/compute"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- "yunion.io/x/cloudmux/pkg/multicloud"
- )
- type DnsZoneConfig struct {
- Comment string `xml:"Comment"`
- PrivateZone bool `xml:"PrivateZone"`
- }
- type AssociatedVPC struct {
- VPCId string `xml:"VPCId"`
- VPCRegion string `xml:"VPCRegion"`
- }
- type SDnsZone struct {
- multicloud.SDnsZoneBase
- AwsTags
- client *SAwsClient
- Id string `xml:"Id"`
- Name string `xml:"Name"`
- CallerReference string `xml:"CallerReference"`
- Config DnsZoneConfig `xml:"Config"`
- ResourceRecordSetCount int64 `xml:"ResourceRecordSetCount"`
- locations []GeoLocationDetails
- }
- type SDnsZoneDetails struct {
- HostedZone SDnsZone `xml:"HostedZone"`
- VPC []struct {
- VPCRegion string `xml:"VPCRegion"`
- VPCId string `xml:"VPCId"`
- } `xml:"VPCs>VPC"`
- }
- func (self *SDnsZone) GetId() string {
- return self.Id
- }
- func (self *SDnsZone) GetName() string {
- return strings.TrimSuffix(self.Name, ".")
- }
- func (self *SDnsZone) GetGlobalId() string {
- return self.Id
- }
- func (self *SDnsZone) GetStatus() string {
- return api.DNS_ZONE_STATUS_AVAILABLE
- }
- func (self *SDnsZone) Refresh() error {
- zone, err := self.client.GetDnsZone(self.Id)
- if err != nil {
- return errors.Wrapf(err, "GetDnsZone(%s)", self.Id)
- }
- return jsonutils.Update(self, zone.HostedZone)
- }
- type GeoLocationDetails struct {
- ContinentCode string `xml:"ContinentCode"`
- ContinentName string `xml:"ContinentName"`
- CountryCode string `xml:"CountryCode"`
- CountryName string `xml:"CountryName"`
- SubdivisionCode string `xml:"SubdivisionCode"`
- SubdivisionName string `xml:"SubdivisionName"`
- }
- func (self GeoLocationDetails) GetPolicyValue() cloudprovider.TDnsPolicyValue {
- if len(self.SubdivisionName) > 0 {
- return cloudprovider.TDnsPolicyValue(self.SubdivisionName)
- }
- if len(self.ContinentName) > 0 {
- return cloudprovider.TDnsPolicyValue(self.ContinentName)
- }
- return cloudprovider.TDnsPolicyValue(self.CountryName)
- }
- func (self GeoLocationDetails) equals(lo GeoLocationDetails) bool {
- return self.CountryCode == lo.CountryCode && self.ContinentCode == self.ContinentCode && self.SubdivisionCode == self.SubdivisionCode
- }
- func (client *SAwsClient) ListGeoLocations() ([]GeoLocationDetails, error) {
- ret := []GeoLocationDetails{}
- params := map[string]string{
- "maxitems": "100",
- }
- for {
- part := struct {
- Locations []GeoLocationDetails `xml:"GeoLocationDetailsList>GeoLocationDetails"`
- NextCountryCode string `xml:"NextCountryCode"`
- NextContinentCode string `xml:"NextContinentCode"`
- NextSubdivisionCode string `xml:"NextSubdivisionCode"`
- }{}
- err := client.dnsRequest("ListGeoLocations", params, &part)
- if err != nil {
- return nil, err
- }
- ret = append(ret, part.Locations...)
- if len(part.NextCountryCode) == 0 && len(part.NextContinentCode) == 0 && len(part.NextSubdivisionCode) == 0 {
- break
- }
- for k, v := range map[string]string{
- "startcountrycode": part.NextCountryCode,
- "startcontinentcode": part.NextContinentCode,
- "startsubdivisioncode": part.NextSubdivisionCode,
- } {
- if len(v) > 0 {
- params[k] = v
- }
- }
- }
- return ret, nil
- }
- func (client *SAwsClient) CreateDnsZone(opts *cloudprovider.SDnsZoneCreateOptions) (*SDnsZone, error) {
- params := map[string]string{
- "CallerReference": time.Now().Format(time.RFC3339),
- "HostedZoneConfig.PrivateZone": "true",
- "Name": opts.Name,
- }
- if opts.ZoneType == cloudprovider.PrivateZone {
- params["HostedZoneConfig.PrivateZone"] = "true"
- }
- if len(opts.Desc) > 0 {
- params["HostedZoneConfig.Comment"] = opts.Desc
- }
- for i, vpc := range opts.Vpcs {
- if i == 0 {
- params["VPC.VPCRegion"] = vpc.RegionId
- params["VPC.VPCId"] = vpc.Id
- }
- }
- ret := SDnsZoneDetails{}
- ret.HostedZone.client = client
- err := client.dnsRequest("CreateHostedZone", params, &ret)
- if err != nil {
- return nil, err
- }
- for i, vpc := range opts.Vpcs {
- if i != 0 {
- err = ret.HostedZone.AddVpc(&vpc)
- if err != nil {
- log.Errorf("add vpc %s(%s) error: %v", vpc.Id, vpc.RegionId, err)
- }
- }
- }
- return &ret.HostedZone, nil
- }
- func (client *SAwsClient) DeleteDnsZone(Id string) error {
- params := map[string]string{
- "Id": Id,
- }
- return client.dnsRequest("DeleteHostedZone", params, nil)
- }
- func (client *SAwsClient) CreateICloudDnsZone(opts *cloudprovider.SDnsZoneCreateOptions) (cloudprovider.ICloudDnsZone, error) {
- return client.CreateDnsZone(opts)
- }
- func (client *SAwsClient) GetDnsZones() ([]SDnsZone, error) {
- params := map[string]string{
- "maxitems": "1",
- }
- ret := []SDnsZone{}
- for {
- part := struct {
- DnsZones []SDnsZone `xml:"HostedZones>HostedZone"`
- NextMarker string `xml:"NextMarker"`
- }{}
- err := client.dnsRequest("ListHostedZones", params, &part)
- if err != nil {
- return nil, err
- }
- ret = append(ret, part.DnsZones...)
- if len(part.NextMarker) == 0 {
- break
- }
- params["marker"] = part.NextMarker
- }
- return ret, nil
- }
- func (client *SAwsClient) GetICloudDnsZones() ([]cloudprovider.ICloudDnsZone, error) {
- zones, err := client.GetDnsZones()
- if err != nil {
- return nil, errors.Wrap(err, "GetDnsZones()")
- }
- result := []cloudprovider.ICloudDnsZone{}
- for i := 0; i < len(zones); i++ {
- zones[i].client = client
- result = append(result, &zones[i])
- }
- return result, nil
- }
- func (client *SAwsClient) GetDnsZone(id string) (*SDnsZoneDetails, error) {
- params := map[string]string{"Id": id}
- ret := SDnsZoneDetails{}
- err := client.dnsRequest("GetHostedZone", params, &ret)
- if err != nil {
- return nil, err
- }
- ret.HostedZone.client = client
- return &ret, nil
- }
- func (client *SAwsClient) AssociateVPCWithHostedZone(vpcId string, regionId string, zoneId string) error {
- params := map[string]string{
- "Id": zoneId,
- "VPC.VPCId": vpcId,
- "VPC.VPCRegion": regionId,
- }
- ret := struct{}{}
- return client.dnsRequest("AssociateVPCWithHostedZone", params, &ret)
- }
- func (client *SAwsClient) DisassociateVPCFromHostedZone(vpcId string, regionId string, zoneId string) error {
- params := map[string]string{
- "Id": zoneId,
- "VPC.VPCId": vpcId,
- "VPC.VPCRegion": regionId,
- }
- ret := struct{}{}
- return client.dnsRequest("DisassociateVPCFromHostedZone", params, &ret)
- }
- func (self *SDnsZone) Delete() error {
- records, err := self.client.ListResourceRecordSet(self.Id)
- if err != nil {
- return errors.Wrapf(err, "ListResourceRecordSet")
- }
- for i := range records {
- if records[i].Type == "NS" || records[i].Type == "SOA" {
- continue
- }
- records[i].zone = self
- err = records[i].Delete()
- if err != nil {
- return errors.Wrapf(err, "Delete record %s", records[i].GetGlobalId())
- }
- }
- return self.client.DeleteDnsZone(self.Id)
- }
- func (self *SDnsZone) GetZoneType() cloudprovider.TDnsZoneType {
- if self.Config.PrivateZone {
- return cloudprovider.PrivateZone
- }
- return cloudprovider.PublicZone
- }
- func (self *SDnsZone) GetICloudVpcIds() ([]string, error) {
- zone, err := self.client.GetDnsZone(self.Id)
- if err != nil {
- return nil, err
- }
- ret := []string{}
- for _, vpc := range zone.VPC {
- ret = append(ret, vpc.VPCId)
- }
- return ret, nil
- }
- func (self *SDnsZone) AddVpc(vpc *cloudprovider.SPrivateZoneVpc) error {
- return self.client.AssociateVPCWithHostedZone(vpc.Id, vpc.RegionId, self.Id)
- }
- func (self *SDnsZone) RemoveVpc(vpc *cloudprovider.SPrivateZoneVpc) error {
- return self.client.DisassociateVPCFromHostedZone(vpc.Id, vpc.RegionId, self.Id)
- }
- func (self *SDnsZone) GetIDnsRecords() ([]cloudprovider.ICloudDnsRecord, error) {
- recordSets, err := self.client.ListResourceRecordSet(self.Id)
- if err != nil {
- return nil, errors.Wrapf(err, "ListResourceRecordSet(%s)", self.Id)
- }
- result := []cloudprovider.ICloudDnsRecord{}
- for i := 0; i < len(recordSets); i++ {
- recordSets[i].zone = self
- result = append(result, &recordSets[i])
- }
- return result, nil
- }
- func (self *SDnsZone) GetIDnsRecordById(id string) (cloudprovider.ICloudDnsRecord, error) {
- records, err := self.GetIDnsRecords()
- if err != nil {
- return nil, err
- }
- for i := range records {
- if records[i].GetGlobalId() == id {
- return records[i], nil
- }
- }
- return nil, cloudprovider.ErrNotFound
- }
- func (self *SDnsZone) GetGeoLocations() ([]GeoLocationDetails, error) {
- if len(self.locations) > 0 {
- return self.locations, nil
- }
- var err error
- self.locations, err = self.client.ListGeoLocations()
- return self.locations, err
- }
- func (self *SDnsZone) AddDnsRecord(opts *cloudprovider.DnsRecord) (string, error) {
- name := opts.DnsName
- if len(opts.DnsName) > 1 && opts.DnsName != "@" {
- name = opts.DnsName + "." + self.Name
- }
- id := ""
- if opts.PolicyType != cloudprovider.DnsPolicyTypeSimple {
- id = stringutils.UUID4()
- }
- err := self.client.ChangeResourceRecordSets("CREATE", self.Id, name, id, *opts)
- if err != nil {
- return "", errors.Wrapf(err, "ChangeResourceRecordSets")
- }
- record := &SDnsRecord{Name: name, Type: string(opts.DnsType), SetIdentifier: id}
- record.ResourceRecords = []SResourceRecord{
- {Value: opts.DnsValue},
- }
- record.zone = self
- return record.GetGlobalId(), nil
- }
- func (self *SDnsZone) GetDnsProductType() cloudprovider.TDnsProductType {
- return ""
- }
|