gandi_v5 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +1 -1
  4. data/.travis.yml +9 -0
  5. data/CHANGELOG.md +15 -0
  6. data/FUNDING.yml +10 -0
  7. data/README.md +7 -17
  8. data/gandi_v5.gemspec +3 -2
  9. data/lib/gandi_v5.rb +24 -10
  10. data/lib/gandi_v5/billing.rb +0 -2
  11. data/lib/gandi_v5/billing/info.rb +0 -2
  12. data/lib/gandi_v5/data.rb +0 -2
  13. data/lib/gandi_v5/data/converter.rb +0 -4
  14. data/lib/gandi_v5/domain.rb +159 -17
  15. data/lib/gandi_v5/domain/availability.rb +0 -3
  16. data/lib/gandi_v5/domain/availability/product.rb +0 -3
  17. data/lib/gandi_v5/domain/live_dns.rb +42 -0
  18. data/lib/gandi_v5/domain/renewal_information.rb +0 -3
  19. data/lib/gandi_v5/email.rb +0 -4
  20. data/lib/gandi_v5/email/forward.rb +108 -0
  21. data/lib/gandi_v5/email/mailbox.rb +0 -2
  22. data/lib/gandi_v5/error.rb +0 -2
  23. data/lib/gandi_v5/live_dns.rb +0 -4
  24. data/lib/gandi_v5/live_dns/domain.rb +1 -144
  25. data/lib/gandi_v5/live_dns/has_zone_records.rb +153 -0
  26. data/lib/gandi_v5/live_dns/zone.rb +1 -146
  27. data/lib/gandi_v5/organization.rb +28 -5
  28. data/lib/gandi_v5/version.rb +1 -1
  29. data/spec/.rubocop.yml +1 -1
  30. data/spec/features/domain_spec.rb +1 -1
  31. data/spec/fixtures/bodies/GandiV5_Billing/{info.yaml → info.yml} +0 -0
  32. data/spec/fixtures/bodies/GandiV5_Domain/{get.yaml → fetch.yml} +0 -0
  33. data/spec/fixtures/bodies/GandiV5_Domain/{fetch_contacts.yaml → fetch_contacts.yml} +0 -0
  34. data/spec/fixtures/bodies/GandiV5_Domain/fetch_glue_records.yml +7 -0
  35. data/spec/fixtures/bodies/GandiV5_Domain/fetch_livedns.yml +6 -0
  36. data/spec/fixtures/bodies/GandiV5_Domain/fetch_name_servers.yml +2 -0
  37. data/spec/fixtures/bodies/GandiV5_Domain/{renewal_info.yaml → fetch_renewal_info.yml} +0 -3
  38. data/spec/fixtures/bodies/GandiV5_Domain/{restore_info.yaml → fetch_restore_info.yml} +0 -0
  39. data/spec/fixtures/bodies/GandiV5_Domain/{list.yaml → list.yml} +1 -0
  40. data/spec/fixtures/bodies/GandiV5_Domain_Availability/{fetch.yaml → fetch.yml} +0 -0
  41. data/spec/fixtures/bodies/GandiV5_Domain_TLD/{fetch.yaml → fetch.yml} +0 -0
  42. data/spec/fixtures/bodies/GandiV5_Domain_TLD/{list.yaml → list.yml} +0 -0
  43. data/spec/fixtures/bodies/GandiV5_Email_Forward/list.yml +6 -0
  44. data/spec/fixtures/bodies/GandiV5_Email_Mailbox/{get.yaml → fetch.yml} +0 -0
  45. data/spec/fixtures/bodies/GandiV5_Email_Mailbox/{list.yaml → list.yml} +0 -0
  46. data/spec/fixtures/bodies/GandiV5_Email_Slot/{get.yaml → fetch.yml} +0 -0
  47. data/spec/fixtures/bodies/GandiV5_Email_Slot/{list.yaml → list.yml} +0 -0
  48. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/{get.yaml → fetch.yml} +0 -0
  49. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/{list.yaml → list.yml} +0 -0
  50. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/{get.yaml → fetch.yml} +0 -0
  51. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/{list.yaml → list.yml} +0 -0
  52. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/{fetch.yaml → fetch.yml} +0 -0
  53. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/{list.yaml → list.yml} +0 -0
  54. data/spec/fixtures/bodies/GandiV5_Organization/{get.yaml → fetch.yml} +0 -0
  55. data/spec/fixtures/bodies/GandiV5_Organization/list.yml +7 -0
  56. data/spec/fixtures/vcr/Domain_features/List_domains.yml +2 -1
  57. data/spec/spec_helper.rb +2 -2
  58. data/spec/units/gandi_v5/billing_spec.rb +2 -2
  59. data/spec/units/gandi_v5/domain/availability_spec.rb +1 -1
  60. data/spec/units/gandi_v5/domain/live_dns_spec.rb +45 -0
  61. data/spec/units/gandi_v5/domain/tld_spec.rb +2 -2
  62. data/spec/units/gandi_v5/domain_spec.rb +241 -22
  63. data/spec/units/gandi_v5/email/forward_spec.rb +121 -0
  64. data/spec/units/gandi_v5/email/mailbox_spec.rb +3 -3
  65. data/spec/units/gandi_v5/email/slot_spec.rb +3 -3
  66. data/spec/units/gandi_v5/live_dns/domain_spec.rb +3 -3
  67. data/spec/units/gandi_v5/live_dns/zone/snapshot_spec.rb +2 -2
  68. data/spec/units/gandi_v5/live_dns/zone_spec.rb +2 -2
  69. data/spec/units/gandi_v5/organization_spec.rb +38 -1
  70. metadata +51 -77
  71. data/doc/GandiV5.html +0 -1183
  72. data/doc/GandiV5/Billing.html +0 -293
  73. data/doc/GandiV5/Billing/Info.html +0 -641
  74. data/doc/GandiV5/Billing/Info/Prepaid.html +0 -817
  75. data/doc/GandiV5/Data.html +0 -785
  76. data/doc/GandiV5/Data/ClassMethods.html +0 -223
  77. data/doc/GandiV5/Data/Converter.html +0 -433
  78. data/doc/GandiV5/Data/Converter/ArrayOf.html +0 -413
  79. data/doc/GandiV5/Data/Converter/Symbol.html +0 -322
  80. data/doc/GandiV5/Data/Converter/Time.html +0 -330
  81. data/doc/GandiV5/Domain.html +0 -16847
  82. data/doc/GandiV5/Domain/AutoRenew.html +0 -1237
  83. data/doc/GandiV5/Domain/Availability.html +0 -1020
  84. data/doc/GandiV5/Domain/Availability/Product.html +0 -988
  85. data/doc/GandiV5/Domain/Availability/Product/Period.html +0 -220
  86. data/doc/GandiV5/Domain/Availability/Product/Price.html +0 -1031
  87. data/doc/GandiV5/Domain/Availability/Tax.html +0 -440
  88. data/doc/GandiV5/Domain/Contact.html +0 -4459
  89. data/doc/GandiV5/Domain/Contract.html +0 -520
  90. data/doc/GandiV5/Domain/Dates.html +0 -1313
  91. data/doc/GandiV5/Domain/RenewalInformation.html +0 -1147
  92. data/doc/GandiV5/Domain/RestoreInformation.html +0 -339
  93. data/doc/GandiV5/Domain/SharingSpace.html +0 -437
  94. data/doc/GandiV5/Domain/TLD.html +0 -1565
  95. data/doc/GandiV5/Email.html +0 -144
  96. data/doc/GandiV5/Email/Mailbox.html +0 -6307
  97. data/doc/GandiV5/Email/Mailbox/Responder.html +0 -1560
  98. data/doc/GandiV5/Email/Offer.html +0 -514
  99. data/doc/GandiV5/Email/Slot.html +0 -4244
  100. data/doc/GandiV5/Error.html +0 -151
  101. data/doc/GandiV5/Error/GandiError.html +0 -270
  102. data/doc/GandiV5/LiveDNS.html +0 -300
  103. data/doc/GandiV5/LiveDNS/Domain.html +0 -2984
  104. data/doc/GandiV5/LiveDNS/RecordSet.html +0 -1593
  105. data/doc/GandiV5/LiveDNS/Zone.html +0 -8891
  106. data/doc/GandiV5/LiveDNS/Zone/Snapshot.html +0 -1556
  107. data/doc/GandiV5/Organization.html +0 -2341
  108. data/doc/_index.html +0 -474
  109. data/doc/class_list.html +0 -51
  110. data/doc/css/common.css +0 -1
  111. data/doc/css/full_list.css +0 -58
  112. data/doc/css/style.css +0 -496
  113. data/doc/file.README.html +0 -175
  114. data/doc/file_list.html +0 -56
  115. data/doc/frames.html +0 -17
  116. data/doc/index.html +0 -175
  117. data/doc/js/app.js +0 -303
  118. data/doc/js/full_list.js +0 -216
  119. data/doc/js/jquery.js +0 -4
  120. data/doc/method_list.html +0 -2427
  121. data/doc/top-level-namespace.html +0 -110
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'availability/tax'
4
- require_relative 'availability/product'
5
-
6
3
  class GandiV5
7
4
  class Domain
8
5
  # Information about the availabillity of processes on a domain.
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'product/price'
4
- require_relative 'product/period'
5
-
6
3
  class GandiV5
7
4
  class Domain
8
5
  class Availability
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ class GandiV5
4
+ class Domain
5
+ # LiveDNS information for a domain.
6
+ # @!attribute [r] current
7
+ # @return [:classic, :livedns, :other]
8
+ # type of nameservers currently set. classic corresponds to Gandi's classic nameservers,
9
+ # livedns is for the new, default, Gandi nameservers and other is for custom nameservers.
10
+ # @!attribute [r] name_servers
11
+ # @return [Array<String>] list of current nameservers.
12
+ # @!attribute [r] dnssec_available
13
+ # @return [nil, Boolean] whether DNSSEC may be applied to the domain.
14
+ # @!attribute [r] livednssec_available
15
+ # @return [nil, Boolean] whether DNSSEC with liveDNS may be applied to this domain.
16
+ class LiveDNS
17
+ include GandiV5::Data
18
+
19
+ members :dnssec_available, :livednssec_available
20
+ member :name_servers, gandi_key: 'nameservers'
21
+ member :current, converter: GandiV5::Data::Converter::Symbol
22
+
23
+ # Check if classic DNS is being used.
24
+ # @return [Boolean]
25
+ def classic?
26
+ current == :classic
27
+ end
28
+
29
+ # Check if custom DNS is being used.
30
+ # @return [Boolean]
31
+ def custom?
32
+ current == :custom
33
+ end
34
+
35
+ # Check if LiveDNS is being used.
36
+ # @return [Boolean]
37
+ def livedns?
38
+ current == :livedns
39
+ end
40
+ end
41
+ end
42
+ end
@@ -17,8 +17,6 @@ class GandiV5
17
17
  # @return [Integer]
18
18
  # @!attribute [r] minimum
19
19
  # @return [Integer]
20
- # @!attribute [r] contracts
21
- # @return [Array<GandiV5::Domain::Contract>]
22
20
  class RenewalInformation
23
21
  include GandiV5::Data
24
22
 
@@ -26,7 +24,6 @@ class GandiV5
26
24
 
27
25
  member :begins_at, converter: GandiV5::Data::Converter::Time
28
26
  member :ends_at, converter: GandiV5::Data::Converter::Time
29
- member :contracts, converter: GandiV5::Domain::Contract, array: true
30
27
 
31
28
  # Check if the domain is currently renewable.
32
29
  # @return [Boolean]
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'email/mailbox'
4
- require_relative 'email/offer'
5
- require_relative 'email/slot'
6
-
7
3
  class GandiV5
8
4
  # Gandi Email Mailbox Management API.
9
5
  class Email
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ class GandiV5
4
+ class Email
5
+ # A forwarding address that lives within a domain.
6
+ # @see https://docs.gandi.net/en/gandimail/forwarding_and_aliases/
7
+ # @!attribute [r] source
8
+ # @return [String] the source email address ("alice" rather than "alice@example.com").
9
+ # @!attribute [r] destinations
10
+ # @return [Array<String>] list of destination email addresses.
11
+ # @!attribute [r] fqdn
12
+ # @return [String] domain name.
13
+ class Forward
14
+ include GandiV5::Data
15
+
16
+ members :source, :fqdn
17
+ member :destinations, array: true
18
+
19
+ # Delete the forwarding.
20
+ # @see https://api.gandi.net/docs/email/#delete-v5-email-forwards-domain-source
21
+ # @return [String] The confirmation message from Gandi.
22
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
23
+ def delete
24
+ _response, data = GandiV5.delete url
25
+ data['message']
26
+ end
27
+
28
+ # Update the forwarding.
29
+ # @see https://api.gandi.net/docs/email/#put-v5-email-forwards-domain-source
30
+ # @param destinations [Array<String, #to_s>] new list of destination email addresses.
31
+ # @return [String] The confirmation message from Gandi.
32
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
33
+ def update(*destinations)
34
+ fail ArgumentError, 'destinations can\'t be empty' if destinations.none?
35
+
36
+ _response, data = GandiV5.put url, { destinations: destinations }.to_json
37
+ @destinations = destinations.map(&:to_s)
38
+ data['message']
39
+ end
40
+
41
+ # Returns the string representation of the forwarding.
42
+ # @return [String]
43
+ def to_s
44
+ "#{source}@#{fqdn} -> #{destinations.join(', ')}"
45
+ end
46
+
47
+ # Create a new forward.
48
+ # @see https://api.gandi.net/docs/email/#post-v5-email-forwards-domain
49
+ # @param fqdn [String, #to_s] the fully qualified domain name for the forward.
50
+ # @param source [String, #to_s]
51
+ # the source email address ("alice" rather than "alice@example.com").
52
+ # @param destinations [Array<String, #to_s>] list of destination email addresses.
53
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
54
+ def self.create(fqdn, source, *destinations)
55
+ fail ArgumentError, 'destinations can\'t be empty' if destinations.none?
56
+
57
+ body = {
58
+ source: source,
59
+ destinations: destinations
60
+ }.to_json
61
+ _response, _data = GandiV5.post url(fqdn), body
62
+
63
+ new fqdn: fqdn, source: source, destinations: destinations
64
+ end
65
+
66
+ # List forwards for a domain.
67
+ # @see https://api.gandi.net/docs/email/#get-v5-email-forwards-domain
68
+ # @param fqdn [String, #to_s] the fully qualified domain name for the forwards.
69
+ # @param page [Integer, #each<Integer>] which page(s) of results to get.
70
+ # If page is not provided keep querying until an empty list is returned.
71
+ # If page responds to .each then iterate until an empty list is returned.
72
+ # @param per_page [Integer, #to_s] (optional default 100) how many results ot get per page.
73
+ # @param sort_by [#to_s] (optional default "login")
74
+ # how to sort the results ("login", "-login").
75
+ # @param source [String] (optional) filter the source (pattern)
76
+ # e.g. ("alice" "*lice", "alic*").
77
+ # @return [Array<GandiV5::Email::Forward>]
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
+
82
+ params.reject! { |_k, v| v.nil? }
83
+
84
+ mailboxes = []
85
+ page.each do |page_number|
86
+ _response, data = GandiV5.get url(fqdn), params: params.merge(page: page_number)
87
+ break if data.empty?
88
+
89
+ mailboxes += data.map { |mailbox| from_gandi mailbox.merge(fqdn: fqdn) }
90
+ break if data.count < params.fetch(:per_page, 100)
91
+ end
92
+ mailboxes
93
+ end
94
+
95
+ private
96
+
97
+ def url
98
+ "#{BASE}email/forwards/#{CGI.escape fqdn}/#{CGI.escape source}"
99
+ end
100
+
101
+ def self.url(fqdn, source = nil)
102
+ "#{BASE}email/forwards/#{CGI.escape fqdn}" +
103
+ (source ? "/#{CGI.escape source}" : '')
104
+ end
105
+ private_class_method :url
106
+ end
107
+ end
108
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'mailbox/responder'
4
-
5
3
  class GandiV5
6
4
  class Email
7
5
  # A mailbox that lives within a domain.
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'error/gandi_error'
4
-
5
3
  class GandiV5
6
4
  # Generic error class for errors occuring using the API.
7
5
  class Error < RuntimeError
@@ -44,7 +44,3 @@ class GandiV5
44
44
  # rubocop:enable Style/GuardClause
45
45
  end
46
46
  end
47
-
48
- require_relative 'live_dns/record_set'
49
- require_relative 'live_dns/domain'
50
- require_relative 'live_dns/zone'
@@ -9,6 +9,7 @@ class GandiV5
9
9
  # @return [String]
10
10
  class Domain
11
11
  include GandiV5::Data
12
+ include GandiV5::LiveDNS::HasZoneRecords
12
13
 
13
14
  members :fqdn
14
15
 
@@ -26,150 +27,6 @@ class GandiV5
26
27
  from_gandi data
27
28
  end
28
29
 
29
- # @overload fetch_records()
30
- # Fetch all records for this domain.
31
- # @overload fetch_records(name)
32
- # Fetch records for a name.
33
- # @param name [String] the name to fetch records for.
34
- # @overload fetch_records(name, type)
35
- # Fetch records of a type for a name.
36
- # @param name [String] the name to fetch records for.
37
- # @param type [String] the record type to fetch.
38
- # @return [Array<GandiV5::LiveDNS::RecordSet>]
39
- # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
40
- def fetch_records(name = nil, type = nil)
41
- GandiV5::LiveDNS.require_valid_record_type type if type
42
-
43
- url_ = "#{url}/records"
44
- url_ += "/#{CGI.escape name}" if name
45
- url_ += "/#{CGI.escape type}" if type
46
-
47
- _response, data = GandiV5.get url_
48
- data = [data] unless data.is_a?(Array)
49
- data.map { |item| GandiV5::LiveDNS::RecordSet.from_gandi item }
50
- end
51
-
52
- # @overload fetch_zone_lines()
53
- # Fetch all records for this domain.
54
- # @overload fetch_zone_lines(name)
55
- # Fetch records for a name.
56
- # @param name [String] the name to fetch records for.
57
- # @overload fetch_zone_lines(name, type)
58
- # Fetch records of a type for a name.
59
- # @param name [String] the name to fetch records for.
60
- # @param type [String] the record type to fetch.
61
- # @return [String]
62
- # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
63
- def fetch_zone_lines(name = nil, type = nil)
64
- GandiV5::LiveDNS.require_valid_record_type type if type
65
-
66
- url_ = "#{url}/records"
67
- url_ += "/#{CGI.escape name}" if name
68
- url_ += "/#{CGI.escape type}" if type
69
-
70
- GandiV5.get(url_, accept: 'text/plain').last
71
- end
72
-
73
- # Add record to this domain.
74
- # @param name [String]
75
- # @param type [String]
76
- # @param ttl [Integer]
77
- # @param values [Array<String>]
78
- # @return [String] The confirmation message from Gandi.
79
- # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
80
- def add_record(name, type, ttl, *values)
81
- GandiV5::LiveDNS.require_valid_record_type type
82
- fail ArgumentError, 'ttl must be positive and non-zero' unless ttl.positive?
83
- fail ArgumentError, 'there must be at least one value' if values.none?
84
-
85
- body = {
86
- rrset_name: name,
87
- rrset_type: type,
88
- rrset_ttl: ttl,
89
- rrset_values: values
90
- }.to_json
91
- _response, data = GandiV5.post "#{url}/records", body
92
- data['message']
93
- end
94
-
95
- # @overload delete_records()
96
- # Delete all records for this domain.
97
- # @overload delete_records(name)
98
- # Delete records for a name.
99
- # @param name [String] the name to delete records for.
100
- # @overload delete_records(name, type)
101
- # Delete records of a type for a name.
102
- # @param name [String] the name to delete records for.
103
- # @param type [String] the record type to delete.
104
- # @return [nil]
105
- # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
106
- def delete_records(name = nil, type = nil)
107
- GandiV5::LiveDNS.require_valid_record_type(type) if type
108
-
109
- url_ = "#{url}/records"
110
- url_ += "/#{CGI.escape name}" if name
111
- url_ += "/#{CGI.escape type}" if type
112
- GandiV5.delete(url_).last
113
- end
114
-
115
- # Replace all records for this domain.
116
- # @param records
117
- # [Array<Hash<:name, :type => String, :ttl => Integer, :values => Array<String>>>]
118
- # the records to add.
119
- # @param text [String] zone file lines to replace the records with.
120
- # @return [String] The confirmation message from Gandi.
121
- # @raise [ArgumentError] if neither/both of records & test are passed.
122
- # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
123
- def replace_records(records: nil, text: nil)
124
- unless [records, text].count(&:nil?).eql?(1)
125
- fail ArgumentError, 'you must pass ONE of records: or text:'
126
- end
127
-
128
- if records
129
- body = {
130
- items: records.map { |r| r.transform_keys { |k| "rrset_#{k}" } }
131
- }.to_json
132
- _response, data = GandiV5.put "#{url}/records", body
133
- elsif text
134
- _response, data = GandiV5.put "#{url}/records", text, 'content-type': 'text/plain'
135
- end
136
- data['message']
137
- end
138
-
139
- # @override replace_records_for(name, records)
140
- # Replace records for a name in this domain.
141
- # @param name [String]
142
- # @param records
143
- # [Array<Hash<type: String, ttl: Integer, values: Array<String>>>]
144
- # the records to add.
145
- # @override replace_records_for(name, values, type: nil, ttl: nil)
146
- # Replace records for a name in this domain.
147
- # @param name [String]
148
- # @param type [String] the record type.
149
- # @param ttl [Integer] the TTL to set for the record.
150
- # @param values [Array<String>] the values to set for the record.
151
- # @raise [ArgumentError] if ttl is present and type is absent.
152
- # @return [String] The confirmation message from Gandi.
153
- # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
154
- def replace_records_for(name, records, type: nil, ttl: nil)
155
- fail ArgumentError, 'missing keyword: type' if ttl && type.nil?
156
-
157
- if type
158
- GandiV5::LiveDNS.require_valid_record_type type
159
- body = { rrset_values: records, rrset_ttl: ttl }
160
- # body[:rrset_ttl] = ttl if ttl
161
- _response, data = GandiV5.put "#{url}/records/#{name}/#{type}", body.to_json
162
-
163
- else
164
- body = {
165
- items: records.map { |r| r.transform_keys { |k| "rrset_#{k}" } }
166
- }
167
- _response, data = GandiV5.put "#{url}/records/#{name}", body.to_json
168
- end
169
-
170
- data['message']
171
- end
172
-
173
30
  # Change the zone used by this domain.
174
31
  # @param uuid [String, #uuid, #to_s] the UUID of the zone this domain should now use.
175
32
  # @return [String] The confirmation message from Gandi.
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ class GandiV5
4
+ class LiveDNS
5
+ # Methods for handling record related requests in both
6
+ # GandiV5::LiveDNS::Domain and GandiV5::LiveDNS::Zone.
7
+ module HasZoneRecords
8
+ # @overload fetch_records()
9
+ # Fetch all records for this domain.
10
+ # @overload fetch_records(name)
11
+ # Fetch records for a name.
12
+ # @param name [String] the name to fetch records for.
13
+ # @overload fetch_records(name, type)
14
+ # Fetch records of a type for a name.
15
+ # @param name [String] the name to fetch records for.
16
+ # @param type [String] the record type to fetch.
17
+ # @return [Array<GandiV5::LiveDNS::RecordSet>]
18
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
19
+ def fetch_records(name = nil, type = nil)
20
+ GandiV5::LiveDNS.require_valid_record_type type if type
21
+
22
+ url_ = "#{url}/records"
23
+ url_ += "/#{CGI.escape name}" if name
24
+ url_ += "/#{CGI.escape type}" if type
25
+
26
+ _response, data = GandiV5.get url_
27
+ data = [data] unless data.is_a?(Array)
28
+ data.map { |item| GandiV5::LiveDNS::RecordSet.from_gandi item }
29
+ end
30
+
31
+ # @overload fetch_zone_lines()
32
+ # Fetch all records for this domain.
33
+ # @overload fetch_zone_lines(name)
34
+ # Fetch records for a name.
35
+ # @param name [String] the name to fetch records for.
36
+ # @overload fetch_zone_lines(name, type)
37
+ # Fetch records of a type for a name.
38
+ # @param name [String] the name to fetch records for.
39
+ # @param type [String] the record type to fetch.
40
+ # @return [String]
41
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
42
+ def fetch_zone_lines(name = nil, type = nil)
43
+ GandiV5::LiveDNS.require_valid_record_type type if type
44
+
45
+ url_ = "#{url}/records"
46
+ url_ += "/#{CGI.escape name}" if name
47
+ url_ += "/#{CGI.escape type}" if type
48
+
49
+ GandiV5.get(url_, accept: 'text/plain').last
50
+ end
51
+
52
+ # Add record to this domain.
53
+ # @param name [String]
54
+ # @param type [String]
55
+ # @param ttl [Integer]
56
+ # @param values [Array<String>]
57
+ # @return [String] The confirmation message from Gandi.
58
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
59
+ def add_record(name, type, ttl, *values)
60
+ GandiV5::LiveDNS.require_valid_record_type type
61
+ fail ArgumentError, 'ttl must be positive and non-zero' unless ttl.positive?
62
+ fail ArgumentError, 'there must be at least one value' if values.none?
63
+
64
+ body = {
65
+ rrset_name: name,
66
+ rrset_type: type,
67
+ rrset_ttl: ttl,
68
+ rrset_values: values
69
+ }.to_json
70
+ _response, data = GandiV5.post "#{url}/records", body
71
+ data['message']
72
+ end
73
+
74
+ # @overload delete_records()
75
+ # Delete all records for this domain.
76
+ # @overload delete_records(name)
77
+ # Delete records for a name.
78
+ # @param name [String] the name to delete records for.
79
+ # @overload delete_records(name, type)
80
+ # Delete records of a type for a name.
81
+ # @param name [String] the name to delete records for.
82
+ # @param type [String] the record type to delete.
83
+ # @return [nil]
84
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
85
+ def delete_records(name = nil, type = nil)
86
+ GandiV5::LiveDNS.require_valid_record_type(type) if type
87
+
88
+ url_ = "#{url}/records"
89
+ url_ += "/#{CGI.escape name}" if name
90
+ url_ += "/#{CGI.escape type}" if type
91
+ GandiV5.delete(url_).last
92
+ end
93
+
94
+ # Replace all records for this domain.
95
+ # @param records
96
+ # [Array<Hash<:name, :type => String, :ttl => Integer, :values => Array<String>>>]
97
+ # the records to add.
98
+ # @param text [String] zone file lines to replace the records with.
99
+ # @return [String] The confirmation message from Gandi.
100
+ # @raise [ArgumentError] if neither/both of records & test are passed.
101
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
102
+ def replace_records(records: nil, text: nil)
103
+ unless [records, text].count(&:nil?).eql?(1)
104
+ fail ArgumentError, 'you must pass ONE of records: or text:'
105
+ end
106
+
107
+ if records
108
+ body = {
109
+ items: records.map { |r| r.transform_keys { |k| "rrset_#{k}" } }
110
+ }.to_json
111
+ _response, data = GandiV5.put "#{url}/records", body
112
+ elsif text
113
+ _response, data = GandiV5.put "#{url}/records", text, 'content-type': 'text/plain'
114
+ end
115
+ data['message']
116
+ end
117
+
118
+ # @override replace_records_for(name, records)
119
+ # Replace records for a name in this domain.
120
+ # @param name [String]
121
+ # @param records
122
+ # [Array<Hash<type: String, ttl: Integer, values: Array<String>>>]
123
+ # the records to add.
124
+ # @override replace_records_for(name, values, type: nil, ttl: nil)
125
+ # Replace records for a name in this domain.
126
+ # @param name [String]
127
+ # @param type [String] the record type.
128
+ # @param ttl [Integer] the TTL to set for the record.
129
+ # @param values [Array<String>] the values to set for the record.
130
+ # @raise [ArgumentError] if ttl is present and type is absent.
131
+ # @return [String] The confirmation message from Gandi.
132
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
133
+ def replace_records_for(name, records, type: nil, ttl: nil)
134
+ fail ArgumentError, 'missing keyword: type' if ttl && type.nil?
135
+
136
+ if type
137
+ GandiV5::LiveDNS.require_valid_record_type type
138
+ body = { rrset_values: records, rrset_ttl: ttl }
139
+ # body[:rrset_ttl] = ttl if ttl
140
+ _response, data = GandiV5.put "#{url}/records/#{name}/#{type}", body.to_json
141
+
142
+ else
143
+ body = {
144
+ items: records.map { |r| r.transform_keys { |k| "rrset_#{k}" } }
145
+ }
146
+ _response, data = GandiV5.put "#{url}/records/#{name}", body.to_json
147
+ end
148
+
149
+ data['message']
150
+ end
151
+ end
152
+ end
153
+ end