gandi_v5 0.2.0 → 0.3.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.
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,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,6 @@ 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] 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
- _response, 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] 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').last
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] 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 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] 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_).last
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] if Gandi returns an error.
150
- def replace_records(records: nil, text: nil)
151
- unless [records, text].one?(&:nil?)
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
- _response, data = GandiV5.put "#{url}/records", body
160
- elsif text
161
- _response, data = GandiV5.put "#{url}/records", text, 'content-type': 'text/plain'
162
- end
163
- data['message']
164
- end
165
-
166
- # @override replace_records_for(name, records)
167
- # Replace records for a name in this zone.
168
- # @param name [String]
169
- # @param records
170
- # [Array<Hash<type: String, ttl: Integer, values: Array<String>>>]
171
- # the records to add.
172
- # @override replace_records_for(name, values, type: nil, ttl: nil)
173
- # Replace records for a name in this zone.
174
- # @param name [String]
175
- # @param type [String] the record type.
176
- # @param ttl [Integer] the TTL to set for the record.
177
- # @param values [Array<String>] the values to set for the record.
178
- # @raise [ArgumentError] if ttl is present and type is absent.
179
- # @return [String] The confirmation message from Gandi.
180
- # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
181
- def replace_records_for(name, records, type: nil, ttl: nil)
182
- fail ArgumentError, 'missing keyword: type' if ttl && type.nil?
183
-
184
- if type
185
- GandiV5::LiveDNS.require_valid_record_type type
186
- body = { rrset_values: records, rrset_ttl: ttl }
187
- # body[:rrset_ttl] = ttl if ttl
188
- _response, data = GandiV5.put "#{url}/records/#{name}/#{type}", body.to_json
189
-
190
- else
191
- body = {
192
- items: records.map { |r| r.transform_keys { |k| "rrset_#{k}" } }
193
- }
194
- _response, data = GandiV5.put "#{url}/records/#{name}", body.to_json
195
- end
196
-
197
- data['message']
198
- end
199
-
200
55
  # List the domains that use this zone.
201
56
  # @return [Array<String>] The FQDNs.
202
57
  # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
@@ -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
  # The Organization API is a read-only API.
9
5
  # All organization management must be performed via the web interface.
@@ -59,8 +55,35 @@ class GandiV5
59
55
  # @return [GandiV5::Organization]
60
56
  # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
61
57
  def self.fetch
62
- _response, data = GandiV5.get "#{BASE}organization/user-info"
58
+ _response, data = GandiV5.get "#{url}/user-info"
63
59
  from_gandi data
64
60
  end
61
+
62
+ # List organisations.
63
+ # @see https://api.gandi.net/docs/domains#get-v5-organization-organizations
64
+ # @param name [String, #to_s] (optional)
65
+ # filters the list by name, with optional patterns.
66
+ # e.g. "alice", "ali*", "*ice"
67
+ # @param type [String, #to_s] (optional)
68
+ # filters the list by type of organization.
69
+ # One of: "individual", "company", "association", "publicbody"
70
+ # @param permission [String, #to_s] (optional)
71
+ # filters the list by the permission the authenticated user
72
+ # has on that organization and products in it.
73
+ # @param sort_by [String, #to_s] (optional default "name") how to sort the list.
74
+ # @return [Array<GandiV5::Organization>]
75
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
76
+ def self.list(**params)
77
+ params['~name'] = params.delete(:name) if params.key?(:name)
78
+ _resp, data = GandiV5.get "#{url}/organizations", params: params
79
+ data.map { |organisation| from_gandi organisation }
80
+ end
81
+
82
+ private
83
+
84
+ def self.url
85
+ "#{BASE}organization"
86
+ end
87
+ private_class_method :url
65
88
  end
66
89
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class GandiV5
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.0'
5
5
  end
@@ -1,4 +1,4 @@
1
1
  Metrics/BlockLength:
2
- Max: 500
2
+ Max: 750
3
3
  Metrics/LineLength:
4
4
  Max: 125
@@ -7,7 +7,7 @@ describe 'Domain features' do
7
7
  expect(list.count).to eq 1
8
8
  expect(list.first.fqdn).to eq 'example.net'
9
9
  expect(list.first.fqdn_unicode).to eq 'example.net'
10
- expect(list.first.name_servers).to be nil
10
+ expect(list.first.name_servers).to eq []
11
11
  expect(list.first.services).to be nil
12
12
  expect(list.first.sharing_space).to be nil
13
13
  expect(list.first.status).to match_array [:clientTransferProhibited]
@@ -0,0 +1,7 @@
1
+ ---
2
+ - name: ns1
3
+ fqdn: example.com
4
+ fqdn_unicode: example.com
5
+ href: http://api.test/v5/domain/domains/example.com/hosts/ns1
6
+ ips:
7
+ - '1.2.3.4'
@@ -0,0 +1,6 @@
1
+ ---
2
+ current: livedns
3
+ nameservers:
4
+ - '1.2.3.4'
5
+ dnssec_available: true
6
+ livednssec_available: true
@@ -7,6 +7,3 @@ renew:
7
7
  maximum: 2
8
8
  minimum: 1
9
9
  prohibited: false
10
- contracts:
11
- - id: uuid
12
- name: Name
@@ -18,3 +18,4 @@
18
18
  current: livedns
19
19
  href: https://api.gandi.net/v5/domain/domains/example.com
20
20
  fqdn_unicode: example.com
21
+ nameservers: []
@@ -0,0 +1,6 @@
1
+ ---
2
+ - source: alice
3
+ href: https://api.test/api/v5/email/forwards/example.com/alice
4
+ destinations:
5
+ - bob@example.com
6
+ - charlie@example.com
@@ -0,0 +1,7 @@
1
+ ---
2
+ - id: organization-uuid
3
+ name: FirstLast
4
+ corporate: false
5
+ firstname: First
6
+ lastname: Last
7
+ reseller: false
@@ -46,7 +46,8 @@ http_interactions:
46
46
  "current": "livedns"
47
47
  },
48
48
  "href": "https://api.test/v5/domain/domains/example.net",
49
- "fqdn_unicode": "example.net"
49
+ "fqdn_unicode": "example.net",
50
+ "nameservers": []
50
51
  }
51
52
  ]
52
53
  http_version:
@@ -13,12 +13,12 @@ allow_http_connections_to = %w[localhost 127.0.0.1]
13
13
 
14
14
  Dotenv.load File.join(__dir__, 'test.env')
15
15
 
16
- SimpleCov.coverage_dir(File.join('tmp', 'coverage'))
16
+ SimpleCov.coverage_dir(File.join('tmp', 'coverage')) unless ENV.key?('TRAVIS')
17
17
  SimpleCov.start do
18
18
  add_filter 'spec/'
19
19
  end
20
20
 
21
- if ENV['TRAVIS']
21
+ if ENV.key?('TRAVIS')
22
22
  Coveralls.wear!
23
23
  allow_http_connections_to.push 'coveralls.io'
24
24
  end
@@ -4,7 +4,7 @@ describe GandiV5::Billing do
4
4
  describe '.info' do
5
5
  subject { described_class.info }
6
6
  before :each do
7
- body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Billing', 'info.yaml'))
7
+ body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Billing', 'info.yml'))
8
8
  expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/billing/info')
9
9
  .and_return([nil, YAML.load_file(body_fixture)])
10
10
  end
@@ -23,7 +23,7 @@ describe GandiV5::Billing do
23
23
  describe '.info (for a sharing_id)' do
24
24
  subject { described_class.info('sharing-id') }
25
25
  before :each do
26
- body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Billing', 'info.yaml'))
26
+ body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Billing', 'info.yml'))
27
27
  expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/billing/info/sharing-id')
28
28
  .and_return([nil, YAML.load_file(body_fixture)])
29
29
  end
@@ -3,7 +3,7 @@
3
3
  describe GandiV5::Domain::Availability do
4
4
  describe '.fetch' do
5
5
  let(:body_fixture) do
6
- File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain_Availability', 'fetch.yaml'))
6
+ File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain_Availability', 'fetch.yml'))
7
7
  end
8
8
 
9
9
  describe 'With default values' do
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe GandiV5::Domain::LiveDNS do
4
+ describe '#classic?' do
5
+ it 'Is using classic DNS' do
6
+ expect(described_class.new(current: :classic).classic?).to be true
7
+ end
8
+
9
+ it 'Is using LiveDNS' do
10
+ expect(described_class.new(current: :livedns).classic?).to be false
11
+ end
12
+
13
+ it 'Is using custom DNS' do
14
+ expect(described_class.new(current: :custom).classic?).to be false
15
+ end
16
+ end
17
+
18
+ describe '#livedns?' do
19
+ it 'Is using classic DNS' do
20
+ expect(described_class.new(current: :classic).livedns?).to be false
21
+ end
22
+
23
+ it 'Is using LiveDNS' do
24
+ expect(described_class.new(current: :livedns).livedns?).to be true
25
+ end
26
+
27
+ it 'Is using custom DNS' do
28
+ expect(described_class.new(current: :custom).livedns?).to be false
29
+ end
30
+ end
31
+
32
+ describe '#custom?' do
33
+ it 'Is using classic DNS' do
34
+ expect(described_class.new(current: :classic).custom?).to be false
35
+ end
36
+
37
+ it 'Is using LiveDNS' do
38
+ expect(described_class.new(current: :livedns).custom?).to be false
39
+ end
40
+
41
+ it 'Is using custom DNS' do
42
+ expect(described_class.new(current: :custom).custom?).to be true
43
+ end
44
+ end
45
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  describe GandiV5::Domain::TLD do
4
4
  it '.list' do
5
- body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain_TLD', 'list.yaml'))
5
+ body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain_TLD', 'list.yml'))
6
6
  expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/domain/tlds')
7
7
  .and_return([nil, YAML.load_file(body_fixture)])
8
8
  expect(described_class.list.map(&:name)).to match_array %w[a b c]
@@ -12,7 +12,7 @@ describe GandiV5::Domain::TLD do
12
12
  subject { described_class.fetch 'name' }
13
13
 
14
14
  before(:each) do
15
- body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain_TLD', 'fetch.yaml'))
15
+ body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain_TLD', 'fetch.yml'))
16
16
  expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/domain/tlds/name')
17
17
  .and_return([nil, YAML.load_file(body_fixture)])
18
18
  end
@@ -4,7 +4,7 @@ describe GandiV5::Domain do
4
4
  subject { described_class.new fqdn: 'example.com' }
5
5
 
6
6
  describe '.list' do
7
- let(:body_fixture) { File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'list.yaml')) }
7
+ let(:body_fixture) { File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'list.yml')) }
8
8
 
9
9
  describe 'With default values' do
10
10
  subject { described_class.list }
@@ -19,7 +19,7 @@ describe GandiV5::Domain do
19
19
  its('first.uuid') { should eq 'domain-uuid' }
20
20
  its('first.fqdn') { should eq 'example.com' }
21
21
  its('first.fqdn_unicode') { should eq 'example.com' }
22
- its('first.name_servers') { should be_nil }
22
+ its('first.name_servers') { should eq [] }
23
23
  its('first.services') { should be_nil }
24
24
  its('first.status') { should eq [] }
25
25
  its('first.tld') { should eq 'com' }
@@ -89,7 +89,7 @@ describe GandiV5::Domain do
89
89
  subject { described_class.fetch 'example.com' }
90
90
 
91
91
  before :each do
92
- body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'get.yaml'))
92
+ body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'fetch.yml'))
93
93
  expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/domain/domains/example.com')
94
94
  .and_return([nil, YAML.load_file(body_fixture)])
95
95
  end
@@ -128,13 +128,13 @@ describe GandiV5::Domain do
128
128
 
129
129
  describe '.create' do
130
130
  let(:url) { 'https://api.gandi.net/v5/domain/domains' }
131
+ let(:returns) { double described_class }
132
+ let(:response) { double RestClient::Response, headers: { location: 'https://api.gandi.net/v5/domains/example.com' } }
131
133
 
132
134
  describe 'Sets dry-run header' do
133
135
  let(:body) { '{"owner":{},"fqdn":"example.com"}' }
134
136
 
135
137
  it 'False by default' do
136
- returns = double described_class
137
- response = double RestClient::Response, headers: { location: 'https://api.gandi.net/v5/domains/example.com' }
138
138
  expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 0).and_return([response, nil])
139
139
  expect(described_class).to receive(:fetch).with('example.com').and_return(returns)
140
140
  described_class.create 'example.com', owner: {}
@@ -146,8 +146,6 @@ describe GandiV5::Domain do
146
146
  end
147
147
 
148
148
  it 'False' do
149
- returns = double described_class
150
- response = double RestClient::Response, headers: { location: 'https://api.gandi.net/v5/domains/example.com' }
151
149
  expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 0).and_return([response, nil])
152
150
  expect(described_class).to receive(:fetch).with('example.com').and_return(returns)
153
151
  described_class.create 'example.com', owner: {}, dry_run: false
@@ -171,12 +169,29 @@ describe GandiV5::Domain do
171
169
  end
172
170
  end
173
171
 
172
+ describe 'Sets sharing_id' do
173
+ it 'Absent by default' do
174
+ expect(GandiV5).to receive(:post).with(url, any_args).and_return([response, nil])
175
+ expect(described_class).to receive(:fetch).with('example.com').and_return(returns)
176
+ described_class.create('example.com', owner: {})
177
+ end
178
+
179
+ it 'Paying as another organization' do
180
+ expect(GandiV5).to receive(:post).with("#{url}?sharing_id=organization_id", any_args).and_return([response, nil])
181
+ expect(described_class).to receive(:fetch).with('example.com').and_return(returns)
182
+ described_class.create('example.com', sharing_id: 'organization_id', owner: {})
183
+ end
184
+
185
+ it 'Buy as a reseller' do
186
+ expect(GandiV5).to receive(:post).with("#{url}?sharing_id=reseller_id", any_args).and_return([response, nil])
187
+ expect(described_class).to receive(:fetch).with('example.com').and_return(returns)
188
+ described_class.create('example.com', sharing_id: 'reseller_id', owner: {})
189
+ end
190
+ end
191
+
174
192
  it 'Success' do
175
- returns = double described_class
176
- response = double RestClient::Response, headers: { location: 'https://api.gandi.net/v5/domains/example.com' }
177
193
  body = '{"owner":{},"fqdn":"example.com"}'
178
- expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 0)
179
- .and_return([response, nil])
194
+ expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 0).and_return([response, nil])
180
195
  expect(described_class).to receive(:fetch).with('example.com').and_return(returns)
181
196
  expect(described_class.create('example.com', owner: {})).to be returns
182
197
  end
@@ -186,18 +201,14 @@ describe GandiV5::Domain do
186
201
  end
187
202
 
188
203
  it 'Given contact as hash' do
189
- returns = double described_class
190
204
  body = '{"owner":{"email":"owner@example.com"},"fqdn":"example.com"}'
191
- response = double RestClient::Response, headers: { location: 'https://api.gandi.net/v5/domains/example.com' }
192
205
  expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 0).and_return([response, nil])
193
206
  expect(described_class).to receive(:fetch).with('example.com').and_return(returns)
194
207
  described_class.create 'example.com', owner: { email: 'owner@example.com' }
195
208
  end
196
209
 
197
210
  it 'Given contact as GandiV5::Domain::Contact' do
198
- returns = double described_class
199
211
  body = '{"owner":{"email":"owner@example.com"},"fqdn":"example.com"}'
200
- response = double RestClient::Response, headers: { location: 'https://api.gandi.net/v5/domains/example.com' }
201
212
  expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 0).and_return([response, nil])
202
213
  expect(described_class).to receive(:fetch).with('example.com').and_return(returns)
203
214
  owner = double GandiV5::Domain::Contact, to_gandi: { 'email' => 'owner@example.com' }
@@ -205,6 +216,24 @@ describe GandiV5::Domain do
205
216
  end
206
217
  end
207
218
 
219
+ it '.mailboxes' do
220
+ returns = double Array
221
+ expect(GandiV5::Email::Mailbox).to receive(:list).with(param: :value, fqdn: 'example.com').and_return(returns)
222
+ expect(subject.mailboxes(param: :value)).to be returns
223
+ end
224
+
225
+ it '.mailbox_slots' do
226
+ returns = double Array
227
+ expect(GandiV5::Email::Slot).to receive(:list).with(param: :value, fqdn: 'example.com').and_return(returns)
228
+ expect(subject.mailbox_slots(param: :value)).to be returns
229
+ end
230
+
231
+ it '.email_forwards' do
232
+ returns = double Array
233
+ expect(GandiV5::Email::Forward).to receive(:list).with(param: :value, fqdn: 'example.com').and_return(returns)
234
+ expect(subject.email_forwards(param: :value)).to be returns
235
+ end
236
+
208
237
  describe '#to_s' do
209
238
  it 'Has identical fqdn and fqdn_unicode' do
210
239
  domain = described_class.new fqdn: 'example.com', fqdn_unicode: 'example.com'
@@ -219,7 +248,7 @@ describe GandiV5::Domain do
219
248
 
220
249
  describe '#refresh' do
221
250
  before :each do
222
- body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'get.yaml'))
251
+ body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'fetch.yml'))
223
252
  expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/domain/domains/example.com')
224
253
  .and_return([nil, YAML.load_file(body_fixture)])
225
254
  subject.refresh
@@ -275,7 +304,7 @@ describe GandiV5::Domain do
275
304
  subject { described_class.new(fqdn: 'example.com').fetch_contacts }
276
305
 
277
306
  before(:each) do
278
- body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'fetch_contacts.yaml'))
307
+ body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'fetch_contacts.yml'))
279
308
  expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/domain/domains/example.com/contacts')
280
309
  .and_return([nil, YAML.load_file(body_fixture)])
281
310
  end
@@ -332,7 +361,7 @@ describe GandiV5::Domain do
332
361
  subject { described_class.new(fqdn: 'example.com').fetch_renewal_information }
333
362
 
334
363
  before(:each) do
335
- body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'renewal_info.yaml'))
364
+ body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'fetch_renewal_info.yml'))
336
365
  expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/domain/domains/example.com/renew')
337
366
  .and_return([nil, YAML.load_file(body_fixture)])
338
367
  end
@@ -342,9 +371,6 @@ describe GandiV5::Domain do
342
371
  its('minimum') { should eq 1 }
343
372
  its('maximum') { should eq 2 }
344
373
  its('durations') { should match_array [1, 2] }
345
- its('contracts.count') { should eq 1 }
346
- its('contracts.first.id') { should eq 'uuid' }
347
- its('contracts.first.name') { should eq 'Name' }
348
374
  end
349
375
 
350
376
  it '#renew_for' do
@@ -428,7 +454,8 @@ describe GandiV5::Domain do
428
454
 
429
455
  describe 'Information is available' do
430
456
  before(:each) do
431
- body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'restore_info.yaml'))
457
+ body_fixture = File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'fetch_restore_info.yml')
458
+ body_fixture = File.expand_path(body_fixture)
432
459
  expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/domain/domains/example.com/restore')
433
460
  .and_return([nil, YAML.load_file(body_fixture)])
434
461
  end
@@ -456,4 +483,196 @@ describe GandiV5::Domain do
456
483
  expect(subject.restore).to eq 'Confirmation message.'
457
484
  end
458
485
  end
486
+
487
+ describe '#glue_records' do
488
+ let(:glue_records) { double Hash }
489
+
490
+ it 'Already fetched' do
491
+ subject.instance_exec(glue_records) { |glue_records| @glue_records = glue_records }
492
+ expect(subject).to_not receive(:fetch_glue_records)
493
+ expect(subject.glue_records).to be glue_records
494
+ end
495
+
496
+ it 'Not already fetched' do
497
+ expect(subject).to receive(:fetch_glue_records).and_return(glue_records)
498
+ expect(subject.glue_records).to be glue_records
499
+ end
500
+ end
501
+
502
+ it '#fetch_glue_records' do
503
+ body_fixture = File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'fetch_glue_records.yml')
504
+ body_fixture = File.expand_path(body_fixture)
505
+ expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/domain/domains/example.com/hosts')
506
+ .and_return([nil, YAML.load_file(body_fixture)])
507
+ expect(subject.fetch_glue_records).to eq(
508
+ 'ns1' => ['1.2.3.4']
509
+ )
510
+ end
511
+
512
+ describe '#add_glue_record' do
513
+ before(:each) { described_class.instance_exec { @glue_records = {} } }
514
+
515
+ it 'Make API request' do
516
+ expect(GandiV5).to receive(:post).with(
517
+ 'https://api.gandi.net/v5/domain/domains/example.com/hosts',
518
+ '{"name":"ns1","ips":["1.2.3.4"]}'
519
+ )
520
+ .and_return([nil, { 'message' => 'Confirmation message.' }])
521
+ expect(subject.add_glue_record('ns1', '1.2.3.4')).to eq 'Confirmation message.'
522
+ end
523
+
524
+ it 'Updates glue records' do
525
+ expect(GandiV5).to receive(:post).and_return([nil, { 'message' => 'Confirmation message.' }])
526
+ subject.add_glue_record 'ns1', '1.2.3.4'
527
+ expect(subject.glue_records).to eq('ns1' => ['1.2.3.4'])
528
+ end
529
+ end
530
+
531
+ describe '#glue_record' do
532
+ before(:each) { subject.instance_exec { @glue_records = { 'ns1' => ['1.2.3.4'] } } }
533
+
534
+ it 'Already fetched' do
535
+ expect(subject).to_not receive(:fetch_glue_records)
536
+ expect(subject.glue_record('ns1')).to eq('ns1' => ['1.2.3.4'])
537
+ end
538
+
539
+ it 'Not already fetched' do
540
+ expect(subject).to receive(:fetch_glue_records).and_return('ns2' => ['2.3.4.5'])
541
+ expect(subject.glue_record('ns2')).to eq('ns2' => ['2.3.4.5'])
542
+ end
543
+
544
+ it 'Not present' do
545
+ expect(subject).to receive(:fetch_glue_records).and_return({})
546
+ expect(subject.glue_record('ns3')).to be nil
547
+ end
548
+ end
549
+
550
+ describe '#update_glue_record' do
551
+ it 'Make API request' do
552
+ expect(GandiV5).to receive(:put).with(
553
+ 'https://api.gandi.net/v5/domain/domains/example.com/hosts/name',
554
+ '{"ips":["1.2.3.4"]}'
555
+ )
556
+ .and_return([nil, { 'message' => 'Confirmation message.' }])
557
+ expect(subject.update_glue_record('name', '1.2.3.4')).to eq 'Confirmation message.'
558
+ end
559
+
560
+ it 'Update name_servers' do
561
+ expect(GandiV5).to receive(:put).and_return([nil, { 'message' => 'Confirmation message.' }])
562
+ subject.update_glue_record 'name', '1.2.3.4'
563
+ expect(subject.glue_records).to eq('name' => ['1.2.3.4'])
564
+ end
565
+ end
566
+
567
+ describe '#delete_glue_record' do
568
+ before(:each) { subject.instance_exec { @glue_records = { 'ns1' => ['1.2.3.4'], 'ns2' => [] } } }
569
+
570
+ it 'Make API request' do
571
+ expect(GandiV5).to receive(:delete).with(
572
+ 'https://api.gandi.net/v5/domain/domains/example.com/hosts/ns2'
573
+ )
574
+ .and_return([nil, { 'message' => 'Confirmation message.' }])
575
+ expect(subject.delete_glue_record('ns2')).to eq 'Confirmation message.'
576
+ end
577
+
578
+ it 'Update name_servers' do
579
+ expect(GandiV5).to receive(:delete).and_return([nil, { 'message' => 'Confirmation message.' }])
580
+ subject.delete_glue_record 'ns2'
581
+ expect(subject.glue_records).to eq('ns1' => ['1.2.3.4'])
582
+ end
583
+ end
584
+
585
+ describe '#livedns' do
586
+ let(:live_dns) { double GandiV5::Domain::LiveDNS }
587
+
588
+ it 'Already fetched' do
589
+ subject.instance_exec(live_dns) { |live_dns| @livedns = live_dns }
590
+ expect(subject).to_not receive(:fetch_livedns)
591
+ expect(subject.livedns).to be live_dns
592
+ end
593
+
594
+ it 'Not already fetched' do
595
+ expect(subject).to receive(:fetch_livedns).and_return(live_dns)
596
+ expect(subject.livedns).to be live_dns
597
+ end
598
+ end
599
+
600
+ describe '#fetch_livedns' do
601
+ before(:each) do
602
+ body_fixture = File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'fetch_livedns.yml')
603
+ body_fixture = File.expand_path(body_fixture)
604
+ expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/domain/domains/example.com/livedns')
605
+ .and_return([nil, YAML.load_file(body_fixture)])
606
+ end
607
+
608
+ describe 'Returned live_dns' do
609
+ subject { described_class.new(fqdn: 'example.com').fetch_livedns }
610
+
611
+ its('current') { should be :livedns }
612
+ its('name_servers') { should match_array ['1.2.3.4'] }
613
+ its('dnssec_available') { should be true }
614
+ its('livednssec_available') { should be true }
615
+ end
616
+
617
+ it 'Updates name_server' do
618
+ expect(subject.name_server).to be nil
619
+ subject.fetch_livedns
620
+ expect(subject.name_server).to be :livedns
621
+ end
622
+
623
+ it 'Updates name_servers' do
624
+ subject.instance_exec { @name_servers = [] }
625
+ subject.fetch_livedns
626
+ expect(subject.name_servers).to match_array ['1.2.3.4']
627
+ end
628
+ end
629
+
630
+ it '#enable_livedns' do
631
+ expect(GandiV5).to receive(:post).with('https://api.gandi.net/v5/domain/domains/example.com/livedns')
632
+ .and_return([nil, { 'message' => 'Confirmation message.' }])
633
+ expect(subject.enable_livedns).to eq 'Confirmation message.'
634
+ end
635
+
636
+ describe '#name_servers' do
637
+ let(:nameservers) { double Array }
638
+
639
+ it 'Already fetched' do
640
+ subject.instance_exec(nameservers) { |nameservers| @name_servers = nameservers }
641
+ expect(subject).to_not receive(:fetch_name_servers)
642
+ expect(subject.name_servers).to be nameservers
643
+ end
644
+
645
+ it 'Not already fetched' do
646
+ expect(subject).to receive(:fetch_name_servers).and_return(nameservers)
647
+ expect(subject.name_servers).to be nameservers
648
+ end
649
+ end
650
+
651
+ it '#fetch_name_servers' do
652
+ body_fixture = File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain', 'fetch_name_servers.yml')
653
+ body_fixture = File.expand_path(body_fixture)
654
+ expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/domain/domains/example.com/nameservers')
655
+ .and_return([nil, YAML.load_file(body_fixture)])
656
+ expect(subject.fetch_name_servers).to match_array ['1.2.3.4']
657
+ end
658
+
659
+ describe '#update_name_servers' do
660
+ subject { described_class.new fqdn: 'example.com', name_servers: [] }
661
+ let(:new_name_servers) { ['a.examle.com', 'b.example.net'] }
662
+
663
+ it 'Make API request' do
664
+ expect(GandiV5).to receive(:put).with(
665
+ 'https://api.gandi.net/v5/domain/domains/example.com/nameservers',
666
+ '{"nameservers":["a.examle.com","b.example.net"]}'
667
+ )
668
+ .and_return([nil, { 'message' => 'Confirmation message.' }])
669
+ expect(subject.update_name_servers(new_name_servers)).to eq 'Confirmation message.'
670
+ end
671
+
672
+ it 'Update name_servers' do
673
+ expect(GandiV5).to receive(:put).and_return([nil, { 'message' => 'Confirmation message.' }])
674
+ subject.update_name_servers new_name_servers
675
+ expect(subject.name_servers).to be new_name_servers
676
+ end
677
+ end
459
678
  end