gandi_v5 0.1.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +14 -4
  4. data/.travis.yml +16 -1
  5. data/CHANGELOG.md +80 -2
  6. data/FUNDING.yml +10 -0
  7. data/Guardfile +5 -6
  8. data/LICENSE.md +2 -6
  9. data/README.md +17 -23
  10. data/gandi_v5.gemspec +4 -3
  11. data/lib/gandi_v5.rb +54 -15
  12. data/lib/gandi_v5/billing.rb +2 -4
  13. data/lib/gandi_v5/billing/info.rb +0 -2
  14. data/lib/gandi_v5/data.rb +1 -2
  15. data/lib/gandi_v5/data/converter.rb +0 -4
  16. data/lib/gandi_v5/data/converter/integer.rb +26 -0
  17. data/lib/gandi_v5/domain.rb +201 -101
  18. data/lib/gandi_v5/domain/auto_renew.rb +4 -4
  19. data/lib/gandi_v5/domain/availability.rb +46 -0
  20. data/lib/gandi_v5/domain/availability/product.rb +49 -0
  21. data/lib/gandi_v5/domain/availability/product/period.rb +24 -0
  22. data/lib/gandi_v5/domain/availability/product/price.rb +36 -0
  23. data/lib/gandi_v5/domain/availability/tax.rb +20 -0
  24. data/lib/gandi_v5/domain/live_dns.rb +42 -0
  25. data/lib/gandi_v5/domain/renewal_information.rb +0 -3
  26. data/lib/gandi_v5/domain/sharing_space.rb +10 -2
  27. data/lib/gandi_v5/domain/tld.rb +57 -0
  28. data/lib/gandi_v5/email.rb +0 -4
  29. data/lib/gandi_v5/email/forward.rb +108 -0
  30. data/lib/gandi_v5/email/mailbox.rb +85 -24
  31. data/lib/gandi_v5/email/mailbox/responder.rb +43 -2
  32. data/lib/gandi_v5/email/offer.rb +2 -2
  33. data/lib/gandi_v5/email/slot.rb +52 -18
  34. data/lib/gandi_v5/error.rb +0 -2
  35. data/lib/gandi_v5/error/gandi_error.rb +2 -2
  36. data/lib/gandi_v5/live_dns.rb +20 -4
  37. data/lib/gandi_v5/live_dns/domain.rb +21 -150
  38. data/lib/gandi_v5/live_dns/has_zone_records.rb +153 -0
  39. data/lib/gandi_v5/live_dns/record_set.rb +1 -1
  40. data/lib/gandi_v5/live_dns/zone.rb +24 -165
  41. data/lib/gandi_v5/live_dns/zone/snapshot.rb +27 -8
  42. data/lib/gandi_v5/organization.rb +39 -6
  43. data/lib/gandi_v5/organization/customer.rb +90 -0
  44. data/lib/gandi_v5/version.rb +1 -1
  45. data/spec/.rubocop.yml +9 -2
  46. data/spec/features/domain_spec.rb +2 -2
  47. data/spec/features/livedns_zone_spec.rb +12 -13
  48. data/spec/fixtures/bodies/GandiV5_Billing/{info.yaml → info.yml} +0 -0
  49. data/spec/fixtures/bodies/GandiV5_Domain/{get.yaml → fetch.yml} +8 -0
  50. data/spec/fixtures/bodies/GandiV5_Domain/{fetch_contacts.yaml → fetch_contacts.yml} +0 -0
  51. data/spec/fixtures/bodies/GandiV5_Domain/fetch_glue_records.yml +7 -0
  52. data/spec/fixtures/bodies/GandiV5_Domain/fetch_livedns.yml +6 -0
  53. data/spec/fixtures/bodies/GandiV5_Domain/fetch_name_servers.yml +2 -0
  54. data/spec/fixtures/bodies/GandiV5_Domain/{renewal_info.yaml → fetch_renewal_info.yml} +0 -3
  55. data/spec/fixtures/bodies/GandiV5_Domain/{restore_info.yaml → fetch_restore_info.yml} +0 -0
  56. data/spec/fixtures/bodies/GandiV5_Domain/{list.yaml → list.yml} +1 -0
  57. data/spec/fixtures/bodies/{GandiV5_Domain/availability.yaml → GandiV5_Domain_Availability/fetch.yml} +0 -0
  58. data/spec/fixtures/bodies/{GandiV5_Domain/tld.yaml → GandiV5_Domain_TLD/fetch.yml} +0 -0
  59. data/spec/fixtures/bodies/{GandiV5_Domain/tlds.yaml → GandiV5_Domain_TLD/list.yml} +0 -0
  60. data/spec/fixtures/bodies/GandiV5_Email_Forward/list.yml +6 -0
  61. data/spec/fixtures/bodies/GandiV5_Email_Mailbox/{get.yaml → fetch.yml} +0 -0
  62. data/spec/fixtures/bodies/GandiV5_Email_Mailbox/{list.yaml → list.yml} +0 -0
  63. data/spec/fixtures/bodies/GandiV5_Email_Slot/{get.yaml → fetch.yml} +0 -0
  64. data/spec/fixtures/bodies/GandiV5_Email_Slot/{list.yaml → list.yml} +0 -0
  65. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/{get.yaml → fetch.yml} +0 -0
  66. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/{list.yaml → list.yml} +0 -0
  67. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/{get.yaml → fetch.yml} +0 -0
  68. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/{list.yaml → list.yml} +0 -0
  69. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/{get.yaml → fetch.yml} +0 -0
  70. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/list.yml +3 -0
  71. data/spec/fixtures/bodies/GandiV5_Organization/{get.yaml → fetch.yml} +0 -0
  72. data/spec/fixtures/bodies/GandiV5_Organization/list.yml +7 -0
  73. data/spec/fixtures/bodies/GandiV5_Organization_Customer/list.yml +8 -0
  74. data/spec/fixtures/vcr/Domain_features/List_domains.yml +2 -1
  75. data/spec/spec_helper.rb +2 -2
  76. data/spec/units/gandi_v5/billing_spec.rb +4 -4
  77. data/spec/units/gandi_v5/data/converter/integer_spec.rb +16 -0
  78. data/spec/units/gandi_v5/domain/auto_renew_spec.rb +5 -5
  79. data/spec/units/gandi_v5/domain/availability/product/period_spec.rb +4 -0
  80. data/spec/units/gandi_v5/domain/availability/product/price_spec.rb +4 -0
  81. data/spec/units/gandi_v5/domain/availability/product_spec.rb +4 -0
  82. data/spec/units/gandi_v5/domain/availability/tax_spec.rb +4 -0
  83. data/spec/units/gandi_v5/domain/availability_spec.rb +43 -0
  84. data/spec/units/gandi_v5/domain/live_dns_spec.rb +45 -0
  85. data/spec/units/gandi_v5/domain/tld_spec.rb +29 -0
  86. data/spec/units/gandi_v5/domain_spec.rb +359 -91
  87. data/spec/units/gandi_v5/email/forward_spec.rb +121 -0
  88. data/spec/units/gandi_v5/email/mailbox/responder_spec.rb +52 -0
  89. data/spec/units/gandi_v5/email/mailbox_spec.rb +174 -33
  90. data/spec/units/gandi_v5/email/offer_spec.rb +1 -1
  91. data/spec/units/gandi_v5/email/slot_spec.rb +113 -17
  92. data/spec/units/gandi_v5/live_dns/domain_spec.rb +73 -43
  93. data/spec/units/gandi_v5/live_dns/zone/snapshot_spec.rb +32 -3
  94. data/spec/units/gandi_v5/live_dns/zone_spec.rb +70 -52
  95. data/spec/units/gandi_v5/live_dns_spec.rb +24 -0
  96. data/spec/units/gandi_v5/organization/customer_spec.rb +81 -0
  97. data/spec/units/gandi_v5/organization_spec.rb +52 -1
  98. data/spec/units/gandi_v5_spec.rb +56 -19
  99. metadata +71 -29
  100. data/TODO.md +0 -29
@@ -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
 
@@ -20,179 +21,49 @@ class GandiV5
20
21
 
21
22
  # Refetch the information for this domain from Gandi.
22
23
  # @return [GandiV5::LiveDNS::Domain]
23
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
24
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
24
25
  def refresh
25
- data = GandiV5.get url
26
+ _response, data = GandiV5.get url
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::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
- 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::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'
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::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
- 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::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_
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::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
- data = GandiV5.put "#{url}/records", body
133
- elsif text
134
- data = GandiV5.put "#{url}/records", text, 'content-type': 'text/plain'
135
- end
136
- data['message']
137
- end
138
-
139
- # Replace records for a name in this domain.
140
- # @param name [String]
141
- # @param records
142
- # [Array<Hash<type: String, ttl: Integer, values: Array<String>>>]
143
- # the records to add.
144
- # @return [String] The confirmation message from Gandi.
145
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
146
- def replace_records_for(name, *records)
147
- body = {
148
- items: records.map { |r| r.transform_keys { |k| "rrset_#{k}" } }
149
- }.to_json
150
- data = GandiV5.put "#{url}/records/#{name}", body
151
- data['message']
152
- end
153
-
154
- GandiV5::LiveDNS::RECORD_TYPES.each do |type|
155
- # Replace records of a given type for a name in this domain.
156
- # TODO: @param name [Type] description.
157
- # TODO: @param ttl [Type] description.
158
- # TODO: documentation for *values
159
- # @return [String] The confirmation message from Gandi.
160
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
161
- define_method "replace_#{type.downcase}_records_for" do |name, ttl, *values|
162
- body = {
163
- rrset_ttl: ttl,
164
- rrset_values: values
165
- }.to_json
166
- data = GandiV5.put "#{url}/records/#{name}/#{type}", body
167
- data['message']
168
- end
169
- end
170
-
171
30
  # Change the zone used by this domain.
172
31
  # @param uuid [String, #uuid, #to_s] the UUID of the zone this domain should now use.
173
32
  # @return [String] The confirmation message from Gandi.
174
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
33
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
175
34
  def change_zone(uuid)
176
35
  uuid = uuid.uuid if uuid.respond_to?(:uuid)
177
- data = GandiV5.patch url, { zone_uuid: uuid }.to_json
36
+ _response, data = GandiV5.patch url, { zone_uuid: uuid }.to_json
178
37
  self.zone_uuid = uuid
179
38
  data['message']
180
39
  end
181
40
 
41
+ # @see GandiV5::LiveDNS::Zone.fetch
42
+ def fetch_zone
43
+ GandiV5::LiveDNS::Zone.fetch zone_uuid
44
+ end
45
+
46
+ # The domain's zone (fetching from Gandi if required).
47
+ # @return [GandiV5::LiveDNS::Zone]
48
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
49
+ def zone
50
+ @zone ||= fetch_zone
51
+ end
52
+
182
53
  # List the domains.
183
54
  # @return [Array<GandiV5::LiveDNS::Domain>]
184
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
55
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
185
56
  def self.list
186
- data = GandiV5.get url
57
+ _response, data = GandiV5.get url
187
58
  data.map { |item| from_gandi item }
188
59
  end
189
60
 
190
61
  # Get a domain.
191
62
  # @param fqdn [String, #to_s] the fully qualified domain name to fetch.
192
63
  # @return [GandiV5::LiveDNS::Domain]
193
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
64
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
194
65
  def self.fetch(fqdn)
195
- data = GandiV5.get url(fqdn)
66
+ _response, data = GandiV5.get url(fqdn)
196
67
  from_gandi data
197
68
  end
198
69
 
@@ -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
@@ -15,7 +15,7 @@ class GandiV5
15
15
  include GandiV5::Data
16
16
 
17
17
  member :type, gandi_key: 'rrset_type'
18
- member :ttl, gandi_key: 'rrset_ttl'
18
+ member :ttl, gandi_key: 'rrset_ttl', converter: GandiV5::Data::Converter::Integer
19
19
  member :name, gandi_key: 'rrset_name'
20
20
  member :values, gandi_key: 'rrset_values'
21
21
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'zone/snapshot'
4
-
5
3
  class GandiV5
6
4
  class LiveDNS
7
5
  # A zone within the LiveDNS system.
@@ -28,6 +26,7 @@ class GandiV5
28
26
  # @return [String] primary name server, as reported in SOA record.
29
27
  class Zone
30
28
  include GandiV5::Data
29
+ include GandiV5::LiveDNS::HasZoneRecords
31
30
 
32
31
  members :uuid, :name
33
32
  member :sharing_uuid, gandi_key: 'sharing_id'
@@ -53,150 +52,11 @@ class GandiV5
53
52
  ')'
54
53
  end
55
54
 
56
- # @overload fetch_records()
57
- # Fetch all records for this zone.
58
- # @overload fetch_records(name)
59
- # Fetch records for a name.
60
- # @param name [String] the name to fetch records for.
61
- # @overload fetch_records(name, type)
62
- # Fetch records of a type for a name.
63
- # @param name [String] the name to fetch records for.
64
- # @param type [String] the record type to fetch.
65
- # @return [Array<GandiV5::LiveDNS::RecordSet>]
66
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
67
- def fetch_records(name = nil, type = nil)
68
- GandiV5::LiveDNS.require_valid_record_type type if type
69
-
70
- url_ = "#{url}/records"
71
- url_ += "/#{CGI.escape name}" if name
72
- url_ += "/#{CGI.escape type}" if type
73
-
74
- data = GandiV5.get url_
75
- data = [data] unless data.is_a?(Array)
76
- data.map { |item| GandiV5::LiveDNS::RecordSet.from_gandi item }
77
- end
78
-
79
- # @overload fetch_zone_lines()
80
- # Fetch all records for this zone.
81
- # @overload fetch_zone_lines(name)
82
- # Fetch records for a name.
83
- # @param name [String] the name to fetch records for.
84
- # @overload fetch_zone_lines(name, type)
85
- # Fetch records of a type for a name.
86
- # @param name [String] the name to fetch records for.
87
- # @param type [String] the record type to fetch.
88
- # @return [String]
89
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
90
- def fetch_zone_lines(name = nil, type = nil)
91
- GandiV5::LiveDNS.require_valid_record_type type if type
92
-
93
- url_ = "#{url}/records"
94
- url_ += "/#{CGI.escape name}" if name
95
- url_ += "/#{CGI.escape type}" if type
96
-
97
- GandiV5.get url_, accept: 'text/plain'
98
- end
99
-
100
- # Add record to this zone.
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::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
- data = GandiV5.post "#{url}/records", body
119
- data['message']
120
- end
121
-
122
- # @overload delete_records()
123
- # Delete all records for this zone.
124
- # @overload delete_records(name)
125
- # Delete records for a name.
126
- # @param name [String] the name to delete records for.
127
- # @overload delete_records(name, type)
128
- # Delete records of a type for a name.
129
- # @param name [String] the name to delete records for.
130
- # @param type [String] the record type to delete.
131
- # @return [nil]
132
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
133
- def delete_records(name = nil, type = nil)
134
- GandiV5::LiveDNS.require_valid_record_type type if type
135
-
136
- url_ = "#{url}/records"
137
- url_ += "/#{CGI.escape name}" if name
138
- url_ += "/#{CGI.escape type}" if type
139
- GandiV5.delete url_
140
- end
141
-
142
- # Replace all records for this zone.
143
- # @param records
144
- # [Array<Hash<:name, :type => String, :ttl => Integer, :values => Array<String>>>]
145
- # the records to add.
146
- # @param text [String] zone file lines to replace the records with.
147
- # @return [String] The confirmation message from Gandi.
148
- # @raise [ArgumentError] if neither/both of records & test are passed.
149
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
150
- def replace_records(records: nil, text: nil)
151
- unless [records, text].count(&:nil?).eql?(1)
152
- fail ArgumentError, 'you must pass ONE of records: or text:'
153
- end
154
-
155
- if records
156
- body = {
157
- items: records.map { |r| r.transform_keys { |k| "rrset_#{k}" } }
158
- }.to_json
159
- data = GandiV5.put "#{url}/records", body
160
- elsif text
161
- data = GandiV5.put "#{url}/records", text, 'content-type': 'text/plain'
162
- end
163
- data['message']
164
- end
165
-
166
- # Replace records for a name in this zone.
167
- # @param name [String]
168
- # @param records
169
- # [Array<Hash<type: String, ttl: Integer, values: Array<String>>>]
170
- # the records to add.
171
- # @return [String] The confirmation message from Gandi.
172
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
173
- def replace_records_for(name, *records)
174
- body = {
175
- items: records.map { |r| r.transform_keys { |k| "rrset_#{k}" } }
176
- }.to_json
177
- data = GandiV5.put "#{url}/records/#{name}", body
178
- data['message']
179
- end
180
-
181
- GandiV5::LiveDNS::RECORD_TYPES.each do |type|
182
- # Replace records of a given type for a name in this zone.
183
- # @return [String] The confirmation message from Gandi.
184
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
185
- define_method "replace_#{type.downcase}_records_for" do |name, ttl, *values|
186
- body = {
187
- rrset_ttl: ttl,
188
- rrset_values: values
189
- }.to_json
190
- data = GandiV5.put "#{url}/records/#{name}/#{type}", body
191
- data['message']
192
- end
193
- end
194
-
195
55
  # List the domains that use this zone.
196
56
  # @return [Array<String>] The FQDNs.
197
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
57
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
198
58
  def list_domains
199
- data = GandiV5.get "#{url}/domains"
59
+ _response, data = GandiV5.get "#{url}/domains"
200
60
  data.map { |item| item['fqdn'] }
201
61
  end
202
62
 
@@ -204,50 +64,49 @@ class GandiV5
204
64
  # @param fqdn [String, #fqdn, #to_s] the fully qualified domain name
205
65
  # that should start using this zone.
206
66
  # @return [String] The confirmation message from Gandi.
207
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
67
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
208
68
  def attach_domain(fqdn)
209
69
  fqdn = fqdn.fqdn if fqdn.respond_to?(:fqdn)
210
- data = GandiV5.patch "#{BASE}domains/#{CGI.escape fqdn}", { zone_uuid: uuid }.to_json
70
+ _resp, data = GandiV5.patch "#{BASE}domains/#{CGI.escape fqdn}", { zone_uuid: uuid }.to_json
211
71
  data['message']
212
72
  end
213
73
 
214
- # Get snapshot UUIDs for this zone from Gandi.lib/gandi_v5/domain/auto_renew.rb
215
- # @return [Hash{String => Time}] Mapping UUID to time made.
216
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
74
+ # Get snapshot UUIDs for this zone from Gandi.
75
+ # @return [Hash{String => Time}] Mapping snapshot UUID to time made.
76
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
217
77
  def snapshots
218
- data = GandiV5.get "#{url}/snapshots"
219
- Hash[data.map { |snapshot| [snapshot['uuid'], Time.parse(snapshot['date_created'])] }]
78
+ GandiV5::LiveDNS::Zone::Snapshot.list uuid
220
79
  end
221
80
 
222
81
  # Get snapshot from Gandi.
223
82
  # @param uuid [String] the UUID of the snapshot to fetch.
224
83
  # @return [GandiV5::LiveDNS::Zone::Snapshot]
225
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
84
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
226
85
  def snapshot(uuid)
227
86
  GandiV5::LiveDNS::Zone::Snapshot.fetch self.uuid, uuid
228
87
  end
229
88
 
230
89
  # Take a snapshot of this zone.
231
90
  # @return [GandiV5::LiveDNS::Zone::Snapshot]
232
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
91
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
233
92
  def take_snapshot
234
- data = GandiV5.post "#{url}/snapshots"
93
+ _response, data = GandiV5.post "#{url}/snapshots"
235
94
  snapshot data['uuid']
236
95
  end
237
96
 
238
97
  # Update this zone.
239
98
  # @param name [String, #to_s] new name for the zone.
240
99
  # @return [String] The confirmation message from Gandi.
241
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
100
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
242
101
  def update(name:)
243
- data = GandiV5.patch url, { name: name }.to_json
102
+ _response, data = GandiV5.patch url, { name: name }.to_json
244
103
  self.name = name
245
104
  data['message']
246
105
  end
247
106
 
248
107
  # Delete this zone from Gandi.
249
108
  # @return [nil]
250
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
109
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
251
110
  def delete
252
111
  GandiV5.delete url
253
112
  end
@@ -255,34 +114,34 @@ class GandiV5
255
114
  # Create a new zone.
256
115
  # @param name [String] the name for the created zone.
257
116
  # @param sharing_id [String] the UUID of the account to ceate the zone under.
258
- # @return [String] The confirmation message from Gandi.
259
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
260
- # TODO: Fetch created zone
117
+ # @return [GandiV5::LiveDNS::Zone] The created zone.
118
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
261
119
  def self.create(name, sharing_id: nil)
262
120
  params = sharing_id ? { sharing_id: sharing_id } : {}
263
121
 
264
- data = GandiV5.post(
122
+ response, _data = GandiV5.post(
265
123
  url,
266
124
  { name: name }.to_json,
267
125
  params: params
268
126
  )
269
- data['message']
127
+
128
+ fetch response.headers[:location].split('/').last
270
129
  end
271
130
 
272
131
  # List the zones.
273
132
  # @return [Array<GandiV5::LiveDNS::Zone>]
274
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
133
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
275
134
  def self.list
276
- data = GandiV5.get url
135
+ _response, data = GandiV5.get url
277
136
  data.map { |item| from_gandi item }
278
137
  end
279
138
 
280
139
  # Get a zone from Gandi.
281
140
  # @param uuid [String, #to_s] the UUID of the zone to fetch.
282
141
  # @return [GandiV5::LiveDNS::Zone]
283
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
142
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
284
143
  def self.fetch(uuid)
285
- data = GandiV5.get url(uuid)
144
+ _response, data = GandiV5.get url(uuid)
286
145
  from_gandi data
287
146
  end
288
147