mirror of
				https://github.com/kubernetes-sigs/external-dns.git
				synced 2025-11-03 20:21:23 +01:00 
			
		
		
		
	Merge pull request #2121 from ddymko/vultr-v2-updates
Vultr : Update vultr provider to use API v2
This commit is contained in:
		
						commit
						ab91b0c866
					
				
							
								
								
									
										4
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.mod
									
									
									
									
									
								
							@ -27,7 +27,7 @@ require (
 | 
			
		||||
	github.com/fatih/structs v1.1.0 // indirect
 | 
			
		||||
	github.com/ffledgling/pdns-go v0.0.0-20180219074714-524e7daccd99
 | 
			
		||||
	github.com/golang/sync v0.0.0-20180314180146-1d60e4601c6f
 | 
			
		||||
	github.com/google/go-cmp v0.4.1
 | 
			
		||||
	github.com/google/go-cmp v0.5.2
 | 
			
		||||
	github.com/gophercloud/gophercloud v0.1.0
 | 
			
		||||
	github.com/gorilla/mux v1.7.4 // indirect
 | 
			
		||||
	github.com/hooklift/gowsdl v0.4.0
 | 
			
		||||
@ -53,7 +53,7 @@ require (
 | 
			
		||||
	github.com/transip/gotransip/v6 v6.6.0
 | 
			
		||||
	github.com/ultradns/ultradns-sdk-go v0.0.0-20200616202852-e62052662f60
 | 
			
		||||
	github.com/vinyldns/go-vinyldns v0.0.0-20200211145900-fe8a3d82e556
 | 
			
		||||
	github.com/vultr/govultr v0.4.2
 | 
			
		||||
	github.com/vultr/govultr/v2 v2.5.1
 | 
			
		||||
	go.etcd.io/etcd v0.5.0-alpha.5.0.20200401174654-e694b7bb0875
 | 
			
		||||
	go.uber.org/ratelimit v0.1.0
 | 
			
		||||
	golang.org/x/net v0.0.0-20201224014010-6772e930b67b
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										19
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								go.sum
									
									
									
									
									
								
							@ -390,10 +390,11 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
 | 
			
		||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 | 
			
		||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 | 
			
		||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
			
		||||
github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
 | 
			
		||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
			
		||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
 | 
			
		||||
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
 | 
			
		||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
			
		||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
 | 
			
		||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
 | 
			
		||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
 | 
			
		||||
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
 | 
			
		||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 | 
			
		||||
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
 | 
			
		||||
@ -464,8 +465,8 @@ github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:
 | 
			
		||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
 | 
			
		||||
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
 | 
			
		||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
 | 
			
		||||
github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
 | 
			
		||||
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
 | 
			
		||||
github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4=
 | 
			
		||||
github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
 | 
			
		||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
 | 
			
		||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
 | 
			
		||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
 | 
			
		||||
@ -639,7 +640,6 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
 | 
			
		||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
 | 
			
		||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
 | 
			
		||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
 | 
			
		||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
 | 
			
		||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
 | 
			
		||||
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
 | 
			
		||||
github.com/nesv/go-dynect v0.6.0 h1:Ow/DiSm4LAISwnFku/FITSQHnU6pBvhQMsUE5Gu6Oq4=
 | 
			
		||||
@ -870,8 +870,8 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
 | 
			
		||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
 | 
			
		||||
github.com/vinyldns/go-vinyldns v0.0.0-20200211145900-fe8a3d82e556 h1:UbVjBjgJUYGD8MlobEdOR+yTeNqaNa2Gf1/nskVNCSE=
 | 
			
		||||
github.com/vinyldns/go-vinyldns v0.0.0-20200211145900-fe8a3d82e556/go.mod h1:RWc47jtnVuQv6+lY3c768WtXCas/Xi+U5UFc5xULmYg=
 | 
			
		||||
github.com/vultr/govultr v0.4.2 h1:9i8xKZ+xp6vwZ9raqHoBLzhB4wCnMj7nOQTj5YIRLWY=
 | 
			
		||||
github.com/vultr/govultr v0.4.2/go.mod h1:TUuUizMOFc7z+PNMssb6iGjKjQfpw5arIaOLfocVudQ=
 | 
			
		||||
github.com/vultr/govultr/v2 v2.5.1 h1:Bh3G7nqHs0Gv7OQRExfYFppbuscwVKFDK05b8XBYYnQ=
 | 
			
		||||
github.com/vultr/govultr/v2 v2.5.1/go.mod h1:BvOhVe6/ZpjwcoL6/unkdQshmbS9VGbowI4QT+3DGVU=
 | 
			
		||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
 | 
			
		||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
 | 
			
		||||
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
 | 
			
		||||
@ -1006,7 +1006,6 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
 | 
			
		||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
			
		||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 | 
			
		||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 | 
			
		||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
 | 
			
		||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 | 
			
		||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
 | 
			
		||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
			
		||||
@ -1064,11 +1063,9 @@ golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7w
 | 
			
		||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
 | 
			
		||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
 | 
			
		||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
 | 
			
		||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
			
		||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
			
		||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								main.go
									
									
									
									
									
								
							@ -207,7 +207,7 @@ func main() {
 | 
			
		||||
	case "vinyldns":
 | 
			
		||||
		p, err = vinyldns.NewVinylDNSProvider(domainFilter, zoneIDFilter, cfg.DryRun)
 | 
			
		||||
	case "vultr":
 | 
			
		||||
		p, err = vultr.NewVultrProvider(domainFilter, cfg.DryRun)
 | 
			
		||||
		p, err = vultr.NewVultrProvider(ctx, domainFilter, cfg.DryRun)
 | 
			
		||||
	case "ultradns":
 | 
			
		||||
		p, err = ultradns.NewUltraDNSProvider(domainFilter, cfg.DryRun)
 | 
			
		||||
	case "cloudflare":
 | 
			
		||||
 | 
			
		||||
@ -20,11 +20,11 @@ import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
	"github.com/vultr/govultr"
 | 
			
		||||
	"github.com/vultr/govultr/v2"
 | 
			
		||||
	"golang.org/x/oauth2"
 | 
			
		||||
 | 
			
		||||
	"sigs.k8s.io/external-dns/endpoint"
 | 
			
		||||
	"sigs.k8s.io/external-dns/plan"
 | 
			
		||||
@ -51,30 +51,33 @@ type VultrProvider struct {
 | 
			
		||||
type VultrChanges struct {
 | 
			
		||||
	Action string
 | 
			
		||||
 | 
			
		||||
	ResourceRecordSet govultr.DNSRecord
 | 
			
		||||
	ResourceRecordSet *govultr.DomainRecordReq
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewVultrProvider initializes a new Vultr BNS based provider
 | 
			
		||||
func NewVultrProvider(domainFilter endpoint.DomainFilter, dryRun bool) (*VultrProvider, error) {
 | 
			
		||||
func NewVultrProvider(ctx context.Context, domainFilter endpoint.DomainFilter, dryRun bool) (*VultrProvider, error) {
 | 
			
		||||
	apiKey, ok := os.LookupEnv("VULTR_API_KEY")
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, fmt.Errorf("no token found")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	client := govultr.NewClient(nil, apiKey)
 | 
			
		||||
	oauthClient := oauth2.NewClient(ctx, oauth2.StaticTokenSource(&oauth2.Token{
 | 
			
		||||
		AccessToken: apiKey,
 | 
			
		||||
	}))
 | 
			
		||||
	client := govultr.NewClient(oauthClient)
 | 
			
		||||
	client.SetUserAgent(fmt.Sprintf("ExternalDNS/%s", client.UserAgent))
 | 
			
		||||
 | 
			
		||||
	provider := &VultrProvider{
 | 
			
		||||
	p := &VultrProvider{
 | 
			
		||||
		client:       *client,
 | 
			
		||||
		domainFilter: domainFilter,
 | 
			
		||||
		DryRun:       dryRun,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return provider, nil
 | 
			
		||||
	return p, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Zones returns list of hosted zones
 | 
			
		||||
func (p *VultrProvider) Zones(ctx context.Context) ([]govultr.DNSDomain, error) {
 | 
			
		||||
func (p *VultrProvider) Zones(ctx context.Context) ([]govultr.Domain, error) {
 | 
			
		||||
	zones, err := p.fetchZones(ctx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
@ -108,34 +111,58 @@ func (p *VultrProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, erro
 | 
			
		||||
					name = zone.Domain
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				endPointTTL := endpoint.NewEndpointWithTTL(name, r.Type, endpoint.TTL(r.TTL), r.Data)
 | 
			
		||||
				endpoints = append(endpoints, endPointTTL)
 | 
			
		||||
				endpoints = append(endpoints, endpoint.NewEndpointWithTTL(name, r.Type, endpoint.TTL(r.TTL), r.Data))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return endpoints, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *VultrProvider) fetchRecords(ctx context.Context, domain string) ([]govultr.DNSRecord, error) {
 | 
			
		||||
	records, err := p.client.DNSRecord.List(ctx, domain)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
func (p *VultrProvider) fetchRecords(ctx context.Context, domain string) ([]govultr.DomainRecord, error) {
 | 
			
		||||
	var allRecords []govultr.DomainRecord
 | 
			
		||||
	listOptions := &govultr.ListOptions{}
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		records, meta, err := p.client.DomainRecord.List(ctx, domain, listOptions)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		allRecords = append(allRecords, records...)
 | 
			
		||||
 | 
			
		||||
		if meta.Links.Next == "" {
 | 
			
		||||
			break
 | 
			
		||||
		} else {
 | 
			
		||||
			listOptions.Cursor = meta.Links.Next
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return records, nil
 | 
			
		||||
	return allRecords, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *VultrProvider) fetchZones(ctx context.Context) ([]govultr.DNSDomain, error) {
 | 
			
		||||
	var zones []govultr.DNSDomain
 | 
			
		||||
func (p *VultrProvider) fetchZones(ctx context.Context) ([]govultr.Domain, error) {
 | 
			
		||||
	var zones []govultr.Domain
 | 
			
		||||
	listOptions := &govultr.ListOptions{}
 | 
			
		||||
 | 
			
		||||
	allZones, err := p.client.DNSDomain.List(ctx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	for {
 | 
			
		||||
		allZones, meta, err := p.client.Domain.List(ctx, listOptions)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	for _, zone := range allZones {
 | 
			
		||||
		if p.domainFilter.Match(zone.Domain) {
 | 
			
		||||
			zones = append(zones, zone)
 | 
			
		||||
		for _, zone := range allZones {
 | 
			
		||||
			if p.domainFilter.Match(zone.Domain) {
 | 
			
		||||
				zones = append(zones, zone)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if meta.Links.Next == "" {
 | 
			
		||||
			break
 | 
			
		||||
		} else {
 | 
			
		||||
			listOptions.Cursor = meta.Links.Next
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -153,24 +180,21 @@ func (p *VultrProvider) submitChanges(ctx context.Context, changes []*VultrChang
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	zoneChanges := seperateChangesByZone(zones, changes)
 | 
			
		||||
	zoneChanges := separateChangesByZone(zones, changes)
 | 
			
		||||
 | 
			
		||||
	for zoneName, changes := range zoneChanges {
 | 
			
		||||
		for _, change := range changes {
 | 
			
		||||
			log.WithFields(log.Fields{
 | 
			
		||||
				"record":   change.ResourceRecordSet.Name,
 | 
			
		||||
				"type":     change.ResourceRecordSet.Type,
 | 
			
		||||
				"ttl":      change.ResourceRecordSet.TTL,
 | 
			
		||||
				"priority": change.ResourceRecordSet.Priority,
 | 
			
		||||
				"action":   change.Action,
 | 
			
		||||
				"zone":     zoneName,
 | 
			
		||||
				"record": change.ResourceRecordSet.Name,
 | 
			
		||||
				"type":   change.ResourceRecordSet.Type,
 | 
			
		||||
				"ttl":    change.ResourceRecordSet.TTL,
 | 
			
		||||
				"action": change.Action,
 | 
			
		||||
				"zone":   zoneName,
 | 
			
		||||
			}).Info("Changing record.")
 | 
			
		||||
 | 
			
		||||
			switch change.Action {
 | 
			
		||||
			case vultrCreate:
 | 
			
		||||
				priority := getPriority(change.ResourceRecordSet.Priority)
 | 
			
		||||
				err = p.client.DNSRecord.Create(ctx, zoneName, change.ResourceRecordSet.Type, change.ResourceRecordSet.Name, change.ResourceRecordSet.Data, change.ResourceRecordSet.TTL, priority)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
				if _, err := p.client.DomainRecord.Create(ctx, zoneName, change.ResourceRecordSet); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			case vultrDelete:
 | 
			
		||||
@ -179,8 +203,7 @@ func (p *VultrProvider) submitChanges(ctx context.Context, changes []*VultrChang
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				err = p.client.DNSRecord.Delete(ctx, zoneName, strconv.Itoa(id))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
				if err := p.client.DomainRecord.Delete(ctx, zoneName, id); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			case vultrUpdate:
 | 
			
		||||
@ -188,17 +211,7 @@ func (p *VultrProvider) submitChanges(ctx context.Context, changes []*VultrChang
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				record := &govultr.DNSRecord{
 | 
			
		||||
					RecordID: id,
 | 
			
		||||
					Type:     change.ResourceRecordSet.Type,
 | 
			
		||||
					Name:     change.ResourceRecordSet.Name,
 | 
			
		||||
					Data:     change.ResourceRecordSet.Data,
 | 
			
		||||
					TTL:      change.ResourceRecordSet.TTL,
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				err = p.client.DNSRecord.Update(ctx, zoneName, record)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
				if err := p.client.DomainRecord.Update(ctx, zoneName, id, change.ResourceRecordSet); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
@ -228,19 +241,20 @@ func newVultrChanges(action string, endpoints []*endpoint.Endpoint) []*VultrChan
 | 
			
		||||
 | 
			
		||||
		change := &VultrChanges{
 | 
			
		||||
			Action: action,
 | 
			
		||||
			ResourceRecordSet: govultr.DNSRecord{
 | 
			
		||||
			ResourceRecordSet: &govultr.DomainRecordReq{
 | 
			
		||||
				Type: e.RecordType,
 | 
			
		||||
				Name: e.DNSName,
 | 
			
		||||
				Data: e.Targets[0],
 | 
			
		||||
				TTL:  ttl,
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		changes = append(changes, change)
 | 
			
		||||
	}
 | 
			
		||||
	return changes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func seperateChangesByZone(zones []govultr.DNSDomain, changes []*VultrChanges) map[string][]*VultrChanges {
 | 
			
		||||
func separateChangesByZone(zones []govultr.Domain, changes []*VultrChanges) map[string][]*VultrChanges {
 | 
			
		||||
	change := make(map[string][]*VultrChanges)
 | 
			
		||||
	zoneNameID := provider.ZoneIDName{}
 | 
			
		||||
 | 
			
		||||
@ -260,30 +274,31 @@ func seperateChangesByZone(zones []govultr.DNSDomain, changes []*VultrChanges) m
 | 
			
		||||
	return change
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *VultrProvider) getRecordID(ctx context.Context, zone string, record govultr.DNSRecord) (recordID int, err error) {
 | 
			
		||||
	records, err := p.client.DNSRecord.List(ctx, zone)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, r := range records {
 | 
			
		||||
		strippedName := strings.TrimSuffix(record.Name, "."+zone)
 | 
			
		||||
		if record.Name == zone {
 | 
			
		||||
			strippedName = ""
 | 
			
		||||
func (p *VultrProvider) getRecordID(ctx context.Context, zone string, record *govultr.DomainRecordReq) (recordID string, err error) {
 | 
			
		||||
	listOptions := &govultr.ListOptions{}
 | 
			
		||||
	for {
 | 
			
		||||
		records, meta, err := p.client.DomainRecord.List(ctx, zone, listOptions)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "0", err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if r.Name == strippedName && r.Type == record.Type {
 | 
			
		||||
			return r.RecordID, nil
 | 
			
		||||
		for _, r := range records {
 | 
			
		||||
			strippedName := strings.TrimSuffix(record.Name, "."+zone)
 | 
			
		||||
			if record.Name == zone {
 | 
			
		||||
				strippedName = ""
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if r.Name == strippedName && r.Type == record.Type {
 | 
			
		||||
				return r.ID, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if meta.Links.Next == "" {
 | 
			
		||||
			break
 | 
			
		||||
		} else {
 | 
			
		||||
			listOptions.Cursor = meta.Links.Next
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0, fmt.Errorf("no record was found")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getPriority(priority *int) int {
 | 
			
		||||
	p := 0
 | 
			
		||||
	if priority != nil {
 | 
			
		||||
		p = *priority
 | 
			
		||||
	}
 | 
			
		||||
	return p
 | 
			
		||||
	return "", fmt.Errorf("no record was found")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,8 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
	"github.com/vultr/govultr"
 | 
			
		||||
	"github.com/vultr/govultr/v2"
 | 
			
		||||
 | 
			
		||||
	"sigs.k8s.io/external-dns/endpoint"
 | 
			
		||||
	"sigs.k8s.io/external-dns/plan"
 | 
			
		||||
)
 | 
			
		||||
@ -33,63 +34,84 @@ type mockVultrDomain struct {
 | 
			
		||||
	client *govultr.Client
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *mockVultrDomain) Create(ctx context.Context, domain, InstanceIP string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *mockVultrDomain) Delete(ctx context.Context, domain string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *mockVultrDomain) ToggleDNSSec(ctx context.Context, domain string, enabled bool) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *mockVultrDomain) DNSSecInfo(ctx context.Context, domain string) ([]string, error) {
 | 
			
		||||
func (m mockVultrDomain) Create(ctx context.Context, domainReq *govultr.DomainReq) (*govultr.Domain, error) {
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *mockVultrDomain) List(ctx context.Context) ([]govultr.DNSDomain, error) {
 | 
			
		||||
	return []govultr.DNSDomain{{Domain: "test.com"}}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *mockVultrDomain) GetSoa(ctx context.Context, domain string) (*govultr.Soa, error) {
 | 
			
		||||
func (m mockVultrDomain) Get(ctx context.Context, domain string) (*govultr.Domain, error) {
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *mockVultrDomain) UpdateSoa(ctx context.Context, domain, nsPrimary, email string) error {
 | 
			
		||||
func (m mockVultrDomain) Update(ctx context.Context, domain, dnsSec string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m mockVultrDomain) Delete(ctx context.Context, domain string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m mockVultrDomain) List(ctx context.Context, options *govultr.ListOptions) ([]govultr.Domain, *govultr.Meta, error) {
 | 
			
		||||
	return []govultr.Domain{{Domain: "test.com", DateCreated: "1234"}}, &govultr.Meta{
 | 
			
		||||
		Total: 1,
 | 
			
		||||
		Links: &govultr.Links{
 | 
			
		||||
			Next: "",
 | 
			
		||||
			Prev: "",
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m mockVultrDomain) GetSoa(ctx context.Context, domain string) (*govultr.Soa, error) {
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m mockVultrDomain) UpdateSoa(ctx context.Context, domain string, soaReq *govultr.Soa) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m mockVultrDomain) GetDNSSec(ctx context.Context, domain string) ([]string, error) {
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
type mockVultrRecord struct {
 | 
			
		||||
	client *govultr.Client
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *mockVultrRecord) Create(ctx context.Context, domain, recordType, name, data string, ttl, priority int) error {
 | 
			
		||||
func (m mockVultrRecord) Create(ctx context.Context, domain string, domainRecordReq *govultr.DomainRecordReq) (*govultr.DomainRecord, error) {
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m mockVultrRecord) Get(ctx context.Context, domain, recordID string) (*govultr.DomainRecord, error) {
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m mockVultrRecord) Update(ctx context.Context, domain, recordID string, domainRecordReq *govultr.DomainRecordReq) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *mockVultrRecord) Delete(ctx context.Context, domain, recordID string) error {
 | 
			
		||||
func (m mockVultrRecord) Delete(ctx context.Context, domain, recordID string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *mockVultrRecord) List(ctx context.Context, domain string) ([]govultr.DNSRecord, error) {
 | 
			
		||||
	return []govultr.DNSRecord{{RecordID: 123, Type: "A", Name: "test", Data: "192.168.1.1", TTL: 300}}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *mockVultrRecord) Update(ctx context.Context, domain string, dnsRecord *govultr.DNSRecord) error {
 | 
			
		||||
	return nil
 | 
			
		||||
func (m mockVultrRecord) List(ctx context.Context, domain string, options *govultr.ListOptions) ([]govultr.DomainRecord, *govultr.Meta, error) {
 | 
			
		||||
	return []govultr.DomainRecord{{ID: "123", Type: "A", Name: "test", Data: "192.168.1.1", TTL: 300}}, &govultr.Meta{
 | 
			
		||||
		Total: 1,
 | 
			
		||||
		Links: &govultr.Links{
 | 
			
		||||
			Next: "",
 | 
			
		||||
			Prev: "",
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestNewVultrProvider(t *testing.T) {
 | 
			
		||||
	_ = os.Setenv("VULTR_API_KEY", "")
 | 
			
		||||
	_, err := NewVultrProvider(endpoint.NewDomainFilter([]string{"test.vultr.com"}), true)
 | 
			
		||||
	_, err := NewVultrProvider(context.Background(), endpoint.NewDomainFilter([]string{"test.vultr.com"}), true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("failed : %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_ = os.Unsetenv("VULTR_API_KEY")
 | 
			
		||||
	_, err = NewVultrProvider(endpoint.NewDomainFilter([]string{"test.vultr.com"}), true)
 | 
			
		||||
	_, err = NewVultrProvider(context.Background(), endpoint.NewDomainFilter([]string{"test.vultr.com"}), true)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		t.Errorf("expected to fail")
 | 
			
		||||
	}
 | 
			
		||||
@ -99,18 +121,21 @@ func TestVultrProvider_Zones(t *testing.T) {
 | 
			
		||||
	mocked := mockVultrDomain{nil}
 | 
			
		||||
	provider := &VultrProvider{
 | 
			
		||||
		client: govultr.Client{
 | 
			
		||||
			DNSDomain: &mocked,
 | 
			
		||||
			Domain: &mocked,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	expected, err := provider.client.DNSDomain.List(context.Background())
 | 
			
		||||
	expected, _, err := provider.client.Domain.List(context.Background(), nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	provider.Zones(context.Background())
 | 
			
		||||
	zones, err := provider.Zones(context.Background())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !reflect.DeepEqual(expected, zones) {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
@ -122,12 +147,12 @@ func TestVultrProvider_Records(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	provider := &VultrProvider{
 | 
			
		||||
		client: govultr.Client{
 | 
			
		||||
			DNSRecord: &mocked,
 | 
			
		||||
			DNSDomain: &mockedDomain,
 | 
			
		||||
			DomainRecord: &mocked,
 | 
			
		||||
			Domain:       &mockedDomain,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	expected, _ := provider.client.DNSRecord.List(context.Background(), "test.com")
 | 
			
		||||
	expected, _, _ := provider.client.DomainRecord.List(context.Background(), "test.com", nil)
 | 
			
		||||
	records, err := provider.Records(context.Background())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
@ -138,7 +163,6 @@ func TestVultrProvider_Records(t *testing.T) {
 | 
			
		||||
		assert.Equal(t, v.RecordType, expected[0].Type)
 | 
			
		||||
		assert.Equal(t, int(v.RecordTTL), expected[0].TTL)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestVultrProvider_ApplyChanges(t *testing.T) {
 | 
			
		||||
@ -148,8 +172,8 @@ func TestVultrProvider_ApplyChanges(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	provider := &VultrProvider{
 | 
			
		||||
		client: govultr.Client{
 | 
			
		||||
			DNSRecord: &mocked,
 | 
			
		||||
			DNSDomain: &mockedDomain,
 | 
			
		||||
			DomainRecord: &mocked,
 | 
			
		||||
			Domain:       &mockedDomain,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -172,20 +196,19 @@ func TestVultrProvider_getRecordID(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	provider := &VultrProvider{
 | 
			
		||||
		client: govultr.Client{
 | 
			
		||||
			DNSRecord: &mocked,
 | 
			
		||||
			DNSDomain: &mockedDomain,
 | 
			
		||||
			DomainRecord: &mocked,
 | 
			
		||||
			Domain:       &mockedDomain,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	record := govultr.DNSRecord{
 | 
			
		||||
		RecordID: 123,
 | 
			
		||||
		Type:     "A",
 | 
			
		||||
		Name:     "test.test.com",
 | 
			
		||||
	record := &govultr.DomainRecordReq{
 | 
			
		||||
		Type: "A",
 | 
			
		||||
		Name: "test.test.com",
 | 
			
		||||
	}
 | 
			
		||||
	id, err := provider.getRecordID(context.Background(), "test.com", record)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, id, record.RecordID)
 | 
			
		||||
	assert.Equal(t, id, "123")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user