update vultr to use API v2

This commit is contained in:
David Dymko 2021-06-04 16:12:27 -04:00
parent 12bba0b340
commit efe799e215
5 changed files with 164 additions and 129 deletions

4
go.mod
View File

@ -27,7 +27,7 @@ require (
github.com/fatih/structs v1.1.0 // indirect github.com/fatih/structs v1.1.0 // indirect
github.com/ffledgling/pdns-go v0.0.0-20180219074714-524e7daccd99 github.com/ffledgling/pdns-go v0.0.0-20180219074714-524e7daccd99
github.com/golang/sync v0.0.0-20180314180146-1d60e4601c6f 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/gophercloud/gophercloud v0.1.0
github.com/gorilla/mux v1.7.4 // indirect github.com/gorilla/mux v1.7.4 // indirect
github.com/hooklift/gowsdl v0.4.0 github.com/hooklift/gowsdl v0.4.0
@ -53,7 +53,7 @@ require (
github.com/transip/gotransip/v6 v6.6.0 github.com/transip/gotransip/v6 v6.6.0
github.com/ultradns/ultradns-sdk-go v0.0.0-20200616202852-e62052662f60 github.com/ultradns/ultradns-sdk-go v0.0.0-20200616202852-e62052662f60
github.com/vinyldns/go-vinyldns v0.0.0-20200211145900-fe8a3d82e556 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.etcd.io/etcd v0.5.0-alpha.5.0.20200401174654-e694b7bb0875
go.uber.org/ratelimit v0.1.0 go.uber.org/ratelimit v0.1.0
golang.org/x/net v0.0.0-20201224014010-6772e930b67b golang.org/x/net v0.0.0-20201224014010-6772e930b67b

19
go.sum
View File

@ -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.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.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.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= 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 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.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= 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.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 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= 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.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4=
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= 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-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-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= 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.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/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/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/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/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
github.com/nesv/go-dynect v0.6.0 h1:Ow/DiSm4LAISwnFku/FITSQHnU6pBvhQMsUE5Gu6Oq4= 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/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 h1:UbVjBjgJUYGD8MlobEdOR+yTeNqaNa2Gf1/nskVNCSE=
github.com/vinyldns/go-vinyldns v0.0.0-20200211145900-fe8a3d82e556/go.mod h1:RWc47jtnVuQv6+lY3c768WtXCas/Xi+U5UFc5xULmYg= 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/v2 v2.5.1 h1:Bh3G7nqHs0Gv7OQRExfYFppbuscwVKFDK05b8XBYYnQ=
github.com/vultr/govultr v0.4.2/go.mod h1:TUuUizMOFc7z+PNMssb6iGjKjQfpw5arIaOLfocVudQ= 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/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/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= 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-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-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-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-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 h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 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-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-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-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-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 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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/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.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -207,7 +207,7 @@ func main() {
case "vinyldns": case "vinyldns":
p, err = vinyldns.NewVinylDNSProvider(domainFilter, zoneIDFilter, cfg.DryRun) p, err = vinyldns.NewVinylDNSProvider(domainFilter, zoneIDFilter, cfg.DryRun)
case "vultr": case "vultr":
p, err = vultr.NewVultrProvider(domainFilter, cfg.DryRun) p, err = vultr.NewVultrProvider(ctx, domainFilter, cfg.DryRun)
case "ultradns": case "ultradns":
p, err = ultradns.NewUltraDNSProvider(domainFilter, cfg.DryRun) p, err = ultradns.NewUltraDNSProvider(domainFilter, cfg.DryRun)
case "cloudflare": case "cloudflare":

View File

@ -20,11 +20,11 @@ import (
"context" "context"
"fmt" "fmt"
"os" "os"
"strconv"
"strings" "strings"
log "github.com/sirupsen/logrus" 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/endpoint"
"sigs.k8s.io/external-dns/plan" "sigs.k8s.io/external-dns/plan"
@ -51,30 +51,33 @@ type VultrProvider struct {
type VultrChanges struct { type VultrChanges struct {
Action string Action string
ResourceRecordSet govultr.DNSRecord ResourceRecordSet *govultr.DomainRecordReq
} }
// NewVultrProvider initializes a new Vultr BNS based provider // 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") apiKey, ok := os.LookupEnv("VULTR_API_KEY")
if !ok { if !ok {
return nil, fmt.Errorf("no token found") 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)) client.SetUserAgent(fmt.Sprintf("ExternalDNS/%s", client.UserAgent))
provider := &VultrProvider{ p := &VultrProvider{
client: *client, client: *client,
domainFilter: domainFilter, domainFilter: domainFilter,
DryRun: dryRun, DryRun: dryRun,
} }
return provider, nil return p, nil
} }
// Zones returns list of hosted zones // 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) zones, err := p.fetchZones(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
@ -108,34 +111,58 @@ func (p *VultrProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, erro
name = zone.Domain name = zone.Domain
} }
endPointTTL := endpoint.NewEndpointWithTTL(name, r.Type, endpoint.TTL(r.TTL), r.Data) endpoints = append(endpoints, endpoint.NewEndpointWithTTL(name, r.Type, endpoint.TTL(r.TTL), r.Data))
endpoints = append(endpoints, endPointTTL)
} }
} }
} }
return endpoints, nil return endpoints, nil
} }
func (p *VultrProvider) fetchRecords(ctx context.Context, domain string) ([]govultr.DNSRecord, error) { func (p *VultrProvider) fetchRecords(ctx context.Context, domain string) ([]govultr.DomainRecord, error) {
records, err := p.client.DNSRecord.List(ctx, domain) var allRecords []govultr.DomainRecord
if err != nil { listOptions := &govultr.ListOptions{}
return nil, err
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) { func (p *VultrProvider) fetchZones(ctx context.Context) ([]govultr.Domain, error) {
var zones []govultr.DNSDomain var zones []govultr.Domain
listOptions := &govultr.ListOptions{}
allZones, err := p.client.DNSDomain.List(ctx) for {
if err != nil { allZones, meta, err := p.client.Domain.List(ctx, listOptions)
return nil, err if err != nil {
} return nil, err
}
for _, zone := range allZones { for _, zone := range allZones {
if p.domainFilter.Match(zone.Domain) { if p.domainFilter.Match(zone.Domain) {
zones = append(zones, zone) 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 return err
} }
zoneChanges := seperateChangesByZone(zones, changes) zoneChanges := separateChangesByZone(zones, changes)
for zoneName, changes := range zoneChanges { for zoneName, changes := range zoneChanges {
for _, change := range changes { for _, change := range changes {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"record": change.ResourceRecordSet.Name, "record": change.ResourceRecordSet.Name,
"type": change.ResourceRecordSet.Type, "type": change.ResourceRecordSet.Type,
"ttl": change.ResourceRecordSet.TTL, "ttl": change.ResourceRecordSet.TTL,
"priority": change.ResourceRecordSet.Priority, "action": change.Action,
"action": change.Action, "zone": zoneName,
"zone": zoneName,
}).Info("Changing record.") }).Info("Changing record.")
switch change.Action { switch change.Action {
case vultrCreate: case vultrCreate:
priority := getPriority(change.ResourceRecordSet.Priority) if _, err := p.client.DomainRecord.Create(ctx, zoneName, change.ResourceRecordSet); err != nil {
err = p.client.DNSRecord.Create(ctx, zoneName, change.ResourceRecordSet.Type, change.ResourceRecordSet.Name, change.ResourceRecordSet.Data, change.ResourceRecordSet.TTL, priority)
if err != nil {
return err return err
} }
case vultrDelete: case vultrDelete:
@ -179,8 +203,7 @@ func (p *VultrProvider) submitChanges(ctx context.Context, changes []*VultrChang
return err return err
} }
err = p.client.DNSRecord.Delete(ctx, zoneName, strconv.Itoa(id)) if err := p.client.DomainRecord.Delete(ctx, zoneName, id); err != nil {
if err != nil {
return err return err
} }
case vultrUpdate: case vultrUpdate:
@ -188,17 +211,7 @@ func (p *VultrProvider) submitChanges(ctx context.Context, changes []*VultrChang
if err != nil { if err != nil {
return err return err
} }
if err := p.client.DomainRecord.Update(ctx, zoneName, id, change.ResourceRecordSet); err != nil {
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 {
return err return err
} }
} }
@ -228,19 +241,20 @@ func newVultrChanges(action string, endpoints []*endpoint.Endpoint) []*VultrChan
change := &VultrChanges{ change := &VultrChanges{
Action: action, Action: action,
ResourceRecordSet: govultr.DNSRecord{ ResourceRecordSet: &govultr.DomainRecordReq{
Type: e.RecordType, Type: e.RecordType,
Name: e.DNSName, Name: e.DNSName,
Data: e.Targets[0], Data: e.Targets[0],
TTL: ttl, TTL: ttl,
}, },
} }
changes = append(changes, change) changes = append(changes, change)
} }
return changes 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) change := make(map[string][]*VultrChanges)
zoneNameID := provider.ZoneIDName{} zoneNameID := provider.ZoneIDName{}
@ -260,30 +274,31 @@ func seperateChangesByZone(zones []govultr.DNSDomain, changes []*VultrChanges) m
return change return change
} }
func (p *VultrProvider) getRecordID(ctx context.Context, zone string, record govultr.DNSRecord) (recordID int, err error) { func (p *VultrProvider) getRecordID(ctx context.Context, zone string, record *govultr.DomainRecordReq) (recordID string, err error) {
records, err := p.client.DNSRecord.List(ctx, zone) listOptions := &govultr.ListOptions{}
if err != nil { for {
return 0, err records, meta, err := p.client.DomainRecord.List(ctx, zone, listOptions)
} if err != nil {
return "0", err
for _, r := range records {
strippedName := strings.TrimSuffix(record.Name, "."+zone)
if record.Name == zone {
strippedName = ""
} }
if r.Name == strippedName && r.Type == record.Type { for _, r := range records {
return r.RecordID, nil 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") return "", fmt.Errorf("no record was found")
}
func getPriority(priority *int) int {
p := 0
if priority != nil {
p = *priority
}
return p
} }

View File

@ -24,7 +24,8 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "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/endpoint"
"sigs.k8s.io/external-dns/plan" "sigs.k8s.io/external-dns/plan"
) )
@ -33,63 +34,84 @@ type mockVultrDomain struct {
client *govultr.Client client *govultr.Client
} }
func (m *mockVultrDomain) Create(ctx context.Context, domain, InstanceIP string) error { func (m mockVultrDomain) Create(ctx context.Context, domainReq *govultr.DomainReq) (*govultr.Domain, 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) {
return nil, nil return nil, nil
} }
func (m *mockVultrDomain) List(ctx context.Context) ([]govultr.DNSDomain, error) { func (m mockVultrDomain) Get(ctx context.Context, domain string) (*govultr.Domain, error) {
return []govultr.DNSDomain{{Domain: "test.com"}}, nil
}
func (m *mockVultrDomain) GetSoa(ctx context.Context, domain string) (*govultr.Soa, error) {
return nil, nil 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 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 { type mockVultrRecord struct {
client *govultr.Client 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 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 return nil
} }
func (m *mockVultrRecord) List(ctx context.Context, domain string) ([]govultr.DNSRecord, error) { func (m mockVultrRecord) List(ctx context.Context, domain string, options *govultr.ListOptions) ([]govultr.DomainRecord, *govultr.Meta, error) {
return []govultr.DNSRecord{{RecordID: 123, Type: "A", Name: "test", Data: "192.168.1.1", TTL: 300}}, nil return []govultr.DomainRecord{{ID: "123", Type: "A", Name: "test", Data: "192.168.1.1", TTL: 300}}, &govultr.Meta{
} Total: 1,
Links: &govultr.Links{
func (m *mockVultrRecord) Update(ctx context.Context, domain string, dnsRecord *govultr.DNSRecord) error { Next: "",
return nil Prev: "",
},
}, nil
} }
func TestNewVultrProvider(t *testing.T) { func TestNewVultrProvider(t *testing.T) {
_ = os.Setenv("VULTR_API_KEY", "") _ = 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 { if err != nil {
t.Errorf("failed : %s", err) t.Errorf("failed : %s", err)
} }
_ = os.Unsetenv("VULTR_API_KEY") _ = 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 { if err == nil {
t.Errorf("expected to fail") t.Errorf("expected to fail")
} }
@ -99,18 +121,21 @@ func TestVultrProvider_Zones(t *testing.T) {
mocked := mockVultrDomain{nil} mocked := mockVultrDomain{nil}
provider := &VultrProvider{ provider := &VultrProvider{
client: govultr.Client{ 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
provider.Zones(context.Background())
zones, err := provider.Zones(context.Background()) zones, err := provider.Zones(context.Background())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if !reflect.DeepEqual(expected, zones) { if !reflect.DeepEqual(expected, zones) {
t.Fatal(err) t.Fatal(err)
} }
@ -122,12 +147,12 @@ func TestVultrProvider_Records(t *testing.T) {
provider := &VultrProvider{ provider := &VultrProvider{
client: govultr.Client{ client: govultr.Client{
DNSRecord: &mocked, DomainRecord: &mocked,
DNSDomain: &mockedDomain, 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()) records, err := provider.Records(context.Background())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -138,7 +163,6 @@ func TestVultrProvider_Records(t *testing.T) {
assert.Equal(t, v.RecordType, expected[0].Type) assert.Equal(t, v.RecordType, expected[0].Type)
assert.Equal(t, int(v.RecordTTL), expected[0].TTL) assert.Equal(t, int(v.RecordTTL), expected[0].TTL)
} }
} }
func TestVultrProvider_ApplyChanges(t *testing.T) { func TestVultrProvider_ApplyChanges(t *testing.T) {
@ -148,8 +172,8 @@ func TestVultrProvider_ApplyChanges(t *testing.T) {
provider := &VultrProvider{ provider := &VultrProvider{
client: govultr.Client{ client: govultr.Client{
DNSRecord: &mocked, DomainRecord: &mocked,
DNSDomain: &mockedDomain, Domain: &mockedDomain,
}, },
} }
@ -172,20 +196,19 @@ func TestVultrProvider_getRecordID(t *testing.T) {
provider := &VultrProvider{ provider := &VultrProvider{
client: govultr.Client{ client: govultr.Client{
DNSRecord: &mocked, DomainRecord: &mocked,
DNSDomain: &mockedDomain, Domain: &mockedDomain,
}, },
} }
record := govultr.DNSRecord{ record := &govultr.DomainRecordReq{
RecordID: 123, Type: "A",
Type: "A", Name: "test.test.com",
Name: "test.test.com",
} }
id, err := provider.getRecordID(context.Background(), "test.com", record) id, err := provider.getRecordID(context.Background(), "test.com", record)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
assert.Equal(t, id, record.RecordID) assert.Equal(t, id, "123")
} }