gandi_v5 0.5.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +69 -5
- data/LICENSE.md +2 -6
- data/README.md +67 -18
- data/lib/gandi_v5.rb +137 -70
- data/lib/gandi_v5/billing/info/prepaid.rb +1 -0
- data/lib/gandi_v5/data.rb +3 -2
- data/lib/gandi_v5/data/converter.rb +3 -2
- data/lib/gandi_v5/data/converter/array_of.rb +3 -2
- data/lib/gandi_v5/data/converter/integer.rb +3 -2
- data/lib/gandi_v5/data/converter/symbol.rb +3 -2
- data/lib/gandi_v5/data/converter/time.rb +3 -2
- data/lib/gandi_v5/domain.rb +16 -17
- data/lib/gandi_v5/domain/availability/product/period.rb +1 -1
- data/lib/gandi_v5/domain/contact.rb +5 -5
- data/lib/gandi_v5/domain/tld.rb +2 -2
- data/lib/gandi_v5/domain/transfer_in.rb +170 -0
- data/lib/gandi_v5/domain/transfer_in/availability.rb +51 -0
- data/lib/gandi_v5/email.rb +1 -0
- data/lib/gandi_v5/email/forward.rb +2 -8
- data/lib/gandi_v5/email/mailbox.rb +4 -10
- data/lib/gandi_v5/email/slot.rb +11 -3
- data/lib/gandi_v5/error/gandi_error.rb +1 -0
- data/lib/gandi_v5/live_dns.rb +2 -12
- data/lib/gandi_v5/live_dns/domain.rb +340 -29
- data/lib/gandi_v5/live_dns/domain/dnssec_key.rb +120 -0
- data/lib/gandi_v5/live_dns/domain/record.rb +81 -0
- data/lib/gandi_v5/live_dns/domain/snapshot.rb +111 -0
- data/lib/gandi_v5/live_dns/domain/tsig_key.rb +74 -0
- data/lib/gandi_v5/sharing_space.rb +27 -0
- data/lib/gandi_v5/simple_hosting.rb +13 -0
- data/lib/gandi_v5/simple_hosting/instance.rb +245 -0
- data/lib/gandi_v5/simple_hosting/instance/application.rb +45 -0
- data/lib/gandi_v5/simple_hosting/instance/database.rb +20 -0
- data/lib/gandi_v5/simple_hosting/instance/language.rb +22 -0
- data/lib/gandi_v5/simple_hosting/instance/upgrade.rb +22 -0
- data/lib/gandi_v5/simple_hosting/instance/virtual_host.rb +187 -0
- data/lib/gandi_v5/simple_hosting/instance/virtual_host/linked_dns_zone.rb +75 -0
- data/lib/gandi_v5/version.rb +1 -1
- data/spec/.rubocop.yml +9 -9
- data/spec/features/list_domain_renewals_spec.rb +16 -0
- data/spec/features/list_email_addresses_spec.rb +39 -0
- data/spec/fixtures/bodies/GandiV5_Domain/fetch.yml +8 -0
- data/spec/fixtures/bodies/GandiV5_Domain_TransferIn/fetch.yml +21 -0
- data/spec/fixtures/bodies/GandiV5_Domain_TransferIn_Availability/fetch.yml +10 -0
- 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/fixtures/bodies/GandiV5_SimpleHosting_Instance/fetch.yml +80 -0
- data/spec/fixtures/bodies/GandiV5_SimpleHosting_Instance/list.yml +38 -0
- data/spec/fixtures/bodies/GandiV5_SimpleHosting_Instance_VirtualHost/fetch.yml +26 -0
- data/spec/fixtures/bodies/GandiV5_SimpleHosting_Instance_VirtualHost/list.yml +18 -0
- data/spec/fixtures/vcr/Examples/List_domain_renewals.yml +54 -0
- data/spec/fixtures/vcr/Examples/List_email_addresses.yml +103 -0
- data/spec/units/gandi_v5/domain/transfer_in/availability_spec.rb +49 -0
- data/spec/units/gandi_v5/domain/transfer_in_spec.rb +143 -0
- data/spec/units/gandi_v5/domain_spec.rb +13 -39
- 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/email/slot_spec.rb +10 -2
- 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/sharing_space_spec.rb +4 -0
- data/spec/units/gandi_v5/simple_hosting/instance/application_spec.rb +37 -0
- data/spec/units/gandi_v5/simple_hosting/instance/database_spec.rb +4 -0
- data/spec/units/gandi_v5/simple_hosting/instance/language_spec.rb +4 -0
- data/spec/units/gandi_v5/simple_hosting/instance/upgrade_spec.rb +4 -0
- data/spec/units/gandi_v5/simple_hosting/instance/virtual_host/linked_dns_zone_spec.rb +50 -0
- data/spec/units/gandi_v5/simple_hosting/instance/virtual_host_spec.rb +199 -0
- data/spec/units/gandi_v5/simple_hosting/instance_spec.rb +182 -0
- data/spec/units/gandi_v5/simple_hosting_spec.rb +9 -0
- data/spec/units/gandi_v5_spec.rb +111 -14
- metadata +174 -53
- data/.gitignore +0 -26
- data/.rspec +0 -3
- data/.rubocop.yml +0 -30
- data/.travis.yml +0 -38
- data/FUNDING.yml +0 -10
- data/Gemfile +0 -6
- data/Guardfile +0 -39
- data/Rakefile +0 -3
- data/bin/console +0 -13
- data/gandi_v5.gemspec +0 -42
- data/lib/gandi_v5/domain/sharing_space.rb +0 -21
- 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/domain/sharing_space_spec.rb +0 -4
- 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
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class GandiV5
|
4
|
+
class Domain
|
5
|
+
class TransferIn
|
6
|
+
# Information about the availabillity of a domain to be transfered into Gandi.
|
7
|
+
# @!attribute [r] fqdn
|
8
|
+
# @return [String] the fully qualified domain name.
|
9
|
+
# @!attribute [r] fqdn_unicode
|
10
|
+
# @return [String] the fully qualified domain name in unicode.
|
11
|
+
# @!attribute [r] available
|
12
|
+
# @return [Boolean] whether the domain can be transfered.
|
13
|
+
# @!attribute [r] corporate
|
14
|
+
# @return [Boolean] Optional
|
15
|
+
# @!attribute [r] internal
|
16
|
+
# @return [Boolean] Optional
|
17
|
+
# @!attribute [r] minimum_duration
|
18
|
+
# @return [Integer] Optional the minimum duration you can reregister the domain for.
|
19
|
+
# @!attribute [r] maximum_duration
|
20
|
+
# @return [Integer] Optional the maximum duration you can reregister the domain for.
|
21
|
+
# @!attribute [r] durations
|
22
|
+
# @return [Array<Integer>] Optional the durations you can reregister the domain for.
|
23
|
+
# @!attribute [r] message
|
24
|
+
# @return [String, nil] Optional message explaining why the domain can't be transfered.
|
25
|
+
class Availability
|
26
|
+
include GandiV5::Data
|
27
|
+
|
28
|
+
members :fqdn, :available, :corporate, :internal,
|
29
|
+
:minimum_duration, :maximum_duration
|
30
|
+
member :durations, array: true
|
31
|
+
member :message, gandi_key: 'msg'
|
32
|
+
member :fqdn_unicode, gandi_key: 'fqdn_ulabel'
|
33
|
+
|
34
|
+
# Find out if a domain can be transfered to Gandi.
|
35
|
+
# @see https://api.gandi.net/docs/domains/#post-v5-domain-transferin-domain-available
|
36
|
+
# @param fqdn [String, #to_s] the fully qualified domain name to query.
|
37
|
+
# @param auth_code [String, #to_s] authorization code (if required).
|
38
|
+
# @return [GandiV5::Domain::TransferIn::Availabillity]
|
39
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
40
|
+
def self.fetch(fqdn, auth_code = nil)
|
41
|
+
url = "#{BASE}domain/transferin/#{fqdn}/available"
|
42
|
+
body = {}
|
43
|
+
body['authinfo'] = auth_code if auth_code
|
44
|
+
|
45
|
+
_response, data = GandiV5.post url, body
|
46
|
+
from_gandi data
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/gandi_v5/email.rb
CHANGED
@@ -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
|
@@ -43,7 +43,7 @@ class GandiV5
|
|
43
43
|
alias mailbox_uuid uuid
|
44
44
|
|
45
45
|
# Create a new GandiV5::Email::Mailbox
|
46
|
-
# @param members [Hash
|
46
|
+
# @param members [Hash{Symbol => Object}]
|
47
47
|
# @return [GandiV5::Email::Slot]
|
48
48
|
def initialize(**members)
|
49
49
|
super(**members)
|
@@ -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
|
@@ -271,7 +265,7 @@ class GandiV5
|
|
271
265
|
def self.crypt_password(password)
|
272
266
|
# You can also send a hashed password in sha512-crypt ie: {SHA512-CRYPT}$6$xxxx$yyyy
|
273
267
|
salt = SecureRandom.random_number(36**8).to_s(36)
|
274
|
-
password.crypt(
|
268
|
+
password.crypt("$6$#{salt}")
|
275
269
|
end
|
276
270
|
private_class_method :crypt_password
|
277
271
|
|
data/lib/gandi_v5/email/slot.rb
CHANGED
@@ -78,15 +78,23 @@ class GandiV5
|
|
78
78
|
# but require more mailboxes on that domain, you must first purchase additional slots.
|
79
79
|
# @see https://api.gandi.net/docs/email#post-v5-email-slots-domain
|
80
80
|
# @param fqdn [String, #to_s] the fully qualified domain name to add the slot to.
|
81
|
-
# @param type [:standard, :premium]
|
81
|
+
# @param type [:standard, :premium] The type of slot to add.
|
82
|
+
# @param sharing_id [nil, String, #to_s] either:
|
83
|
+
# * nil (default) - nothing special happens
|
84
|
+
# * an organization ID - pay using another organization
|
85
|
+
# (you need to have billing permissions on the organization
|
86
|
+
# and use the same organization name for the domain name's owner).
|
87
|
+
# The invoice will be edited using this organization's information.
|
82
88
|
# @return [String] The confirmation message from Gandi.
|
83
89
|
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
84
|
-
def self.create(fqdn, type
|
90
|
+
def self.create(fqdn, type: :standard, sharing_id: nil)
|
85
91
|
body = {
|
86
92
|
mailbox_type: type
|
87
93
|
}.to_json
|
88
94
|
|
89
|
-
|
95
|
+
url_ = url(fqdn)
|
96
|
+
url_ += "?sharing_id=#{sharing_id}" if sharing_id
|
97
|
+
response, _data = GandiV5.post url_, body
|
90
98
|
fetch fqdn, response.headers[:location].split('/').last
|
91
99
|
end
|
92
100
|
|
@@ -5,6 +5,7 @@ class GandiV5
|
|
5
5
|
# Generic error class for errors returned by Gandi.
|
6
6
|
class GandiError < GandiV5::Error
|
7
7
|
# Generate a new GandiV5::Error::GandiError from the hash returned by Gandi.
|
8
|
+
# @api private
|
8
9
|
# @param hash [Hash] the hash returned by Gandi.
|
9
10
|
# @return [GandiV5::Error::GandiError]
|
10
11
|
def self.from_hash(hash)
|
data/lib/gandi_v5/live_dns.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Namespace for classes which access LiveDNS details.
|
4
|
+
# @see https://api.gandi.net/docs/livedns/
|
4
5
|
class GandiV5
|
5
6
|
# Gandi LiveDNS Management API.
|
6
7
|
class LiveDNS
|
7
|
-
|
8
|
-
|
8
|
+
# Permitted record types.
|
9
9
|
RECORD_TYPES = %w[
|
10
10
|
A AAAA CNAME MX NS TXT ALIAS
|
11
11
|
WKS SRV LOC SPF CAA DS SSHFP PTR KEY DNAME TLSA OPENPGPKEY CDS
|
@@ -21,16 +21,6 @@ class GandiV5
|
|
21
21
|
GandiV5::LiveDNS::Domain.list
|
22
22
|
end
|
23
23
|
|
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
24
|
# Raise an error if passed type is invalid.
|
35
25
|
# @param type [String] the record type to check.
|
36
26
|
# @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,38 +20,310 @@ class GandiV5
|
|
27
20
|
from_gandi data
|
28
21
|
end
|
29
22
|
|
30
|
-
#
|
31
|
-
# @
|
23
|
+
# Update this domain's settings.
|
24
|
+
# @see https://api.gandi.net/docs/livedns/#patch-v5-livedns-domains-fqdn
|
25
|
+
# @param automatic_snapshots [String, #to_s]
|
26
|
+
# Enable or disable the automatic creation of new snapshots when records are changed.
|
32
27
|
# @return [String] The confirmation message from Gandi.
|
33
28
|
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
self.zone_uuid = uuid
|
29
|
+
def update(automatic_snapshots:)
|
30
|
+
_response, data = GandiV5.patch url, { automatic_snapshots: automatic_snapshots }.to_json
|
31
|
+
self.automatic_snapshots = automatic_snapshots
|
38
32
|
data['message']
|
39
33
|
end
|
40
34
|
|
41
|
-
# @
|
42
|
-
|
43
|
-
|
35
|
+
# @overload fetch_records()
|
36
|
+
# Fetch all records for this domain.
|
37
|
+
# @see https://api.gandi.net/docs/livedns/#get-v5-livedns-domains-fqdn-records
|
38
|
+
# @param page [Integer, #each<Integer>] which page(s) of results to get.
|
39
|
+
# If page is not provided keep querying until an empty list is returned.
|
40
|
+
# If page responds to .each then iterate until an empty list is returned.
|
41
|
+
# @param per_page [Integer, #to_s] (optional default 100) how many results ot get per page.
|
42
|
+
# @overload fetch_records(name)
|
43
|
+
# Fetch records for a name.
|
44
|
+
# @see https://api.gandi.net/docs/livedns/#get-v5-livedns-domains-fqdn-records-rrset_name
|
45
|
+
# @param name [String] the name to fetch records for.
|
46
|
+
# @param page [Integer, #each<Integer>] which page(s) of results to get.
|
47
|
+
# If page is not provided keep querying until an empty list is returned.
|
48
|
+
# If page responds to .each then iterate until an empty list is returned.
|
49
|
+
# @param per_page [Integer, #to_s] (optional default 100) how many results ot get per page.
|
50
|
+
# @overload fetch_records(name, type)
|
51
|
+
# Fetch records of a type for a name.
|
52
|
+
# @see https://api.gandi.net/docs/livedns/#get-v5-livedns-domains-fqdn-records-rrset_name-rrset_type
|
53
|
+
# @param name [String] the name to fetch records for.
|
54
|
+
# @param type [String] the record type to fetch.
|
55
|
+
# @param page [Integer, #each<Integer>] which page(s) of results to get.
|
56
|
+
# If page is not provided keep querying until an empty list is returned.
|
57
|
+
# If page responds to .each then iterate until an empty list is returned.
|
58
|
+
# @param per_page [Integer, #to_s] (optional default 100) how many results ot get per page.
|
59
|
+
# @return [Array<GandiV5::LiveDNS::Domain::Record>]
|
60
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
61
|
+
def fetch_records(name = nil, type = nil, page: (1..), per_page: 100)
|
62
|
+
GandiV5::LiveDNS.require_valid_record_type type if type
|
63
|
+
|
64
|
+
url_ = "#{url}/records"
|
65
|
+
url_ += "/#{CGI.escape name}" if name
|
66
|
+
url_ += "/#{CGI.escape type}" if type
|
67
|
+
|
68
|
+
all = []
|
69
|
+
GandiV5.paginated_get(url_, page, per_page) do |data|
|
70
|
+
all += [*data].map { |item| GandiV5::LiveDNS::Domain::Record.from_gandi item }
|
71
|
+
end
|
72
|
+
all
|
44
73
|
end
|
45
74
|
|
46
|
-
#
|
47
|
-
#
|
75
|
+
# @overload fetch_zone_lines()
|
76
|
+
# Fetch all records for this domain.
|
77
|
+
# @see https://api.gandi.net/docs/livedns/#get-v5-livedns-domains-fqdn-records
|
78
|
+
# @overload fetch_zone_lines(name)
|
79
|
+
# Fetch records for a name.
|
80
|
+
# @see https://api.gandi.net/docs/livedns/#get-v5-livedns-domains-fqdn-records-rrset_name
|
81
|
+
# @param name [String] the name to fetch records for.
|
82
|
+
# @overload fetch_zone_lines(name, type)
|
83
|
+
# Fetch records of a type for a name.
|
84
|
+
# @see https://api.gandi.net/docs/livedns/#get-v5-livedns-domains-fqdn-records-rrset_name-rrset_type
|
85
|
+
# @param name [String] the name to fetch records for.
|
86
|
+
# @param type [String] the record type to fetch.
|
87
|
+
# @return [String]
|
48
88
|
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
49
|
-
def
|
50
|
-
|
89
|
+
def fetch_zone_lines(name = nil, type = nil)
|
90
|
+
GandiV5::LiveDNS.require_valid_record_type type if type
|
91
|
+
|
92
|
+
url_ = "#{url}/records"
|
93
|
+
url_ += "/#{CGI.escape name}" if name
|
94
|
+
url_ += "/#{CGI.escape type}" if type
|
95
|
+
|
96
|
+
GandiV5.get(url_, accept: 'text/plain').last
|
97
|
+
end
|
98
|
+
|
99
|
+
# Add record to this domain.
|
100
|
+
# @see https://api.gandi.net/docs/livedns/#post-v5-livedns-domains-fqdn-records
|
101
|
+
# @param name [String]
|
102
|
+
# @param type [String]
|
103
|
+
# @param ttl [Integer]
|
104
|
+
# @param values [Array<String>]
|
105
|
+
# @return [String] The confirmation message from Gandi.
|
106
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
107
|
+
def add_record(name, type, ttl, *values)
|
108
|
+
GandiV5::LiveDNS.require_valid_record_type type
|
109
|
+
fail ArgumentError, 'ttl must be positive and non-zero' unless ttl.positive?
|
110
|
+
fail ArgumentError, 'there must be at least one value' if values.none?
|
111
|
+
|
112
|
+
body = {
|
113
|
+
rrset_name: name,
|
114
|
+
rrset_type: type,
|
115
|
+
rrset_ttl: ttl,
|
116
|
+
rrset_values: values
|
117
|
+
}.to_json
|
118
|
+
_response, data = GandiV5.post "#{url}/records", body
|
119
|
+
data['message']
|
120
|
+
end
|
121
|
+
|
122
|
+
# @overload delete_records()
|
123
|
+
# Delete all records for this domain.
|
124
|
+
# @see https://api.gandi.net/docs/livedns/#delete-v5-livedns-domains-fqdn-records
|
125
|
+
# @overload delete_records(name)
|
126
|
+
# Delete records for a name.
|
127
|
+
# @see https://api.gandi.net/docs/livedns/#delete-v5-livedns-domains-fqdn-records-rrset_name
|
128
|
+
# @param name [String] the name to delete records for.
|
129
|
+
# @overload delete_records(name, type)
|
130
|
+
# Delete records of a type for a name.
|
131
|
+
# @see https://api.gandi.net/docs/livedns/#delete-v5-livedns-domains-fqdn-records-rrset_name-rrset_type
|
132
|
+
# @param name [String] the name to delete records for.
|
133
|
+
# @param type [String] the record type to delete.
|
134
|
+
# @return [nil]
|
135
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
136
|
+
def delete_records(name = nil, type = nil)
|
137
|
+
GandiV5::LiveDNS.require_valid_record_type(type) if type
|
138
|
+
|
139
|
+
url_ = "#{url}/records"
|
140
|
+
url_ += "/#{CGI.escape name}" if name
|
141
|
+
url_ += "/#{CGI.escape type}" if type
|
142
|
+
GandiV5.delete(url_).last
|
143
|
+
end
|
144
|
+
|
145
|
+
# Replace records for the domain.
|
146
|
+
# @param name [String, nil] only replaces records for this name.
|
147
|
+
# @param type [String, nil] only replaces record of this type (requires name).
|
148
|
+
# @param values [Array<String>] the values to set for the record.
|
149
|
+
# @raise [ArgumentError] if ttl is present and type is absent.
|
150
|
+
# @see https://api.gandi.net/docs/livedns/#put-v5-livedns-domains-fqdn-records
|
151
|
+
# @see https://api.gandi.net/docs/livedns/#put-v5-livedns-domains-fqdn-records-rrset_name
|
152
|
+
# @see https://api.gandi.net/docs/livedns/#put-v5-livedns-domains-fqdn-records-rrset_name-rrset_type
|
153
|
+
# @return [String] The confirmation message from Gandi.
|
154
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
155
|
+
# rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
156
|
+
def replace_records(records, name: nil, type: nil)
|
157
|
+
if type
|
158
|
+
GandiV5::LiveDNS.require_valid_record_type(type) if type
|
159
|
+
fail ArgumentError, 'missing keyword: name' if name.nil?
|
160
|
+
end
|
161
|
+
|
162
|
+
url_ = "#{url}/records"
|
163
|
+
url_ += "/#{CGI.escape name}" if name
|
164
|
+
url_ += "/#{CGI.escape type}" if type
|
165
|
+
|
166
|
+
body = if type && name
|
167
|
+
{ rrset_values: records }
|
168
|
+
else
|
169
|
+
{ items: records.map { |r| r.transform_keys { |k| "rrset_#{k}" } } }
|
170
|
+
end
|
171
|
+
|
172
|
+
_response, data = GandiV5.put url_, body.to_json
|
173
|
+
data['message']
|
174
|
+
end
|
175
|
+
# rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
176
|
+
|
177
|
+
# Replace all records for this domain.
|
178
|
+
# @see https://api.gandi.net/docs/livedns/#put-v5-livedns-domains-fqdn-records
|
179
|
+
# @param text [String] zone file lines to replace the records with.
|
180
|
+
# @return [String] The confirmation message from Gandi.
|
181
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
182
|
+
def replace_zone_lines(text)
|
183
|
+
_response, data = GandiV5.put "#{url}/records", text, 'content-type': 'text/plain'
|
184
|
+
data['message']
|
185
|
+
end
|
186
|
+
|
187
|
+
# The list of nameservers that this domain is using according to LiveDNS' systems.
|
188
|
+
# * Either there are no NS records on @ and the 3 hashed nameservers are returned
|
189
|
+
# (ns-{123}-{abc}.gandi.net)
|
190
|
+
# * Or some NS records exist on @ and it will return those
|
191
|
+
# @see https://api.gandi.net/docs/domains#get-v5-domain-domains-domain-name$
|
192
|
+
# @return [Array<String>]
|
193
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
194
|
+
def name_servers
|
195
|
+
@name_servers ||= fetch_name_servers
|
196
|
+
end
|
197
|
+
|
198
|
+
# Requery Gandi for the domain's name servers.
|
199
|
+
# @see https://api.gandi.net/docs/domains#get-v5-domain-domains-domain-name$
|
200
|
+
# @return [Array<String>]
|
201
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
202
|
+
def fetch_name_servers
|
203
|
+
_response, data = GandiV5.get "#{url}/nameservers"
|
204
|
+
@name_servers = data
|
205
|
+
end
|
206
|
+
|
207
|
+
# The list of DNSSEC keys for the domain.
|
208
|
+
# If you need the fingerprint, public_key or tag attributes you'll need
|
209
|
+
# use GandiV5::LiveDNS::Domain::DnssecKey.fetch on each item.
|
210
|
+
# @return [Array<GandiV5::LiveDNS::Domain::DnssecKey>]
|
211
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
212
|
+
def dnssec_keys
|
213
|
+
@dnssec_keys ||= fetch_dnssec_keys
|
214
|
+
end
|
215
|
+
|
216
|
+
# Requery Gandi for the domain's DNSSEC keys.
|
217
|
+
# @see https://api.gandi.net/docs/livedns/#get-v5-livedns-domains-fqdn-keys
|
218
|
+
# @return [Array<GandiV5::LiveDNS::Domain::DnssecKey>]
|
219
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
220
|
+
def fetch_dnssec_keys
|
221
|
+
@dnssec_keys = GandiV5::LiveDNS::Domain::DnssecKey.list(fqdn)
|
222
|
+
end
|
223
|
+
|
224
|
+
# The list of TSIG keys for the domain.
|
225
|
+
# If you need the secret, fingerprint, public_key or tag attributes you'll need
|
226
|
+
# to use GandiV5::LiveDNS::Domain::DnssecKey.fetch on each item.
|
227
|
+
# @return [Array<GandiV5::LiveDNS::Domain::TsigKey>]
|
228
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
229
|
+
def tsig_keys
|
230
|
+
@tsig_keys ||= fetch_tsig_keys
|
231
|
+
end
|
232
|
+
|
233
|
+
# Requery Gandi for the domain's TSIG keys.
|
234
|
+
# @see https://api.gandi.net/docs/livedns/#get-v5-livedns-domains-fqdn-axfr-tsig
|
235
|
+
# @return [Array<GandiV5::LiveDNS::Domain::TsigKey>]
|
236
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
237
|
+
def fetch_tsig_keys
|
238
|
+
_response, data = GandiV5.get "#{url}/axfr/tsig"
|
239
|
+
data.map { |item| GandiV5::LiveDNS::Domain::TsigKey.from_gandi item }
|
240
|
+
end
|
241
|
+
|
242
|
+
# Add a Tsig key to this domain.
|
243
|
+
# @see https://api.gandi.net/docs/livedns/#put-v5-livedns-domains-fqdn-axfr-tsig-id
|
244
|
+
# @param key [GandiV5::LiveDNS::Domain::TsigKey, #uuid, String, #to_s]
|
245
|
+
# the key to add.
|
246
|
+
# @param sharing_id [nil, String, #to_s]
|
247
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
248
|
+
def add_tsig_key(key, sharing_id: nil)
|
249
|
+
key = key.uuid if key.respond_to?(:uuid)
|
250
|
+
url_ = "#{url}/axfr/tsig/#{key}"
|
251
|
+
url_ += "?sharing_id=#{CGI.escape sharing_id}" if sharing_id
|
252
|
+
_response, _data = GandiV5.put url_
|
253
|
+
end
|
254
|
+
|
255
|
+
# Remove a Tsig key from this domain.
|
256
|
+
# @see https://api.gandi.net/docs/livedns/#delete-v5-livedns-domains-fqdn-axfr-tsig-id
|
257
|
+
# @param key [GandiV5::LiveDNS::Domain::TsigKey, #uuid, String, #to_s]
|
258
|
+
# the key to remove.
|
259
|
+
# @param sharing_id [nil, String, #to_s]
|
260
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
261
|
+
def remove_tsig_key(key, sharing_id: nil)
|
262
|
+
key = key.uuid if key.respond_to?(:uuid)
|
263
|
+
url_ = "#{url}/axfr/tsig/#{key}"
|
264
|
+
url_ += "?sharing_id=#{CGI.escape sharing_id}" if sharing_id
|
265
|
+
_response, _data = GandiV5.delete url_
|
266
|
+
end
|
267
|
+
|
268
|
+
# The list of AXFR clients for the domain.
|
269
|
+
# @return [Array<String>] list of IP addresses.
|
270
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
271
|
+
def axfr_clients
|
272
|
+
@axfr_clients ||= fetch_axfr_clients
|
273
|
+
end
|
274
|
+
|
275
|
+
# Requery Gandi for the domain's AXFR clients.
|
276
|
+
# @see https://api.gandi.net/docs/livedns/#get-v5-livedns-domains-fqdn-axfr-slaves
|
277
|
+
# @return [Array<String>] list of IP addresses.
|
278
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
279
|
+
def fetch_axfr_clients
|
280
|
+
_response, data = GandiV5.get "#{url}/axfr/slaves"
|
281
|
+
data
|
282
|
+
end
|
283
|
+
|
284
|
+
# Add an AXFR client to this domain.
|
285
|
+
# @see https://api.gandi.net/docs/livedns/#put-v5-livedns-domains-fqdn-axfr-slaves-ip
|
286
|
+
# @param ip [String, #to_s] the IP address to add.
|
287
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
288
|
+
def add_axfr_client(ip)
|
289
|
+
_response, _data = GandiV5.put "#{url}/axfr/slaves/#{ip}"
|
290
|
+
end
|
291
|
+
|
292
|
+
# Remove and AXFR client from this domain.
|
293
|
+
# @see https://api.gandi.net/docs/livedns/#delete-v5-livedns-domains-fqdn-axfr-slaves-ip
|
294
|
+
# @param ip [String, #to_s] the IP address to remove.
|
295
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
296
|
+
def remove_axfr_client(ip)
|
297
|
+
_response, _data = GandiV5.delete "#{url}/axfr/slaves/#{ip}"
|
51
298
|
end
|
52
299
|
|
53
300
|
# List the domains.
|
54
|
-
# @
|
301
|
+
# @see https://api.gandi.net/docs/livedns/#get-v5-livedns-domains
|
302
|
+
# @param page [#each<Integer, #to_s>] the page(s) of results to retrieve.
|
303
|
+
# If page is not provided keep querying until an empty list is returned.
|
304
|
+
# If page responds to .each then iterate until an empty list is returned.
|
305
|
+
# @param per_page [Integer, #to_s] (optional default 100) how many results to get per page.
|
306
|
+
# @param sharing_id [String, #to_s] (optional) filter by domains assigned to a given user.
|
307
|
+
# @return [Array<String>]
|
55
308
|
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
56
|
-
def self.list
|
57
|
-
|
58
|
-
|
309
|
+
def self.list(page: (1..), per_page: 100, sharing_id: nil)
|
310
|
+
page = [page.to_i] unless page.respond_to?(:each)
|
311
|
+
params = { per_page: per_page }
|
312
|
+
params[:sharing_id] = sharing_id unless sharing_id.nil?
|
313
|
+
|
314
|
+
domains = []
|
315
|
+
page.each do |page_number|
|
316
|
+
_resp, data = GandiV5.get url, params: params.merge(page: page_number)
|
317
|
+
break if data.empty?
|
318
|
+
|
319
|
+
domains += data.map { |item| item['fqdn'] }
|
320
|
+
break if data.count < per_page
|
321
|
+
end
|
322
|
+
domains
|
59
323
|
end
|
60
324
|
|
61
325
|
# Get a domain.
|
326
|
+
# @see https://api.gandi.net/docs/livedns/#get-v5-livedns-domains-fqdn
|
62
327
|
# @param fqdn [String, #to_s] the fully qualified domain name to fetch.
|
63
328
|
# @return [GandiV5::LiveDNS::Domain]
|
64
329
|
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
@@ -67,14 +332,60 @@ class GandiV5
|
|
67
332
|
from_gandi data
|
68
333
|
end
|
69
334
|
|
335
|
+
# Create a new domain in the LiveDNS system.
|
336
|
+
# You must have sufficent permission to manage the domain to do this.
|
337
|
+
# @see https://api.gandi.net/docs/livedns/#post-v5-livedns-domains
|
338
|
+
# @param fqdn [String, #to_s] the fully qualified domain to add to LiveDNS.
|
339
|
+
# @param records [Array<Hash, GandiV5::LiveDNS::Domain::Record, #to_h, nil>]
|
340
|
+
# @param ttl [Integer, #to_s, nil] the TTL of the SOA record.
|
341
|
+
# Note that this is not a default TTL that will be used for the records in the zone.
|
342
|
+
# the records (if any) to add to the created zone.
|
343
|
+
# @param sharing_id [nil, String, #to_s]
|
344
|
+
# @return [GandiV5::LiveDNS::Domain]
|
345
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
346
|
+
def self.create(fqdn, records = nil, soa_ttl: nil, sharing_id: nil)
|
347
|
+
body = { fqdn: fqdn, zone: {} }
|
348
|
+
body[:zone][:ttl] = soa_ttl if soa_ttl
|
349
|
+
if records
|
350
|
+
body[:zone][:items] = records.map do |r|
|
351
|
+
r.to_h.transform_keys { |k| "rrset_#{k}" }
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
url_ = url
|
356
|
+
url_ += "?sharing_id=#{CGI.escape sharing_id}" if sharing_id
|
357
|
+
|
358
|
+
GandiV5.post url_, body.to_json
|
359
|
+
fetch(fqdn)
|
360
|
+
end
|
361
|
+
|
362
|
+
# Fetch the list of known record types (A, CNAME, etc.)
|
363
|
+
# @see https://api.gandi.net/docs/livedns/#get-v5-livedns-dns-rrtypes
|
364
|
+
# @return [Array<String>]
|
365
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
366
|
+
def self.record_types
|
367
|
+
GandiV5.get("#{BASE}livedns/dns/rrtypes").last
|
368
|
+
end
|
369
|
+
|
370
|
+
# Get the LiveDNS servers to use for a domain.
|
371
|
+
# @note Does not take into account any NS records that exist in the zone.
|
372
|
+
# @see https://api.gandi.net/docs/livedns/#get-v5-livedns-nameservers-fqdn
|
373
|
+
# @param fqdn [String, #to_s] the fully qualified domain to hash in
|
374
|
+
# in order to get the LiveDNS servers to use.
|
375
|
+
# @return [Array<String>]
|
376
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
377
|
+
def self.generic_name_servers(fqdn)
|
378
|
+
GandiV5.get("#{BASE}livedns/nameservers/#{CGI.escape fqdn}").last
|
379
|
+
end
|
380
|
+
|
70
381
|
private
|
71
382
|
|
72
383
|
def url
|
73
|
-
"#{BASE}domains/#{CGI.escape
|
384
|
+
"#{BASE}livedns/domains/#{CGI.escape fqdn}"
|
74
385
|
end
|
75
386
|
|
76
387
|
def self.url(fqdn = nil)
|
77
|
-
"#{BASE}domains" + (fqdn ? "/#{CGI.escape
|
388
|
+
"#{BASE}livedns/domains" + (fqdn ? "/#{CGI.escape fqdn}" : '')
|
78
389
|
end
|
79
390
|
private_class_method :url
|
80
391
|
end
|