gandi_v5 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -0
- data/README.md +3 -2
- data/lib/gandi_v5.rb +34 -13
- data/lib/gandi_v5/domain.rb +2 -8
- data/lib/gandi_v5/email/forward.rb +2 -8
- data/lib/gandi_v5/email/mailbox.rb +2 -8
- data/lib/gandi_v5/live_dns.rb +0 -12
- data/lib/gandi_v5/live_dns/domain.rb +313 -29
- data/lib/gandi_v5/live_dns/domain/dnssec_key.rb +115 -0
- data/lib/gandi_v5/live_dns/domain/record.rb +81 -0
- data/lib/gandi_v5/live_dns/domain/snapshot.rb +107 -0
- data/lib/gandi_v5/live_dns/domain/tsig_key.rb +71 -0
- data/lib/gandi_v5/version.rb +1 -1
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/fetch.yml +1 -2
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/list_tsig.yml +3 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/nameservers.yml +3 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_DnssecKey/fetch.yml +12 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_DnssecKey/list.yml +9 -0
- data/spec/fixtures/bodies/{GandiV5_LiveDNS_Zone_Snapshot → GandiV5_LiveDNS_Domain_Snapshot}/fetch.yml +4 -3
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_Snapshot/list.yml +5 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_TsigKey/fetch.yml +9 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_TsigKey/list.yml +4 -0
- data/spec/units/gandi_v5/domain_spec.rb +6 -37
- data/spec/units/gandi_v5/email/forward_spec.rb +5 -34
- data/spec/units/gandi_v5/email/mailbox_spec.rb +4 -34
- data/spec/units/gandi_v5/live_dns/domain/dnssec_key_spec.rb +128 -0
- data/spec/units/gandi_v5/live_dns/{record_set_spec.rb → domain/record_spec.rb} +1 -1
- data/spec/units/gandi_v5/live_dns/domain/snapshot_spec.rb +101 -0
- data/spec/units/gandi_v5/live_dns/domain/tsig_key_spec.rb +78 -0
- data/spec/units/gandi_v5/live_dns/domain_spec.rb +297 -118
- data/spec/units/gandi_v5/live_dns_spec.rb +0 -12
- data/spec/units/gandi_v5_spec.rb +111 -14
- metadata +18 -24
- data/lib/gandi_v5/live_dns/has_zone_records.rb +0 -153
- data/lib/gandi_v5/live_dns/record_set.rb +0 -79
- data/lib/gandi_v5/live_dns/zone.rb +0 -160
- data/lib/gandi_v5/live_dns/zone/snapshot.rb +0 -81
- data/spec/features/domain_spec.rb +0 -45
- data/spec/features/livedns_domain_spec.rb +0 -8
- data/spec/features/livedns_zone_spec.rb +0 -44
- data/spec/features/mailbox_spec.rb +0 -18
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/fetch.yml +0 -11
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/list.yml +0 -11
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/list.yml +0 -3
- data/spec/fixtures/vcr/Domain_features/List_domains.yml +0 -55
- data/spec/fixtures/vcr/Domain_features/Renew_domain.yml +0 -133
- data/spec/fixtures/vcr/LiveDNS_Domain_features/List_domains.yml +0 -32
- data/spec/fixtures/vcr/LiveDNS_Zone_features/List_zones.yml +0 -42
- data/spec/fixtures/vcr/LiveDNS_Zone_features/Make_and_save_snapshot.yml +0 -72
- data/spec/fixtures/vcr/LiveDNS_Zone_features/Save_zone_to_file.yml +0 -28
- data/spec/fixtures/vcr/Mailbox_features/List_mailboxes.yml +0 -39
- data/spec/units/gandi_v5/live_dns/zone/snapshot_spec.rb +0 -66
- data/spec/units/gandi_v5/live_dns/zone_spec.rb +0 -347
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6873be5c700e1ef88075c90b71361bb9568b11661661dd0bc4f7d77cfdefd6f0
|
4
|
+
data.tar.gz: 13aac04c42357193607cff0f55c0502253fb6b527475e40ad5cb5d53011268ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46afb560fe574db5bf9d47e3e5bbce0843acef12edd132e26cba685608e4b1fa2dc1579dc30e287128ef6462924d56c14856168bcc2d277dededbf9360c45d0b
|
7
|
+
data.tar.gz: 9e35714cdb2ad68d57d11f4bdd689a6fc0103d155827682bb6a2f66340e8054af328761827f13e7af857c5c41263568daed84805e20b90e5b580917dea502eab
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
# Gandi V5 API Gem Changelog
|
2
2
|
|
3
|
+
## Version 0.7.0
|
4
|
+
|
5
|
+
* LiveDNS:
|
6
|
+
* Rename LiveDNS::RecordSet to LiveDNS::Domain::Record
|
7
|
+
* Domains:
|
8
|
+
* .list now returns an array of strings
|
9
|
+
* Can no longer change the zone used by a domain
|
10
|
+
* Added automatic_snapshots attribute for whether snapshots are automatically created when a modification is made to this domain's records
|
11
|
+
* #replace_records and #replace_records_for merged into #replace_records
|
12
|
+
* If replacing with a zone file use the new #replace_zone_lines
|
13
|
+
* Added:
|
14
|
+
* .create
|
15
|
+
* .record_types
|
16
|
+
* .generic_name_servers(fqdn)
|
17
|
+
* #name_servers and #fetch_name_servers
|
18
|
+
* #tsig_keys, #fetch_tsig_keys, #add_tsig_key, #remove_tsig_key
|
19
|
+
* #axfr_clients, #fetch_axfr_clients, #add_axfr_client, #remove_axfr_client
|
20
|
+
* ::DnssecKeys, #dnssec_keys, #fetch_dnssec_keys
|
21
|
+
* Snapshots:
|
22
|
+
* Moved to live under LiveDNS::Domain not LiveDNS::Zone
|
23
|
+
* Are now accessed via the fully qualified domain name NOT the zone's UUID
|
24
|
+
* Ability to access the zone from a snapshot is removed
|
25
|
+
* Taking a snapshot now allows for named snapshots
|
26
|
+
* Added automatic attribute for when a snapshot was taken due to a zone change
|
27
|
+
* .list now returns an array of snapshots (records are fetched in a seperate request when first needed)
|
28
|
+
* Zone removed.
|
29
|
+
|
3
30
|
## Version 0.6.0
|
4
31
|
|
5
32
|
* GandiV5::Email::Slot.create now supports sharing_id
|
data/README.md
CHANGED
@@ -36,12 +36,12 @@ Details of the API can be found at:
|
|
36
36
|
If you're using bundler then add it to your Gemfile and run the bundle command.
|
37
37
|
|
38
38
|
```ruby
|
39
|
-
gem 'gandi_v5', '~> 0.
|
39
|
+
gem 'gandi_v5', '~> 0.7'
|
40
40
|
```
|
41
41
|
|
42
42
|
If you're not using bundler then install it from the command line.
|
43
43
|
```bash
|
44
|
-
gem install gandi_v5 -v '~> 0.
|
44
|
+
gem install gandi_v5 -v '~> 0.7'
|
45
45
|
```
|
46
46
|
|
47
47
|
## Usage
|
@@ -77,6 +77,7 @@ We follow the [Semantic Versioning](http://semver.org/) concept.
|
|
77
77
|
|
78
78
|
| Gem Version | Gandi API Release Date |
|
79
79
|
| --------------- | ------------------------ |
|
80
|
+
| 0.7.0 | 2020-05-07 |
|
80
81
|
| 0.6.0 | 2020-05-07 (not LiveDNS) |
|
81
82
|
| 0.5.0 | 2019-10-01 |
|
82
83
|
| 0.4.0 | 2019-10-01 |
|
data/lib/gandi_v5.rb
CHANGED
@@ -82,6 +82,36 @@ class GandiV5
|
|
82
82
|
handle_bad_request(e)
|
83
83
|
end
|
84
84
|
|
85
|
+
# Might raise:
|
86
|
+
# * RestClient::NotFound
|
87
|
+
# * RestClient::Unauthorized
|
88
|
+
# Bad authentication attempt because of a wrong API Key.
|
89
|
+
# * RestClient::Forbidden
|
90
|
+
# Access to the resource is denied.
|
91
|
+
# Mainly due to a lack of permissions to access it.
|
92
|
+
# * GandiV5::Error
|
93
|
+
# * JSON::ParserError
|
94
|
+
def paginated_get(url, page = (1..), per_page = 100, **headers)
|
95
|
+
unless page.respond_to?(:each)
|
96
|
+
fail ArgumentError, 'page must be positive' unless page.positive?
|
97
|
+
|
98
|
+
page = [page]
|
99
|
+
end
|
100
|
+
|
101
|
+
headers[:params] ||= {}
|
102
|
+
headers[:params].transform_keys!(&:to_s)
|
103
|
+
headers[:params]['per_page'] = per_page
|
104
|
+
|
105
|
+
page.each do |page_number|
|
106
|
+
headers[:params]['page'] = page_number
|
107
|
+
_resp, this_data = get(url, **headers)
|
108
|
+
break if this_data.empty?
|
109
|
+
|
110
|
+
yield this_data
|
111
|
+
break if this_data.count < per_page
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
85
115
|
# Might raise:
|
86
116
|
# * RestClient::NotFound
|
87
117
|
# * RestClient::Unauthorized
|
@@ -169,16 +199,6 @@ class GandiV5
|
|
169
199
|
@api_key ||= ENV.fetch('GANDI_API_KEY')
|
170
200
|
end
|
171
201
|
|
172
|
-
def authorisation_header(url)
|
173
|
-
if url.start_with?(BASE)
|
174
|
-
{ Authorization: "Apikey #{api_key}" }
|
175
|
-
elsif url.start_with?(GandiV5::LiveDNS::BASE)
|
176
|
-
{ 'X-Api-Key': api_key }
|
177
|
-
else
|
178
|
-
fail ArgumentError, "Don't know how to authorise for url: #{url}"
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
202
|
def parse_response(response)
|
183
203
|
type = response.headers.fetch(:content_type).split(';').first.chomp
|
184
204
|
case type
|
@@ -196,10 +216,11 @@ class GandiV5
|
|
196
216
|
end
|
197
217
|
end
|
198
218
|
|
199
|
-
def prepare_headers(headers,
|
200
|
-
headers.transform_keys!
|
219
|
+
def prepare_headers(headers, _url)
|
220
|
+
headers.transform_keys! { |key| key.to_s.downcase.to_sym }
|
201
221
|
headers[:accept] ||= 'application/json'
|
202
|
-
headers
|
222
|
+
headers[:authorization] = "Apikey #{api_key}"
|
223
|
+
headers
|
203
224
|
end
|
204
225
|
|
205
226
|
def handle_bad_request(exception)
|
data/lib/gandi_v5/domain.rb
CHANGED
@@ -492,7 +492,7 @@ class GandiV5
|
|
492
492
|
# @param page [#each<Integer, #to_s>] the page(s) of results to retrieve.
|
493
493
|
# If page is not provided keep querying until an empty list is returned.
|
494
494
|
# If page responds to .each then iterate until an empty list is returned.
|
495
|
-
# @param per_page [Integer, #to_s] (optional default 100) how many results
|
495
|
+
# @param per_page [Integer, #to_s] (optional default 100) how many results to get per page.
|
496
496
|
# @param fqdn [String, #to_s] (optional)
|
497
497
|
# filters the list by domain name, with optional patterns.
|
498
498
|
# e.g. "example.net", "example.*", "*ample.com"
|
@@ -501,15 +501,9 @@ class GandiV5
|
|
501
501
|
# @return [Array<GandiV5::Domain>]
|
502
502
|
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
503
503
|
def self.list(page: (1..), per_page: 100, **params)
|
504
|
-
page = [page.to_i] unless page.respond_to?(:each)
|
505
|
-
|
506
504
|
domains = []
|
507
|
-
|
508
|
-
_resp, data = GandiV5.get url, params: params.merge(page: page_number, per_page: per_page)
|
509
|
-
break if data.empty?
|
510
|
-
|
505
|
+
GandiV5.paginated_get(url, page, per_page, params: params) do |data|
|
511
506
|
domains += data.map { |domain| from_gandi domain }
|
512
|
-
break if data.count < per_page
|
513
507
|
end
|
514
508
|
domains
|
515
509
|
end
|
@@ -76,18 +76,12 @@ class GandiV5
|
|
76
76
|
# e.g. ("alice" "*lice", "alic*").
|
77
77
|
# @return [Array<GandiV5::Email::Forward>]
|
78
78
|
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
79
|
-
def self.list(fqdn, page: (1..), **params)
|
80
|
-
page = [page.to_i] unless page.respond_to?(:each)
|
81
|
-
|
79
|
+
def self.list(fqdn, page: (1..), per_page: 100, **params)
|
82
80
|
params.reject! { |_k, v| v.nil? }
|
83
81
|
|
84
82
|
mailboxes = []
|
85
|
-
|
86
|
-
_response, data = GandiV5.get url(fqdn), params: params.merge(page: page_number)
|
87
|
-
break if data.empty?
|
88
|
-
|
83
|
+
GandiV5.paginated_get(url(fqdn), page, per_page, params: params) do |data|
|
89
84
|
mailboxes += data.map { |mailbox| from_gandi mailbox.merge(fqdn: fqdn) }
|
90
|
-
break if data.count < params.fetch(:per_page, 100)
|
91
85
|
end
|
92
86
|
mailboxes
|
93
87
|
end
|
@@ -197,19 +197,13 @@ class GandiV5
|
|
197
197
|
# e.g. ("alice" "*lice", "alic*").
|
198
198
|
# @return [Array<GandiV5::Email::Mailbox>]
|
199
199
|
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
200
|
-
def self.list(fqdn, page: (1..), **params)
|
201
|
-
page = [page.to_i] unless page.respond_to?(:each)
|
202
|
-
|
200
|
+
def self.list(fqdn, page: (1..), per_page: 100, **params)
|
203
201
|
params['~login'] = params.delete(:login)
|
204
202
|
params.reject! { |_k, v| v.nil? }
|
205
203
|
|
206
204
|
mailboxes = []
|
207
|
-
|
208
|
-
_response, data = GandiV5.get url(fqdn), params: params.merge(page: page_number)
|
209
|
-
break if data.empty?
|
210
|
-
|
205
|
+
GandiV5.paginated_get(url(fqdn), page, per_page, params: params) do |data|
|
211
206
|
mailboxes += data.map { |mailbox| from_gandi mailbox }
|
212
|
-
break if data.count < params.fetch(:per_page, 100)
|
213
207
|
end
|
214
208
|
mailboxes
|
215
209
|
end
|
data/lib/gandi_v5/live_dns.rb
CHANGED
@@ -4,8 +4,6 @@
|
|
4
4
|
class GandiV5
|
5
5
|
# Gandi LiveDNS Management API.
|
6
6
|
class LiveDNS
|
7
|
-
BASE = 'https://dns.api.gandi.net/api/v5/'
|
8
|
-
|
9
7
|
RECORD_TYPES = %w[
|
10
8
|
A AAAA CNAME MX NS TXT ALIAS
|
11
9
|
WKS SRV LOC SPF CAA DS SSHFP PTR KEY DNAME TLSA OPENPGPKEY CDS
|
@@ -21,16 +19,6 @@ class GandiV5
|
|
21
19
|
GandiV5::LiveDNS::Domain.list
|
22
20
|
end
|
23
21
|
|
24
|
-
# @see GandiV5::LiveDNS::Zone.fetch
|
25
|
-
def self.zone(uuid)
|
26
|
-
GandiV5::LiveDNS::Zone.fetch(uuid)
|
27
|
-
end
|
28
|
-
|
29
|
-
# @see GandiV5::LiveDNS::Zone.list
|
30
|
-
def self.zones
|
31
|
-
GandiV5::LiveDNS::Zone.list
|
32
|
-
end
|
33
|
-
|
34
22
|
# Raise an error if passed type is invalid.
|
35
23
|
# @param type [String] the record type to check.
|
36
24
|
# @return [nil]
|
@@ -5,19 +5,12 @@ class GandiV5
|
|
5
5
|
# A domain name within the LiveDNS system.
|
6
6
|
# @!attribute [r] fqdn
|
7
7
|
# @return [String]
|
8
|
-
# @!attribute [r]
|
9
|
-
# @return [
|
8
|
+
# @!attribute [r] automatic_snapshots
|
9
|
+
# @return [Boolean]
|
10
10
|
class Domain
|
11
11
|
include GandiV5::Data
|
12
|
-
include GandiV5::LiveDNS::HasZoneRecords
|
13
|
-
|
14
|
-
members :fqdn
|
15
12
|
|
16
|
-
|
17
|
-
:zone_uuid,
|
18
|
-
gandi_key: 'zone',
|
19
|
-
converter: GandiV5::Data::Converter.new(from_gandi: ->(zone) { zone&.split('/')&.last })
|
20
|
-
)
|
13
|
+
members :fqdn, :automatic_snapshots
|
21
14
|
|
22
15
|
# Refetch the information for this domain from Gandi.
|
23
16
|
# @return [GandiV5::LiveDNS::Domain]
|
@@ -27,35 +20,283 @@ class GandiV5
|
|
27
20
|
from_gandi data
|
28
21
|
end
|
29
22
|
|
30
|
-
#
|
31
|
-
# @param
|
23
|
+
# Update this domain's settings.
|
24
|
+
# @param automatic_snapshots [String, #to_s]
|
25
|
+
# Enable or disable the automatic creation of new snapshots when records are changed.
|
32
26
|
# @return [String] The confirmation message from Gandi.
|
33
27
|
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
self.zone_uuid = uuid
|
28
|
+
def update(automatic_snapshots:)
|
29
|
+
_response, data = GandiV5.patch url, { automatic_snapshots: automatic_snapshots }.to_json
|
30
|
+
self.automatic_snapshots = automatic_snapshots
|
38
31
|
data['message']
|
39
32
|
end
|
40
33
|
|
41
|
-
# @
|
42
|
-
|
43
|
-
|
34
|
+
# @overload fetch_records()
|
35
|
+
# Fetch all records for this domain.
|
36
|
+
# @param page [Integer, #each<Integer>] which page(s) of results to get.
|
37
|
+
# If page is not provided keep querying until an empty list is returned.
|
38
|
+
# If page responds to .each then iterate until an empty list is returned.
|
39
|
+
# @param per_page [Integer, #to_s] (optional default 100) how many results ot get per page.
|
40
|
+
# @overload fetch_records(name)
|
41
|
+
# Fetch records for a name.
|
42
|
+
# @param name [String] the name to fetch records for.
|
43
|
+
# @param page [Integer, #each<Integer>] which page(s) of results to get.
|
44
|
+
# If page is not provided keep querying until an empty list is returned.
|
45
|
+
# If page responds to .each then iterate until an empty list is returned.
|
46
|
+
# @param per_page [Integer, #to_s] (optional default 100) how many results ot get per page.
|
47
|
+
# @overload fetch_records(name, type)
|
48
|
+
# Fetch records of a type for a name.
|
49
|
+
# @param name [String] the name to fetch records for.
|
50
|
+
# @param type [String] the record type to fetch.
|
51
|
+
# @param page [Integer, #each<Integer>] which page(s) of results to get.
|
52
|
+
# If page is not provided keep querying until an empty list is returned.
|
53
|
+
# If page responds to .each then iterate until an empty list is returned.
|
54
|
+
# @param per_page [Integer, #to_s] (optional default 100) how many results ot get per page.
|
55
|
+
# @return [Array<GandiV5::LiveDNS::Domain::Record>]
|
56
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
57
|
+
def fetch_records(name = nil, type = nil, page: (1..), per_page: 100)
|
58
|
+
GandiV5::LiveDNS.require_valid_record_type type if type
|
59
|
+
|
60
|
+
url_ = "#{url}/records"
|
61
|
+
url_ += "/#{CGI.escape name}" if name
|
62
|
+
url_ += "/#{CGI.escape type}" if type
|
63
|
+
|
64
|
+
all = []
|
65
|
+
GandiV5.paginated_get(url_, page, per_page) do |data|
|
66
|
+
all += [*data].map { |item| GandiV5::LiveDNS::Domain::Record.from_gandi item }
|
67
|
+
end
|
68
|
+
all
|
44
69
|
end
|
45
70
|
|
46
|
-
#
|
47
|
-
#
|
71
|
+
# @overload fetch_zone_lines()
|
72
|
+
# Fetch all records for this domain.
|
73
|
+
# @overload fetch_zone_lines(name)
|
74
|
+
# Fetch records for a name.
|
75
|
+
# @param name [String] the name to fetch records for.
|
76
|
+
# @overload fetch_zone_lines(name, type)
|
77
|
+
# Fetch records of a type for a name.
|
78
|
+
# @param name [String] the name to fetch records for.
|
79
|
+
# @param type [String] the record type to fetch.
|
80
|
+
# @return [String]
|
48
81
|
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
49
|
-
def
|
50
|
-
|
82
|
+
def fetch_zone_lines(name = nil, type = nil)
|
83
|
+
GandiV5::LiveDNS.require_valid_record_type type if type
|
84
|
+
|
85
|
+
url_ = "#{url}/records"
|
86
|
+
url_ += "/#{CGI.escape name}" if name
|
87
|
+
url_ += "/#{CGI.escape type}" if type
|
88
|
+
|
89
|
+
GandiV5.get(url_, accept: 'text/plain').last
|
90
|
+
end
|
91
|
+
|
92
|
+
# Add record to this domain.
|
93
|
+
# @param name [String]
|
94
|
+
# @param type [String]
|
95
|
+
# @param ttl [Integer]
|
96
|
+
# @param values [Array<String>]
|
97
|
+
# @return [String] The confirmation message from Gandi.
|
98
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
99
|
+
def add_record(name, type, ttl, *values)
|
100
|
+
GandiV5::LiveDNS.require_valid_record_type type
|
101
|
+
fail ArgumentError, 'ttl must be positive and non-zero' unless ttl.positive?
|
102
|
+
fail ArgumentError, 'there must be at least one value' if values.none?
|
103
|
+
|
104
|
+
body = {
|
105
|
+
rrset_name: name,
|
106
|
+
rrset_type: type,
|
107
|
+
rrset_ttl: ttl,
|
108
|
+
rrset_values: values
|
109
|
+
}.to_json
|
110
|
+
_response, data = GandiV5.post "#{url}/records", body
|
111
|
+
data['message']
|
112
|
+
end
|
113
|
+
|
114
|
+
# @overload delete_records()
|
115
|
+
# Delete all records for this domain.
|
116
|
+
# @overload delete_records(name)
|
117
|
+
# Delete records for a name.
|
118
|
+
# @param name [String] the name to delete records for.
|
119
|
+
# @overload delete_records(name, type)
|
120
|
+
# Delete records of a type for a name.
|
121
|
+
# @param name [String] the name to delete records for.
|
122
|
+
# @param type [String] the record type to delete.
|
123
|
+
# @return [nil]
|
124
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
125
|
+
def delete_records(name = nil, type = nil)
|
126
|
+
GandiV5::LiveDNS.require_valid_record_type(type) if type
|
127
|
+
|
128
|
+
url_ = "#{url}/records"
|
129
|
+
url_ += "/#{CGI.escape name}" if name
|
130
|
+
url_ += "/#{CGI.escape type}" if type
|
131
|
+
GandiV5.delete(url_).last
|
132
|
+
end
|
133
|
+
|
134
|
+
# Replace records for the domain.
|
135
|
+
# @param name [String, nil] only replaces records for this name.
|
136
|
+
# @param type [String, nil] only replaces record of this type (requires name).
|
137
|
+
# @param values [Array<String>] the values to set for the record.
|
138
|
+
# @raise [ArgumentError] if ttl is present and type is absent.
|
139
|
+
# @return [String] The confirmation message from Gandi.
|
140
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
141
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
142
|
+
def replace_records(records, name: nil, type: nil)
|
143
|
+
if type
|
144
|
+
GandiV5::LiveDNS.require_valid_record_type(type) if type
|
145
|
+
fail ArgumentError, 'missing keyword: name' if name.nil?
|
146
|
+
end
|
147
|
+
|
148
|
+
url_ = "#{url}/records"
|
149
|
+
url_ += "/#{CGI.escape name}" if name
|
150
|
+
url_ += "/#{CGI.escape type}" if type
|
151
|
+
|
152
|
+
body = if type && name
|
153
|
+
{ rrset_values: records }
|
154
|
+
else
|
155
|
+
{ items: records.map { |r| r.transform_keys { |k| "rrset_#{k}" } } }
|
156
|
+
end
|
157
|
+
|
158
|
+
_response, data = GandiV5.put url_, body.to_json
|
159
|
+
data['message']
|
160
|
+
end
|
161
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
162
|
+
|
163
|
+
# Replace all records for this domain.
|
164
|
+
# @param text [String] zone file lines to replace the records with.
|
165
|
+
# @return [String] The confirmation message from Gandi.
|
166
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
167
|
+
def replace_zone_lines(text)
|
168
|
+
_response, data = GandiV5.put "#{url}/records", text, 'content-type': 'text/plain'
|
169
|
+
data['message']
|
170
|
+
end
|
171
|
+
|
172
|
+
# The list of nameservers that this domain is using according to LiveDNS' systems.
|
173
|
+
# * Either there are no NS records on @ and the 3 hashed nameservers are returned
|
174
|
+
# (ns-{123}-{abc}.gandi.net)
|
175
|
+
# * Or some NS records exist on @ and it will return those
|
176
|
+
# @see https://api.gandi.net/docs/domains#get-v5-domain-domains-domain-name$
|
177
|
+
# @return [Array<String>]
|
178
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
179
|
+
def name_servers
|
180
|
+
@name_servers ||= fetch_name_servers
|
181
|
+
end
|
182
|
+
|
183
|
+
# Requery Gandi for the domain's name servers.
|
184
|
+
# @see https://api.gandi.net/docs/domains#get-v5-domain-domains-domain-name$
|
185
|
+
# @return [Array<String>]
|
186
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
187
|
+
def fetch_name_servers
|
188
|
+
_response, data = GandiV5.get "#{url}/nameservers"
|
189
|
+
@name_servers = data
|
190
|
+
end
|
191
|
+
|
192
|
+
# The list of DNSSEC keys for the domain.
|
193
|
+
# If you need the fingerprint, public_key or tag attributes you'll need
|
194
|
+
# use GandiV5::LiveDNS::Domain::DnssecKey.fetch on each item.
|
195
|
+
# @return [Array<GandiV5::LiveDNS::Domain::DnssecKey>]
|
196
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
197
|
+
def dnssec_keys
|
198
|
+
@dnssec_keys ||= fetch_dnssec_keys
|
199
|
+
end
|
200
|
+
|
201
|
+
# Requery Gandi for the domain's DNSSEC keys.
|
202
|
+
# @return [Array<GandiV5::LiveDNS::Domain::DnssecKey>]
|
203
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
204
|
+
def fetch_dnssec_keys
|
205
|
+
@dnssec_keys = GandiV5::LiveDNS::Domain::DnssecKey.list(fqdn)
|
206
|
+
end
|
207
|
+
|
208
|
+
# The list of TSIG keys for the domain.
|
209
|
+
# If you need the secret, fingerprint, public_key or tag attributes you'll need
|
210
|
+
# to use GandiV5::LiveDNS::Domain::DnssecKey.fetch on each item.
|
211
|
+
# @return [Array<GandiV5::LiveDNS::Domain::TsigKey>]
|
212
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
213
|
+
def tsig_keys
|
214
|
+
@tsig_keys ||= fetch_tsig_keys
|
215
|
+
end
|
216
|
+
|
217
|
+
# Requery Gandi for the domain's TSIG keys.
|
218
|
+
# @return [Array<GandiV5::LiveDNS::Domain::TsigKey>]
|
219
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
220
|
+
def fetch_tsig_keys
|
221
|
+
_response, data = GandiV5.get "#{url}/axfr/tsig"
|
222
|
+
data.map { |item| GandiV5::LiveDNS::Domain::TsigKey.from_gandi item }
|
223
|
+
end
|
224
|
+
|
225
|
+
# Add a Tsig key to this domain.
|
226
|
+
# @param key [GandiV5::LiveDNS::Domain::TsigKey, #uuid, String, #to_s]
|
227
|
+
# the key to add.
|
228
|
+
# @param sharing_id [nil, String, #to_s]
|
229
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
230
|
+
def add_tsig_key(key, sharing_id: nil)
|
231
|
+
key = key.uuid if key.respond_to?(:uuid)
|
232
|
+
url_ = "#{url}/axfr/tsig/#{key}"
|
233
|
+
url_ += "?sharing_id=#{CGI.escape sharing_id}" if sharing_id
|
234
|
+
_response, _data = GandiV5.put url_
|
235
|
+
end
|
236
|
+
|
237
|
+
# Remove a Tsig key from this domain.
|
238
|
+
# @param key [GandiV5::LiveDNS::Domain::TsigKey, #uuid, String, #to_s]
|
239
|
+
# the key to remove.
|
240
|
+
# @param sharing_id [nil, String, #to_s]
|
241
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
242
|
+
def remove_tsig_key(key, sharing_id: nil)
|
243
|
+
key = key.uuid if key.respond_to?(:uuid)
|
244
|
+
url_ = "#{url}/axfr/tsig/#{key}"
|
245
|
+
url_ += "?sharing_id=#{CGI.escape sharing_id}" if sharing_id
|
246
|
+
_response, _data = GandiV5.delete url_
|
247
|
+
end
|
248
|
+
|
249
|
+
# The list of AXFR clients for the domain.
|
250
|
+
# @return [Array<String>] list of IP addresses.
|
251
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
252
|
+
def axfr_clients
|
253
|
+
@axfr_clients ||= fetch_axfr_clients
|
254
|
+
end
|
255
|
+
|
256
|
+
# Requery Gandi for the domain's AXFR clients.
|
257
|
+
# @return [Array<String>] list of IP addresses.
|
258
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
259
|
+
def fetch_axfr_clients
|
260
|
+
_response, data = GandiV5.get "#{url}/axfr/slaves"
|
261
|
+
data
|
262
|
+
end
|
263
|
+
|
264
|
+
# Add an AXFR client to this domain.
|
265
|
+
# @param ip [String, #to_s] the IP address to add.
|
266
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
267
|
+
def add_axfr_client(ip)
|
268
|
+
_response, _data = GandiV5.put "#{url}/axfr/slaves/#{ip}"
|
269
|
+
end
|
270
|
+
|
271
|
+
# Remove and AXFR client from this domain.
|
272
|
+
# @param ip [String, #to_s] the IP address to remove.
|
273
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
274
|
+
def remove_axfr_client(ip)
|
275
|
+
_response, _data = GandiV5.delete "#{url}/axfr/slaves/#{ip}"
|
51
276
|
end
|
52
277
|
|
53
278
|
# List the domains.
|
54
|
-
# @
|
279
|
+
# @param page [#each<Integer, #to_s>] the page(s) of results to retrieve.
|
280
|
+
# If page is not provided keep querying until an empty list is returned.
|
281
|
+
# If page responds to .each then iterate until an empty list is returned.
|
282
|
+
# @param per_page [Integer, #to_s] (optional default 100) how many results to get per page.
|
283
|
+
# @param sharing_id [String, #to_s] (optional) filter by domains assigned to a given user.
|
284
|
+
# @return [Array<String>]
|
55
285
|
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
56
|
-
def self.list
|
57
|
-
|
58
|
-
|
286
|
+
def self.list(page: (1..), per_page: 100, sharing_id: nil)
|
287
|
+
page = [page.to_i] unless page.respond_to?(:each)
|
288
|
+
params = { per_page: per_page }
|
289
|
+
params[:sharing_id] = sharing_id unless sharing_id.nil?
|
290
|
+
|
291
|
+
domains = []
|
292
|
+
page.each do |page_number|
|
293
|
+
_resp, data = GandiV5.get url, params: params.merge(page: page_number)
|
294
|
+
break if data.empty?
|
295
|
+
|
296
|
+
domains += data.map { |item| item['fqdn'] }
|
297
|
+
break if data.count < per_page
|
298
|
+
end
|
299
|
+
domains
|
59
300
|
end
|
60
301
|
|
61
302
|
# Get a domain.
|
@@ -67,14 +308,57 @@ class GandiV5
|
|
67
308
|
from_gandi data
|
68
309
|
end
|
69
310
|
|
311
|
+
# Create a new domain in the LiveDNS system.
|
312
|
+
# You must have sufficent permission to manage the domain to do this.
|
313
|
+
# @param fqdn [String, #to_s] the fully qualified domain to add to LiveDNS.
|
314
|
+
# @param records [Array<Hash, GandiV5::LiveDNS::Domain::Record, #to_h, nil>]
|
315
|
+
# @param ttl [Integer, #to_s, nil] the TTL of the SOA record.
|
316
|
+
# Note that this is not a default TTL that will be used for the records in the zone.
|
317
|
+
# the records (if any) to add to the created zone.
|
318
|
+
# @param sharing_id [nil, String, #to_s]
|
319
|
+
# @return [GandiV5::LiveDNS::Domain]
|
320
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
321
|
+
def self.create(fqdn, records = nil, soa_ttl: nil, sharing_id: nil)
|
322
|
+
body = { fqdn: fqdn, zone: {} }
|
323
|
+
body[:zone][:ttl] = soa_ttl if soa_ttl
|
324
|
+
if records
|
325
|
+
body[:zone][:items] = records.map do |r|
|
326
|
+
r.to_h.transform_keys { |k| "rrset_#{k}" }
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
url_ = url
|
331
|
+
url_ += "?sharing_id=#{CGI.escape sharing_id}" if sharing_id
|
332
|
+
|
333
|
+
GandiV5.post url_, body.to_json
|
334
|
+
fetch(fqdn)
|
335
|
+
end
|
336
|
+
|
337
|
+
# Fetch the list of known record types (A, CNAME, etc.)
|
338
|
+
# @return [Array<String>]
|
339
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
340
|
+
def self.record_types
|
341
|
+
GandiV5.get("#{BASE}livedns/dns/rrtypes").last
|
342
|
+
end
|
343
|
+
|
344
|
+
# Get the LiveDNS servers to use for a domain.
|
345
|
+
# Does not take into account any NS records that exist in the zone.
|
346
|
+
# @param fqdn [String, #to_s] the fully qualified domain to hash in
|
347
|
+
# in order to get the LiveDNS servers to use.
|
348
|
+
# @return [Array<String>]
|
349
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
350
|
+
def self.generic_name_servers(fqdn)
|
351
|
+
GandiV5.get("#{BASE}livedns/nameservers/#{CGI.escape fqdn}").last
|
352
|
+
end
|
353
|
+
|
70
354
|
private
|
71
355
|
|
72
356
|
def url
|
73
|
-
"#{BASE}domains/#{CGI.escape
|
357
|
+
"#{BASE}livedns/domains/#{CGI.escape fqdn}"
|
74
358
|
end
|
75
359
|
|
76
360
|
def self.url(fqdn = nil)
|
77
|
-
"#{BASE}domains" + (fqdn ? "/#{CGI.escape
|
361
|
+
"#{BASE}livedns/domains" + (fqdn ? "/#{CGI.escape fqdn}" : '')
|
78
362
|
end
|
79
363
|
private_class_method :url
|
80
364
|
end
|