gandi_v5 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -9
  3. data/README.md +54 -10
  4. data/lib/gandi_v5.rb +112 -66
  5. data/lib/gandi_v5/billing/info/prepaid.rb +1 -0
  6. data/lib/gandi_v5/data.rb +1 -0
  7. data/lib/gandi_v5/data/converter.rb +3 -2
  8. data/lib/gandi_v5/data/converter/array_of.rb +3 -2
  9. data/lib/gandi_v5/data/converter/integer.rb +3 -2
  10. data/lib/gandi_v5/data/converter/symbol.rb +3 -2
  11. data/lib/gandi_v5/data/converter/time.rb +3 -2
  12. data/lib/gandi_v5/domain.rb +9 -6
  13. data/lib/gandi_v5/domain/availability/product/period.rb +1 -1
  14. data/lib/gandi_v5/domain/contact.rb +5 -5
  15. data/lib/gandi_v5/domain/tld.rb +2 -2
  16. data/lib/gandi_v5/domain/transfer_in.rb +170 -0
  17. data/lib/gandi_v5/domain/transfer_in/availability.rb +51 -0
  18. data/lib/gandi_v5/email.rb +1 -0
  19. data/lib/gandi_v5/email/mailbox.rb +1 -1
  20. data/lib/gandi_v5/error/gandi_error.rb +1 -0
  21. data/lib/gandi_v5/live_dns.rb +2 -0
  22. data/lib/gandi_v5/live_dns/domain.rb +28 -1
  23. data/lib/gandi_v5/live_dns/domain/dnssec_key.rb +16 -11
  24. data/lib/gandi_v5/live_dns/domain/snapshot.rb +4 -0
  25. data/lib/gandi_v5/live_dns/domain/tsig_key.rb +7 -4
  26. data/lib/gandi_v5/simple_hosting.rb +1 -0
  27. data/lib/gandi_v5/simple_hosting/instance.rb +3 -0
  28. data/lib/gandi_v5/simple_hosting/instance/application.rb +1 -0
  29. data/lib/gandi_v5/simple_hosting/instance/database.rb +1 -0
  30. data/lib/gandi_v5/simple_hosting/instance/language.rb +1 -1
  31. data/lib/gandi_v5/simple_hosting/instance/upgrade.rb +1 -0
  32. data/lib/gandi_v5/simple_hosting/instance/virtual_host.rb +2 -2
  33. data/lib/gandi_v5/simple_hosting/instance/virtual_host/linked_dns_zone.rb +1 -0
  34. data/lib/gandi_v5/version.rb +1 -1
  35. data/spec/features/list_domain_renewals_spec.rb +16 -0
  36. data/spec/features/list_email_addresses_spec.rb +39 -0
  37. data/spec/fixtures/bodies/GandiV5_Domain_TransferIn/fetch.yml +21 -0
  38. data/spec/fixtures/bodies/GandiV5_Domain_TransferIn_Availability/fetch.yml +10 -0
  39. data/spec/fixtures/vcr/Examples/List_domain_renewals.yml +54 -0
  40. data/spec/fixtures/vcr/Examples/List_email_addresses.yml +103 -0
  41. data/spec/units/gandi_v5/domain/transfer_in/availability_spec.rb +49 -0
  42. data/spec/units/gandi_v5/domain/transfer_in_spec.rb +143 -0
  43. metadata +127 -20
  44. data/.gitignore +0 -26
  45. data/.rspec +0 -3
  46. data/.rubocop.yml +0 -74
  47. data/.travis.yml +0 -38
  48. data/FUNDING.yml +0 -10
  49. data/Gemfile +0 -6
  50. data/Guardfile +0 -39
  51. data/Rakefile +0 -3
  52. data/bin/console +0 -13
  53. data/gandi_v5.gemspec +0 -42
@@ -4,6 +4,7 @@ class GandiV5
4
4
  class SimpleHosting
5
5
  class Instance
6
6
  class VirtualHost
7
+ # A DNS Zone linked to a virtual host on a simple hosting instance.
7
8
  # @!attribute [r] allow_zone_alteration
8
9
  # @return [Boolean]
9
10
  # @!attribute [r] cname
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class GandiV5
4
- VERSION = '0.8.0'
4
+ VERSION = '0.9.0'
5
5
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe 'Examples', :vcr do
4
+ it 'List domain renewals' do
5
+ expect(STDOUT).to receive(:puts).with("2021-03-12\t£8.87\texample.com")
6
+
7
+ # For each domain (sorted by assending renewal date) print <date>\t<cost>\t<fqdn>
8
+ GandiV5::Domain.list.each do |domain|
9
+ puts [
10
+ domain.dates.registry_ends_at.to_date,
11
+ "£#{domain.renewal_price.price_after_taxes}",
12
+ domain.fqdn
13
+ ].join("\t")
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe 'Examples', :vcr do
4
+ it 'List email addresses' do
5
+ expect(STDOUT).to receive(:puts).with("alias@example.com\talias for user@example.com").ordered
6
+ expect(STDOUT).to receive(:puts).with("forward@example.com\tforwards to user@example.com").ordered
7
+ expect(STDOUT).to receive(:puts).with("user@example.com\tstandard mailbox (0% of 3GB used)").ordered
8
+
9
+ # For each domain:
10
+ # 1. Create an empty hash to store address => description
11
+ # 2. Get the mailboxes and add them to the hash
12
+ # 3. Get the forwards and add them to the hash
13
+ # 4. Sort the hash by email address
14
+ # 5. Print the list
15
+ GandiV5::Domain.list.each do |domain|
16
+ emails = {}
17
+
18
+ mailboxes = GandiV5::Email::Mailbox.list(domain.fqdn)
19
+ mailboxes.each do |mailbox|
20
+ mailbox.refresh
21
+ emails["#{mailbox.login}@#{domain.fqdn}"] = "#{mailbox.type} mailbox " \
22
+ "(#{mailbox.quota_usage.to_i}% " \
23
+ "of #{(mailbox.quota / 1024**3).round}GB used)"
24
+ mailbox.aliases.each do |alias_name|
25
+ emails["#{alias_name}@#{domain.fqdn}"] = "alias for #{mailbox.login}@#{domain.fqdn}"
26
+ end
27
+ end
28
+
29
+ forwards = GandiV5::Email::Forward.list(domain.fqdn)
30
+ forwards.each do |forward|
31
+ emails["#{forward.source}@#{domain.fqdn}"] = "forwards to #{forward.destinations.join(', ')}"
32
+ end
33
+
34
+ emails.sort.each do |address, text|
35
+ puts "#{address}\t#{text}"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,21 @@
1
+ ---
2
+ created_at: '2011-02-21T10:39:00Z'
3
+ owner_contact: owner contact
4
+ params:
5
+ domain: example.com
6
+ duration: 1
7
+ reseller: reseller-uuid
8
+ tld: com
9
+ version: 0
10
+ step: step text
11
+ step_nb: 2
12
+ updated_at: '2011-02-22T10:39:00Z'
13
+ errortype: error-type
14
+ errortype_label: error label
15
+ foa:
16
+ - answer: ans
17
+ email: user@example.com
18
+ inner_step: inner-step
19
+ regac_at: '2011-02-23T10:39:00Z'
20
+ start_at: '2011-02-24T10:39:00Z'
21
+ transfer_procedure: transfer-procedure
@@ -0,0 +1,10 @@
1
+ ---
2
+ available: true
3
+ fqdn: example.com
4
+ fqdn_ulabel: EXAMPLE.COM
5
+ corporate: false
6
+ internal: false
7
+ durations: [1, 2, 3]
8
+ minimum_duration: 1
9
+ maximum_duration: 3
10
+ msg: This is a message
@@ -0,0 +1,54 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.gandi.net/v5/domain/domains?page=1&per_page=100
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/json
12
+ Authorization:
13
+ - Apikey abdce12345
14
+ response:
15
+ status:
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ Content-Type:
20
+ - application/json; charset=utf-8
21
+ Content-Length:
22
+ - '461'
23
+ body:
24
+ encoding: UTF-8
25
+ string: '[{"status":[],"dates":{"created_at":"2011-02-21T10:39:00Z","registry_created_at":"2003-03-12T12:02:11Z","registry_ends_at":"2021-03-12T12:02:11Z","updated_at":"2020-03-25T17:06:34Z"},"tags":[],"fqdn":"example.com","id":"domain-uuid","autorenew":false,"tld":"com","owner":"Mr. Example","orga_owner":"Example Org","domain_owner":"Owner","nameserver":{"current":"livedns"},"href":"https://api.gandi.net/v5/domain/domains/example.com","fqdn_unicode":"example.com"}]'
26
+ recorded_at: Mon, 17 Aug 2020 16:02:51 GMT
27
+
28
+ - request:
29
+ method: get
30
+ uri: https://api.gandi.net/v5/domain/check?currency=GBP&name=example.com&period=1&processes%5B%5D=renew
31
+ body:
32
+ encoding: US-ASCII
33
+ string: ''
34
+ headers:
35
+ Accept:
36
+ - application/json
37
+ Authorization:
38
+ - Apikey abcde12345
39
+ response:
40
+ status:
41
+ code: 200
42
+ message: OK
43
+ headers:
44
+ Content-Type:
45
+ - application/json; charset=utf-8
46
+ Content-Length:
47
+ - '353'
48
+ body:
49
+ encoding: UTF-8
50
+ string: '{"currency":"GBP","products":[{"name":"example.com","taxes":[{"rate":20,"name":"vat","type":"service"}],"process":"renew","prices":[{"min_duration":1,"discount":false,"price_after_taxes":8.87,"max_duration":9,"price_before_taxes":7.39,"duration_unit":"y"}],"status":"unavailable"}],"grid":"A","taxes":[{"rate":20,"name":"vat","type":"service"}]}'
51
+ http_version:
52
+ recorded_at: Mon, 17 Aug 2020 16:53:54 GMT
53
+
54
+ recorded_with: VCR 4.0.0
@@ -0,0 +1,103 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.gandi.net/v5/domain/domains?page=1&per_page=100
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/json
12
+ Authorization:
13
+ - Apikey abdce12345
14
+ response:
15
+ status:
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ Content-Type:
20
+ - application/json; charset=utf-8
21
+ Content-Length:
22
+ - '461'
23
+ body:
24
+ encoding: UTF-8
25
+ string: '[{"status":[],"dates":{"created_at":"2011-02-21T10:39:00Z","registry_created_at":"2003-03-12T12:02:11Z","registry_ends_at":"2021-03-12T12:02:11Z","updated_at":"2020-03-25T17:06:34Z"},"tags":[],"fqdn":"example.com","id":"domain-uuid","autorenew":false,"tld":"com","owner":"Mr. Example","orga_owner":"Example Org","domain_owner":"Owner","nameserver":{"current":"livedns"},"href":"https://api.gandi.net/v5/domain/domains/example.com","fqdn_unicode":"example.com"}]'
26
+ recorded_at: Mon, 17 Aug 2020 16:02:51 GMT
27
+
28
+ - request:
29
+ method: get
30
+ uri: https://api.gandi.net/v5/email/mailboxes/example.com?page=1&per_page=100
31
+ body:
32
+ encoding: US-ASCII
33
+ string: ''
34
+ headers:
35
+ Accept:
36
+ - application/json
37
+ Authorization:
38
+ - Apikey abdce12345
39
+ response:
40
+ status:
41
+ code: 200
42
+ message: OK
43
+ headers:
44
+ Content-Type:
45
+ - application/json; charset=utf-8
46
+ Content-Length:
47
+ - '284'
48
+ body:
49
+ encoding: UTF-8
50
+ string: '[{"responder":{"message":"","enabled":false},"mailbox_type":"standard","login":"user","quota_used":3597,"domain":"example.com","aliases":["alias"],"address":"user@example.com","href":"https://api.gandi.net/v5/email/mailboxes/example.com/mailbox-uuid","id":"mailbox-uuid"}]'
51
+ recorded_at: Mon, 17 Aug 2020 16:02:51 GMT
52
+
53
+ - request:
54
+ method: get
55
+ uri: https://api.gandi.net/v5/email/mailboxes/example.com/mailbox-uuid
56
+ body:
57
+ encoding: US-ASCII
58
+ string: ''
59
+ headers:
60
+ Accept:
61
+ - application/json
62
+ Authorization:
63
+ - Apikey abdce12345
64
+ response:
65
+ status:
66
+ code: 200
67
+ message: OK
68
+ headers:
69
+ Content-Type:
70
+ - application/json; charset=utf-8
71
+ Content-Length:
72
+ - '270'
73
+ body:
74
+ encoding: UTF-8
75
+ string: '{"responder":{"message":"","enabled":false},"mailbox_type":"standard","login":"user","quota_used":3597,"domain":"example.com","aliases":["alias"],"address":"user@example.com","href":"https://api.gandi.net/v5/email/mailboxes/example.com/mailbox-uuid","id":"mailbox-uuid"}'
76
+ recorded_at: Mon, 17 Aug 2020 16:17:50 GMT
77
+
78
+ - request:
79
+ method: get
80
+ uri: https://api.gandi.net/v5/email/forwards/example.com?page=1&per_page=100
81
+ body:
82
+ encoding: US-ASCII
83
+ string: ''
84
+ headers:
85
+ Accept:
86
+ - application/json
87
+ Authorization:
88
+ - Apikey abdce12345
89
+ response:
90
+ status:
91
+ code: 200
92
+ message: OK
93
+ headers:
94
+ Content-Type:
95
+ - application/json; charset=utf-8
96
+ Content-Length:
97
+ - '127'
98
+ body:
99
+ encoding: UTF-8
100
+ string: '[{"destinations":["user@example.com"],"source":"forward","href":"https://api.gandi.net/v5/email/forwards/example.com/forward"}]'
101
+ recorded_at: Mon, 17 Aug 2020 16:02:52 GMT
102
+
103
+ recorded_with: VCR 4.0.0
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe GandiV5::Domain::TransferIn::Availability do
4
+ describe '.fetch' do
5
+ let(:body_fixture) do
6
+ File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain_TransferIn_Availability', 'fetch.yml'))
7
+ end
8
+
9
+ describe 'Without auth_code' do
10
+ subject { described_class.fetch 'example.com' }
11
+
12
+ before(:each) do
13
+ url = 'https://api.gandi.net/v5/domain/transferin/example.com/available'
14
+ expect(GandiV5).to receive(:post).with(url, {})
15
+ .and_return([nil, YAML.load_file(body_fixture)])
16
+ end
17
+
18
+ its('available') { should be true }
19
+ its('fqdn') { should eq 'example.com' }
20
+ its('fqdn_unicode') { should eq 'EXAMPLE.COM' }
21
+ its('corporate') { should be false }
22
+ its('internal') { should be false }
23
+ its('durations') { should eq [1, 2, 3] }
24
+ its('minimum_duration') { should eq 1 }
25
+ its('maximum_duration') { should eq 3 }
26
+ its('message') { should eq 'This is a message' }
27
+ end
28
+
29
+ describe 'With auth_code' do
30
+ subject { described_class.fetch 'example.com', 'auth-code' }
31
+
32
+ before(:each) do
33
+ url = 'https://api.gandi.net/v5/domain/transferin/example.com/available'
34
+ expect(GandiV5).to receive(:post).with(url, { 'authinfo' => 'auth-code' })
35
+ .and_return([nil, YAML.load_file(body_fixture)])
36
+ end
37
+
38
+ its('available') { should be true }
39
+ its('fqdn') { should eq 'example.com' }
40
+ its('fqdn_unicode') { should eq 'EXAMPLE.COM' }
41
+ its('corporate') { should be false }
42
+ its('internal') { should be false }
43
+ its('durations') { should eq [1, 2, 3] }
44
+ its('minimum_duration') { should eq 1 }
45
+ its('maximum_duration') { should eq 3 }
46
+ its('message') { should eq 'This is a message' }
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe GandiV5::Domain::TransferIn do
4
+ subject { described_class.new fqdn: 'example.com' }
5
+
6
+ describe '.fetch' do
7
+ subject { described_class.fetch 'example.com' }
8
+
9
+ before :each do
10
+ body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Domain_TransferIn', 'fetch.yml'))
11
+ expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/domain/transferin/example.com')
12
+ .and_return([nil, YAML.load_file(body_fixture)])
13
+ end
14
+
15
+ its('fqdn') { should eq 'example.com' }
16
+ its('created_at') { should eq Time.new(2011, 2, 21, 10, 39, 0, 0) }
17
+ its('owner_contact') { should eq 'owner contact' }
18
+ its('duration') { should eq 1 }
19
+ its('reseller_uuid') { should eq 'reseller-uuid' }
20
+ its('version') { should eq 0 }
21
+ its('step') { should eq 'step text' }
22
+ its('step_number') { should eq 2 }
23
+ its('updated_at') { should eq Time.new(2011, 2, 22, 10, 39, 0, 0) }
24
+ its('errortype') { should eq 'error-type' }
25
+ its('errortype_label') { should eq 'error label' }
26
+ its('inner_step') { should eq 'inner-step' }
27
+ its('regac_at') { should eq Time.new(2011, 2, 23, 10, 39, 0, 0) }
28
+ its('start_at') { should eq Time.new(2011, 2, 24, 10, 39, 0, 0) }
29
+ its('transfer_procedure') { should eq 'transfer-procedure' }
30
+ its('foa_status') { should eq({ 'user@example.com' => 'ans' }) }
31
+ end
32
+
33
+ describe '.create' do
34
+ let(:url) { 'https://api.gandi.net/v5/domain/transferin' }
35
+
36
+ describe 'Sets dry-run header' do
37
+ let(:body) { '{"owner":{},"fqdn":"example.com"}' }
38
+
39
+ it 'False by default' do
40
+ expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 0).and_return([nil, { 'message' => 'confirmation' }])
41
+ described_class.create 'example.com', owner: {}
42
+ end
43
+
44
+ it 'True' do
45
+ expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 1).and_return([nil, nil])
46
+ described_class.create 'example.com', owner: {}, dry_run: true
47
+ end
48
+
49
+ it 'False' do
50
+ expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 0).and_return([nil, { 'message' => 'confirmation' }])
51
+ described_class.create 'example.com', owner: {}, dry_run: false
52
+ end
53
+
54
+ it 'Dry run was successful' do
55
+ returns = { 'status' => 'success' }
56
+ expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 1)
57
+ .and_return([nil, returns])
58
+ expect(described_class.create('example.com', owner: {}, dry_run: true)).to be returns
59
+ end
60
+
61
+ it 'Dry run has errors' do
62
+ returns = {
63
+ 'status' => 'error',
64
+ 'errors' => [{ 'description' => 'd', 'location' => 'l', 'name' => 'n' }]
65
+ }
66
+ expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 1)
67
+ .and_return([nil, returns])
68
+ expect(described_class.create('example.com', owner: {}, dry_run: true)).to be returns
69
+ end
70
+ end
71
+
72
+ describe 'Sets sharing_id' do
73
+ it 'Absent by default' do
74
+ expect(GandiV5).to receive(:post).with(url, any_args).and_return([nil, { 'message' => 'confirmation' }])
75
+ described_class.create('example.com', owner: {})
76
+ end
77
+
78
+ it 'Paying as another organization' do
79
+ expect(GandiV5).to receive(:post).with("#{url}?sharing_id=organization_id", any_args)
80
+ .and_return([nil, { 'message' => 'confirmation' }])
81
+ described_class.create('example.com', sharing_id: 'organization_id', owner: {})
82
+ end
83
+
84
+ it 'Buy as a reseller' do
85
+ expect(GandiV5).to receive(:post).with("#{url}?sharing_id=reseller_id", any_args)
86
+ .and_return([nil, { 'message' => 'confirmation' }])
87
+ described_class.create('example.com', sharing_id: 'reseller_id', owner: {})
88
+ end
89
+ end
90
+
91
+ it 'Success' do
92
+ body = '{"owner":{},"fqdn":"example.com"}'
93
+ expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 0)
94
+ .and_return([nil, { 'message' => 'confirmation' }])
95
+ expect(described_class.create('example.com', owner: {})).to eq 'confirmation'
96
+ end
97
+
98
+ it 'Errors on missing owner' do
99
+ expect { described_class.create 'example.com' }.to raise_error ArgumentError, 'missing keyword: owner'
100
+ end
101
+
102
+ it 'Given contact as hash' do
103
+ body = '{"owner":{"email":"owner@example.com"},"fqdn":"example.com"}'
104
+ expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 0)
105
+ .and_return([nil, { 'message' => 'confirmation' }])
106
+ described_class.create 'example.com', owner: { email: 'owner@example.com' }
107
+ end
108
+
109
+ it 'Given contact as GandiV5::Domain::Contact' do
110
+ body = '{"owner":{"email":"owner@example.com"},"fqdn":"example.com"}'
111
+ expect(GandiV5).to receive(:post).with(url, body, 'Dry-Run': 0)
112
+ .and_return([nil, { 'message' => 'confirmation' }])
113
+ owner = double GandiV5::Domain::Contact, to_gandi: { 'email' => 'owner@example.com' }
114
+ described_class.create 'example.com', owner: owner
115
+ end
116
+ end
117
+
118
+ it '.relaunch' do
119
+ expect(GandiV5).to receive(:put).with('https://api.gandi.net/v5/domain/transferin/example.com')
120
+ .and_return([nil, { 'message' => 'confirmation' }])
121
+ expect(described_class.relaunch('example.com')).to eq 'confirmation'
122
+ end
123
+
124
+ it '.resend_foa_emails' do
125
+ url = 'https://api.gandi.net/v5/domain/transferin/example.com/foa'
126
+ body = '{"email":"user@example.com"}'
127
+ expect(GandiV5).to receive(:post).with(url, body)
128
+ .and_return([nil, { 'message' => 'confirmation' }])
129
+ expect(described_class.resend_foa_emails('example.com', 'user@example.com')).to eq 'confirmation'
130
+ end
131
+
132
+ it '#relaunch' do
133
+ returned = double String
134
+ expect(described_class).to receive(:relaunch).with('example.com').and_return(returned)
135
+ expect(subject.relaunch).to be returned
136
+ end
137
+
138
+ it '#resend_foa_emails' do
139
+ returned = double String
140
+ expect(described_class).to receive(:resend_foa_emails).with('example.com', 'user@example.com').and_return(returned)
141
+ expect(subject.resend_foa_emails('user@example.com')).to be returned
142
+ end
143
+ end