gandi_v5 0.5.0 → 0.9.1

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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +69 -5
  3. data/LICENSE.md +2 -6
  4. data/README.md +67 -18
  5. data/lib/gandi_v5.rb +137 -70
  6. data/lib/gandi_v5/billing/info/prepaid.rb +1 -0
  7. data/lib/gandi_v5/data.rb +3 -2
  8. data/lib/gandi_v5/data/converter.rb +3 -2
  9. data/lib/gandi_v5/data/converter/array_of.rb +3 -2
  10. data/lib/gandi_v5/data/converter/integer.rb +3 -2
  11. data/lib/gandi_v5/data/converter/symbol.rb +3 -2
  12. data/lib/gandi_v5/data/converter/time.rb +3 -2
  13. data/lib/gandi_v5/domain.rb +16 -17
  14. data/lib/gandi_v5/domain/availability/product/period.rb +1 -1
  15. data/lib/gandi_v5/domain/contact.rb +5 -5
  16. data/lib/gandi_v5/domain/tld.rb +2 -2
  17. data/lib/gandi_v5/domain/transfer_in.rb +170 -0
  18. data/lib/gandi_v5/domain/transfer_in/availability.rb +51 -0
  19. data/lib/gandi_v5/email.rb +1 -0
  20. data/lib/gandi_v5/email/forward.rb +2 -8
  21. data/lib/gandi_v5/email/mailbox.rb +4 -10
  22. data/lib/gandi_v5/email/slot.rb +11 -3
  23. data/lib/gandi_v5/error/gandi_error.rb +1 -0
  24. data/lib/gandi_v5/live_dns.rb +2 -12
  25. data/lib/gandi_v5/live_dns/domain.rb +340 -29
  26. data/lib/gandi_v5/live_dns/domain/dnssec_key.rb +120 -0
  27. data/lib/gandi_v5/live_dns/domain/record.rb +81 -0
  28. data/lib/gandi_v5/live_dns/domain/snapshot.rb +111 -0
  29. data/lib/gandi_v5/live_dns/domain/tsig_key.rb +74 -0
  30. data/lib/gandi_v5/sharing_space.rb +27 -0
  31. data/lib/gandi_v5/simple_hosting.rb +13 -0
  32. data/lib/gandi_v5/simple_hosting/instance.rb +245 -0
  33. data/lib/gandi_v5/simple_hosting/instance/application.rb +45 -0
  34. data/lib/gandi_v5/simple_hosting/instance/database.rb +20 -0
  35. data/lib/gandi_v5/simple_hosting/instance/language.rb +22 -0
  36. data/lib/gandi_v5/simple_hosting/instance/upgrade.rb +22 -0
  37. data/lib/gandi_v5/simple_hosting/instance/virtual_host.rb +187 -0
  38. data/lib/gandi_v5/simple_hosting/instance/virtual_host/linked_dns_zone.rb +75 -0
  39. data/lib/gandi_v5/version.rb +1 -1
  40. data/spec/.rubocop.yml +9 -9
  41. data/spec/features/list_domain_renewals_spec.rb +16 -0
  42. data/spec/features/list_email_addresses_spec.rb +39 -0
  43. data/spec/fixtures/bodies/GandiV5_Domain/fetch.yml +8 -0
  44. data/spec/fixtures/bodies/GandiV5_Domain_TransferIn/fetch.yml +21 -0
  45. data/spec/fixtures/bodies/GandiV5_Domain_TransferIn_Availability/fetch.yml +10 -0
  46. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/fetch.yml +1 -2
  47. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/list_tsig.yml +3 -0
  48. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/nameservers.yml +3 -0
  49. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_DnssecKey/fetch.yml +12 -0
  50. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_DnssecKey/list.yml +9 -0
  51. data/spec/fixtures/bodies/{GandiV5_LiveDNS_Zone_Snapshot → GandiV5_LiveDNS_Domain_Snapshot}/fetch.yml +4 -3
  52. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_Snapshot/list.yml +5 -0
  53. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_TsigKey/fetch.yml +9 -0
  54. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_TsigKey/list.yml +4 -0
  55. data/spec/fixtures/bodies/GandiV5_SimpleHosting_Instance/fetch.yml +80 -0
  56. data/spec/fixtures/bodies/GandiV5_SimpleHosting_Instance/list.yml +38 -0
  57. data/spec/fixtures/bodies/GandiV5_SimpleHosting_Instance_VirtualHost/fetch.yml +26 -0
  58. data/spec/fixtures/bodies/GandiV5_SimpleHosting_Instance_VirtualHost/list.yml +18 -0
  59. data/spec/fixtures/vcr/Examples/List_domain_renewals.yml +54 -0
  60. data/spec/fixtures/vcr/Examples/List_email_addresses.yml +103 -0
  61. data/spec/units/gandi_v5/domain/transfer_in/availability_spec.rb +49 -0
  62. data/spec/units/gandi_v5/domain/transfer_in_spec.rb +143 -0
  63. data/spec/units/gandi_v5/domain_spec.rb +13 -39
  64. data/spec/units/gandi_v5/email/forward_spec.rb +5 -34
  65. data/spec/units/gandi_v5/email/mailbox_spec.rb +4 -34
  66. data/spec/units/gandi_v5/email/slot_spec.rb +10 -2
  67. data/spec/units/gandi_v5/live_dns/domain/dnssec_key_spec.rb +128 -0
  68. data/spec/units/gandi_v5/live_dns/{record_set_spec.rb → domain/record_spec.rb} +1 -1
  69. data/spec/units/gandi_v5/live_dns/domain/snapshot_spec.rb +101 -0
  70. data/spec/units/gandi_v5/live_dns/domain/tsig_key_spec.rb +78 -0
  71. data/spec/units/gandi_v5/live_dns/domain_spec.rb +297 -118
  72. data/spec/units/gandi_v5/live_dns_spec.rb +0 -12
  73. data/spec/units/gandi_v5/sharing_space_spec.rb +4 -0
  74. data/spec/units/gandi_v5/simple_hosting/instance/application_spec.rb +37 -0
  75. data/spec/units/gandi_v5/simple_hosting/instance/database_spec.rb +4 -0
  76. data/spec/units/gandi_v5/simple_hosting/instance/language_spec.rb +4 -0
  77. data/spec/units/gandi_v5/simple_hosting/instance/upgrade_spec.rb +4 -0
  78. data/spec/units/gandi_v5/simple_hosting/instance/virtual_host/linked_dns_zone_spec.rb +50 -0
  79. data/spec/units/gandi_v5/simple_hosting/instance/virtual_host_spec.rb +199 -0
  80. data/spec/units/gandi_v5/simple_hosting/instance_spec.rb +182 -0
  81. data/spec/units/gandi_v5/simple_hosting_spec.rb +9 -0
  82. data/spec/units/gandi_v5_spec.rb +111 -14
  83. metadata +174 -53
  84. data/.gitignore +0 -26
  85. data/.rspec +0 -3
  86. data/.rubocop.yml +0 -30
  87. data/.travis.yml +0 -38
  88. data/FUNDING.yml +0 -10
  89. data/Gemfile +0 -6
  90. data/Guardfile +0 -39
  91. data/Rakefile +0 -3
  92. data/bin/console +0 -13
  93. data/gandi_v5.gemspec +0 -42
  94. data/lib/gandi_v5/domain/sharing_space.rb +0 -21
  95. data/lib/gandi_v5/live_dns/has_zone_records.rb +0 -153
  96. data/lib/gandi_v5/live_dns/record_set.rb +0 -79
  97. data/lib/gandi_v5/live_dns/zone.rb +0 -160
  98. data/lib/gandi_v5/live_dns/zone/snapshot.rb +0 -81
  99. data/spec/features/domain_spec.rb +0 -45
  100. data/spec/features/livedns_domain_spec.rb +0 -8
  101. data/spec/features/livedns_zone_spec.rb +0 -44
  102. data/spec/features/mailbox_spec.rb +0 -18
  103. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/fetch.yml +0 -11
  104. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/list.yml +0 -11
  105. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/list.yml +0 -3
  106. data/spec/fixtures/vcr/Domain_features/List_domains.yml +0 -55
  107. data/spec/fixtures/vcr/Domain_features/Renew_domain.yml +0 -133
  108. data/spec/fixtures/vcr/LiveDNS_Domain_features/List_domains.yml +0 -32
  109. data/spec/fixtures/vcr/LiveDNS_Zone_features/List_zones.yml +0 -42
  110. data/spec/fixtures/vcr/LiveDNS_Zone_features/Make_and_save_snapshot.yml +0 -72
  111. data/spec/fixtures/vcr/LiveDNS_Zone_features/Save_zone_to_file.yml +0 -28
  112. data/spec/fixtures/vcr/Mailbox_features/List_mailboxes.yml +0 -39
  113. data/spec/units/gandi_v5/domain/sharing_space_spec.rb +0 -4
  114. data/spec/units/gandi_v5/live_dns/zone/snapshot_spec.rb +0 -66
  115. data/spec/units/gandi_v5/live_dns/zone_spec.rb +0 -347
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eac7a49d78a12be6f28ce2a12aab37a8fcbe25e24ffd40f215a7bf088df81125
4
- data.tar.gz: bb0e28904dc4869a6846c6cd4204b7c9c9e97937f9a1d7ef9dcbf1ceef7b7ea2
3
+ metadata.gz: 4bfa3d695cec03737e8e5c3639c7744300babd00d59081f4edf14f013d2e9787
4
+ data.tar.gz: ce687383ed1d014889d22e9d33a068dad8a8dc8ec2a73a38c9150014195a3f0b
5
5
  SHA512:
6
- metadata.gz: 3fa831c1c527c6b06f97627d36ba3085586f5675690ff120a075f9a88a24bde2493d83c4b7b04803e00295459af2a49f92e049f0172af288634c04d32d4c1f6c
7
- data.tar.gz: 7116bae0e14637e37ff361e530d711a3d2d68177554df107963a020049746b955cc9cfbb61e9dca5ad354ced47b5d88d4c3047ec2a3b7f9d4bf8005426b1ebdc
6
+ metadata.gz: a2752f84704fbd326503b2bada3e3193d2215abc6c19e1b71198b29eabaf4e67f473249d076aa806ca2c937195a35c7d2a8c490e1f586d0c3f121be5900c1ae5
7
+ data.tar.gz: 398dc026b251a700432dee898e23c207bee4fa10c5bcc879f706f0e9c0ed0793d3b670861b97221bd4f64bfbfd27c32a589b5b7eeb911662b95623461ec90f59
@@ -1,5 +1,69 @@
1
1
  # Gandi V5 API Gem Changelog
2
2
 
3
+ ## Version 0.9.1
4
+
5
+ * Add testing against ruby 2.7.2 and 3.0.0
6
+
7
+ ## Version 0.9.0
8
+
9
+ * Add transferring a domain to Gandi (I don't have any domains outside Gandi to test this myself so it's possible I've misread the docs and a bug is waiting to be found, please add an issue if I have):
10
+ * GandiV5::Domain::TransferIn:
11
+ * .create(fqdn, \*\*options)
12
+ * .fetch(fqdn)
13
+ * .relaunch(fqdn)
14
+ * .resend_foa_emails(fqdn, email_address)
15
+ * \#relaunch
16
+ * \#resend_foa_emails(email_address)
17
+ * GandiV5::Domain::TransferIn::Availabillity:
18
+ * .fetch(fqdn, auth_code = nil)
19
+ * Documentation improvements
20
+
21
+ ## Version 0.8.0
22
+
23
+ * Domain:
24
+ * .list - add resellee_id filter
25
+ * Added simple hosting: (I don't use simple hosting myself so it's possible I've misread the docs and a bug is waiting to be found, please add an issue if I have)
26
+ * SimpleHosting::Instance
27
+ * SimpleHosting::Instance::VirtualHost
28
+ * SimpleHosting::Instance::Application
29
+ * SimpleHosting::Instance::Database
30
+ * SimpleHosting::Instance::Language
31
+ * SimpleHosting::Instance::Upgrade
32
+ * GandiV5::Domain::SharingSpace moved to GandiV5::SharingSpace
33
+
34
+ ## Version 0.7.0
35
+
36
+ * LiveDNS:
37
+ * Rename LiveDNS::RecordSet to LiveDNS::Domain::Record
38
+ * Domains:
39
+ * .list now returns an array of strings
40
+ * Can no longer change the zone used by a domain
41
+ * Added automatic_snapshots attribute for whether snapshots are automatically created when a modification is made to this domain's records
42
+ * \#replace_records and \#replace_records_for merged into \#replace_records
43
+ * If replacing with a zone file use the new #replace_zone_lines
44
+ * Added:
45
+ * .create
46
+ * .record_types
47
+ * .generic_name_servers(fqdn)
48
+ * \#name_servers and #fetch_name_servers
49
+ * \#tsig_keys, #fetch_tsig_keys, \#add_tsig_key, \#remove_tsig_key
50
+ * \#axfr_clients, #fetch_axfr_clients, #add_axfr_client, \#remove_axfr_client
51
+ * ::DnssecKeys, #dnssec_keys, #fetch_dnssec_keys
52
+ * Snapshots:
53
+ * Moved to live under LiveDNS::Domain not LiveDNS::Zone
54
+ * Are now accessed via the fully qualified domain name NOT the zone's UUID
55
+ * Ability to access the zone from a snapshot is removed
56
+ * Taking a snapshot now allows for named snapshots
57
+ * Added automatic attribute for when a snapshot was taken due to a zone change
58
+ * .list now returns an array of snapshots (records are fetched in a seperate request when first needed)
59
+ * Zone removed.
60
+
61
+ ## Version 0.6.0
62
+
63
+ * GandiV5::Email::Slot.create now supports sharing_id
64
+ * GandiV5::Email::Slot.create's type argument is now named not positional
65
+ * Add reseller information to GandiV5::Domain
66
+
3
67
  ## Version 0.5.0
4
68
 
5
69
  * Add support for truffleruby 20.1.0
@@ -33,11 +97,11 @@
33
97
  ## Version 0.2.0
34
98
 
35
99
  * Enhancements to GandiV5::Domain
36
- * .availability(fqdn, **options) moved to GandiV5::Domain::Availability.fetch(fqdn, **options)
100
+ * .availability(fqdn, \*\*options) moved to GandiV5::Domain::Availability.fetch(fqdn, \*\*options)
37
101
  * .create now returns created domain (except in dry-run mode)
38
102
  * .tlds moved to GandiV5::Domain::TLD.list
39
103
  * .tld(name) moved to GandiV5::Domain::TLD.fetch(name)
40
- * #renewal_price(currency: 'GBP', period: 1) added
104
+ * \#renewal_price(currency: 'GBP', period: 1) added
41
105
  * Enhancements to GandiV5::Email::Mailbox
42
106
  * .create now returns created mailbox
43
107
  * .create now checks for available slots and a valid type has been passed
@@ -46,14 +110,14 @@
46
110
  * Add #disable to disable the auto responder in Gandi
47
111
  * Enhancements to GandiV5::Email::Slot
48
112
  * .create now returns created slot
49
- * #delete now checks for inactiveness and refundableness
113
+ * \#delete now checks for inactiveness and refundableness
50
114
  * Enhancements to GandiV5::LiveDNS::Domain
51
115
  * Add #zone and #fetch_zone
52
- * Remove #replace_*_records_for methods
116
+ * Remove #replace_\*_records_for methods
53
117
  * Changes to #replace_records_for to allow calling with name, type, ttl and values. When calling with name and fecords records MUST be passed as an array.
54
118
  * Enhancements to GandiV5::LiveDNS::Zone
55
119
  * .create now returns created zone
56
- * Remove #replace_*_records_for methods
120
+ * Remove #replace_\*_records_for methods
57
121
  * Changes to #replace_records_for to allow calling with name, type, ttl and values. When calling with name and fecords records MUST be passed as an array.
58
122
  * Enhancements to GandiV5::LiveDNS::Zone::Snapshot
59
123
  * Add .list
data/LICENSE.md CHANGED
@@ -1,14 +1,10 @@
1
- ##Copyright
2
- Copyright (c) 2018, Robert Gauld. All rights reserved.
3
-
4
-
5
- ##License
1
+ ## License
6
2
  This code can be used under the BSD License (reproduced below).
7
3
  Commiters to the project give Robert Gauld the right to redistribute their commits
8
4
  under the BSD license.
9
5
 
10
6
 
11
- ###BSD License
7
+ ### BSD License
12
8
  Redistribution and use in source and binary forms, with or without modification,
13
9
  are permitted provided that the following conditions are met:
14
10
 
data/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/gandi_v5.png)](http://badge.fury.io/rb/gandi_v5)
2
- [![Build Status](https://secure.travis-ci.org/robertgauld/gandi_v5.png?branch=master)](http://travis-ci.org/robertgauld/gandi_v5)
3
- [![Coveralls Status](https://coveralls.io/repos/robertgauld/gandi_v5/badge.png?branch=master)](https://coveralls.io/r/robertgauld/gandi_v5)
4
- [![Code Climate](https://codeclimate.com/github/robertgauld/gandi_v5.png?branch=master)](https://codeclimate.com/github/robertgauld/gandi_v5)
5
- [![security](https://hakiri.io/github/robertgauld/gandi_v5/master.svg)](https://hakiri.io/github/robertgauld/gandi_v5/master)
2
+ [![Build Status](https://secure.travis-ci.org/robertgauld/gandi_v5.png?branch=main)](http://travis-ci.org/robertgauld/gandi_v5)
3
+ [![Coveralls Status](https://coveralls.io/repos/robertgauld/gandi_v5/badge.png?branch=main)](https://coveralls.io/r/robertgauld/gandi_v5)
4
+ [![Code Climate](https://codeclimate.com/github/robertgauld/gandi_v5.png?branch=main)](https://codeclimate.com/github/robertgauld/gandi_v5)
6
5
 
7
6
  ## Ruby Versions
8
7
  This gem supports the following versions of ruby, it may work on other versions but is not tested against them so don't rely on it.
9
8
 
10
9
  * ruby:
11
10
  * 2.6.0 - 2.6.6
12
- * 2.7.0 - 2.7.1
13
- * truffleruby 20.1.0
11
+ * 2.7.0 - 2.7.2
12
+ * 3.0.0
13
+ * truffleruby 20.1.0 - 20.2.0
14
14
  * jruby, once it's reached parity with ruby 2.6.x
15
15
  * rubinius, once it's reached parity with ruby 2.6.x
16
16
 
@@ -25,23 +25,24 @@ Gandi say: **_"Please note that this API is currently in BETA testing, so care s
25
25
 
26
26
  But then you were going to be careful anyway as this gem is currently in the version 0.something range weren't you!
27
27
 
28
- Details of the API can be found at:
28
+ Details of Gandi's API can be found at:
29
29
 
30
30
  * <https://api.gandi.net/docs/>
31
31
  * <https://doc.livedns.gandi.net/>
32
32
 
33
+ Details of the gem's API can be found at <https://rubydoc.info/github/robertgauld/gandi_v5/main>
33
34
 
34
35
  ## Installation
35
36
 
36
37
  If you're using bundler then add it to your Gemfile and run the bundle command.
37
38
 
38
39
  ```ruby
39
- gem 'gandi_v5', '~> 0.1'
40
+ gem 'gandi_v5', '~> 0.8'
40
41
  ```
41
42
 
42
43
  If you're not using bundler then install it from the command line.
43
44
  ```bash
44
- gem install gandi_v5 -v '~> 0.1'
45
+ gem install gandi_v5 -v '~> 0.8'
45
46
  ```
46
47
 
47
48
  ## Usage
@@ -58,6 +59,52 @@ GandiV5.api_key = '…' # Unless you've set it in the environment variable GANDI
58
59
 
59
60
  ### Examples
60
61
 
62
+ #### List renewal dates and costs for all domains
63
+ ```ruby
64
+ # For each domain (sorted by assending renewal date) print <date>\t<cost>\t<fqdn>
65
+ GandiV5::Domain.list.each do |domain|
66
+ puts [
67
+ domain.dates.registry_ends_at.to_date,
68
+ "£#{domain.renewal_price.price_after_taxes}",
69
+ domain.fqdn
70
+ ].join("\t")
71
+ end
72
+ ```
73
+
74
+ #### List email addresses for all domains
75
+
76
+ ```ruby
77
+ # For each domain:
78
+ # 1. Create an empty hash to store address => description
79
+ # 2. Get the mailboxes and add them to the hash
80
+ # 3. Get the forwards and add them to the hash
81
+ # 4. Sort the hash by email address
82
+ # 5. Print the list
83
+ GandiV5::Domain.list.each do |domain|
84
+ emails = {}
85
+
86
+ mailboxes = GandiV5::Email::Mailbox.list(domain.fqdn)
87
+ mailboxes.each do |mailbox|
88
+ mailbox.refresh
89
+ emails["#{mailbox.login}@#{domain.fqdn}"] = "#{mailbox.type} mailbox " \
90
+ "(#{mailbox.quota_usage.to_i}% " \
91
+ "of #{(mailbox.quota / 1024**3).round}GB used)"
92
+ mailbox.aliases.each do |alias_name|
93
+ emails["#{alias_name}@#{domain.fqdn}"] = "alias for #{mailbox.login}@#{domain.fqdn}"
94
+ end
95
+ end
96
+
97
+ forwards = GandiV5::Email::Forward.list(domain.fqdn)
98
+ forwards.each do |forward|
99
+ emails["#{forward.source}@#{domain.fqdn}"] = "forwards to #{forward.destinations.join(', ')}"
100
+ end
101
+
102
+ emails.sort.each do |address, text|
103
+ puts "#{address}\t#{text}"
104
+ end
105
+ end
106
+ ```
107
+
61
108
  #### Domains
62
109
 
63
110
  ```ruby
@@ -68,19 +115,21 @@ domains = GandiV5.domains
68
115
  domains.map!(&:refresh)
69
116
  ```
70
117
 
71
- TODO: More examples!
72
-
73
-
74
118
  ## Versioning
75
119
 
76
120
  We follow the [Semantic Versioning](http://semver.org/) concept.
77
121
 
78
- | Gem Version | Gandi API Release Date |
79
- | --------------- | ---------------------- |
80
- | 0.4.0 | 2019-10-01 |
81
- | 0.3.0 | 2019-08-22 |
82
- | 0.2.0 | 2019-05-16 |
83
- | 0.1.0 | 2019-05-16 |
122
+ | Gem Version | Gandi API Release Date |
123
+ | --------------- | ------------------------ |
124
+ | 0.9.0 | 2020-07-29 |
125
+ | 0.8.0 | 2020-07-10 |
126
+ | 0.7.0 | 2020-05-07 |
127
+ | 0.6.0 | 2020-05-07 (not LiveDNS) |
128
+ | 0.5.0 | 2019-10-01 |
129
+ | 0.4.0 | 2019-10-01 |
130
+ | 0.3.0 | 2019-08-22 |
131
+ | 0.2.0 | 2019-05-16 |
132
+ | 0.1.0 | 2019-05-16 |
84
133
 
85
134
  See <https://api.gandi.net/docs/reference#API-Changelog> to find out what
86
135
  Gandi changed on each date.
@@ -5,11 +5,12 @@ require 'securerandom'
5
5
  require 'zeitwerk'
6
6
 
7
7
  # Custom inflector for Zeitwerk.
8
+ # @api private
8
9
  class MyInflector < Zeitwerk::Inflector
9
10
  # Convert file's base name to class name when
10
11
  # Zeitwerk's included inflector gets it wrong.
11
12
  # @param basename [String] the file's base name (no path or extension)
12
- # @param abspath [String] the file's absolute path
13
+ # @param _abspath [String] the file's absolute path
13
14
  # @return [String] the class name
14
15
  def camelize(basename, _abspath)
15
16
  case basename
@@ -31,32 +32,37 @@ loader.setup
31
32
 
32
33
  # Namespace for classes which access the Gandi V5 API.
33
34
  # Also provides useful methods and constants for them.
34
- # This is where you configure the gem:
35
- # * Setting your Gandi API key:
36
- # 1. Get your API key - Login to Gandi and visit User Settings ->
37
- # Change password & configure access restrictions.
35
+ # To get your API key login to Gandi and visit
36
+ # "User Settings" -> "Change password & configure access restrictions".
37
+ # Set your API key either in the GANDI_API_KEY environment variable or
38
+ # by setting the api_key class attribute.
38
39
  # @see https://api.gandi.net/docs/
39
40
  # @see https://doc.livedns.gandi.net/
40
41
  # @!attribute [w] api_key
41
42
  # @return [String]
42
43
  class GandiV5
44
+ # Base URL for all API requests.
43
45
  BASE = 'https://api.gandi.net/v5/'
44
46
 
47
+ # Get information on a domain.
45
48
  # @see GandiV5::Domain.fetch
46
49
  def self.domain(fqdn)
47
50
  GandiV5::Domain.fetch(fqdn)
48
51
  end
49
52
 
53
+ # Get information on all domains.
50
54
  # @see GandiV5::Domain.list
51
55
  def self.domains(**params)
52
56
  GandiV5::Domain.list(**params)
53
57
  end
54
58
 
59
+ # List mailboxes for a domain.
55
60
  # @see GandiV5::Email::Mailbox.list
56
61
  def self.mailboxes(fqdn, **params)
57
62
  GandiV5::Email::Mailbox.list(fqdn, **params)
58
63
  end
59
64
 
65
+ # List email slots for a domain.
60
66
  # @see GandiV5::Email::Slot.list
61
67
  def self.mailbox_slots(fqdn)
62
68
  GandiV5::Email::Slot.list(fqdn)
@@ -65,15 +71,21 @@ class GandiV5
65
71
  class << self
66
72
  attr_writer :api_key
67
73
 
68
- # Might raise:
69
- # * RestClient::NotFound
70
- # * RestClient::Unauthorized
71
- # Bad authentication attempt because of a wrong API Key.
72
- # * RestClient::Forbidden
73
- # Access to the resource is denied.
74
- # Mainly due to a lack of permissions to access it.
75
- # * GandiV5::Error
76
- # * JSON::ParserError
74
+ # Make a GET request to a Gandi end point.
75
+ # @param url [String, #to_s]
76
+ # the full URL (including GandiV5::BASE) to fetch.
77
+ # @param headers [Hash{String, Symbol, #to_s => String, Symbol, #to_s}]
78
+ # the headers to send in the request, the authorisation will be added.
79
+ # @return [Array<(RestClient::Response, Object)>]
80
+ # The response from the server and the result of parsing the responce's body.
81
+ # @raise [RestClient::NotFound]
82
+ # @raise [RestClient::Unauthorized]
83
+ # Bad authentication attempt because of a wrong API Key.
84
+ # @raise [RestClient::Forbidden]
85
+ # Access to the resource is denied.
86
+ # Mainly due to a lack of permissions to access it.
87
+ # @raise [GandiV5::Error]
88
+ # @raise [JSON::ParserError]
77
89
  def get(url, **headers)
78
90
  prepare_headers headers, url
79
91
  response = RestClient.get url, **headers
@@ -82,16 +94,59 @@ class GandiV5
82
94
  handle_bad_request(e)
83
95
  end
84
96
 
85
- # Might raise:
86
- # * RestClient::NotFound
87
- # * RestClient::Unauthorized
88
- # Bad authentication attempt because of a wrong API Key.
89
- # * RestClient::Forbidden
90
- # Access to the resource is denied.
91
- # Mainly due to a lack of permissions to access it.
92
- # * RestClient::Conflict
93
- # * GandiV5::Error
94
- # * JSON::ParserError
97
+ # Make a GET request to a paginated end point at Gandi.
98
+ # @param url [String, #to_s]
99
+ # the full URL (including GandiV5::BASE) to fetch.
100
+ # @param page [#each, Integer] the page/pages of results to get.
101
+ # @param per_page [Integer, #to_s] the number of items to get per page of results.
102
+ # @param headers [Hash{String, Symbol, #to_s => String, Symbol, #to_s}]
103
+ # the headers to send in the request, the authorisation will be added.
104
+ # @return [Array<(RestClient::Response, Object)>]
105
+ # The response from the server and the result of parsing the responce's body.
106
+ # @raise [RestClient::NotFound]
107
+ # @raise [RestClient::Unauthorized]
108
+ # Bad authentication attempt because of a wrong API Key.
109
+ # @raise [RestClient::Forbidden]
110
+ # Access to the resource is denied.
111
+ # Mainly due to a lack of permissions to access it.
112
+ # @raise [GandiV5::Error]
113
+ # @raise [JSON::ParserError]
114
+ def paginated_get(url, page = (1..), per_page = 100, **headers)
115
+ unless page.respond_to?(:each)
116
+ fail ArgumentError, 'page must be positive' unless page.positive?
117
+
118
+ page = [page]
119
+ end
120
+
121
+ headers[:params] ||= {}
122
+ headers[:params].transform_keys!(&:to_s)
123
+ headers[:params]['per_page'] = per_page
124
+
125
+ page.each do |page_number|
126
+ headers[:params]['page'] = page_number
127
+ _resp, this_data = get(url, **headers)
128
+ break if this_data.empty?
129
+
130
+ yield this_data
131
+ break if this_data.count < per_page
132
+ end
133
+ end
134
+
135
+ # Make a DELETE request to a Gandi end point.
136
+ # @param url [String, #to_s]
137
+ # the full URL (including GandiV5::BASE) to fetch.
138
+ # @param headers [Hash{String, Symbol, #to_s => String, Symbol, #to_s}]
139
+ # the headers to send in the request, the authorisation will be added.
140
+ # @return [Array<(RestClient::Response, Object)>]
141
+ # The response from the server and the result of parsing the responce's body.
142
+ # @raise [RestClient::NotFound]
143
+ # @raise [RestClient::Unauthorized]
144
+ # Bad authentication attempt because of a wrong API Key.
145
+ # @raise [RestClient::Forbidden]
146
+ # Access to the resource is denied.
147
+ # Mainly due to a lack of permissions to access it.
148
+ # @raise [GandiV5::Error]
149
+ # @raise [JSON::ParserError]
95
150
  def delete(url, **headers)
96
151
  prepare_headers headers, url
97
152
  response = RestClient.delete url, **headers
@@ -103,17 +158,24 @@ class GandiV5
103
158
  handle_bad_request(e)
104
159
  end
105
160
 
106
- # Might raise:
107
- # * RestClient::NotFound
108
- # * RestClient::Unauthorized
109
- # Bad authentication attempt because of a wrong API Key.
110
- # * RestClient::Forbidden
111
- # Access to the resource is denied.
112
- # Mainly due to a lack of permissions to access it.
113
- # * RestClient::BadRequest
114
- # * RestClient::Conflict
115
- # * GandiV5::Error
116
- # * JSON::ParserError
161
+ # Make a PATCH request to a Gandi end point.
162
+ # @param url [String, #to_s]
163
+ # the full URL (including GandiV5::BASE) to fetch.
164
+ # @param payload [String, #to_s] the body for the request.
165
+ # @param headers [Hash{String, Symbol, #to_s => String, Symbol, #to_s}]
166
+ # the headers to send in the request, the authorisation will be added.
167
+ # @return [Array<(RestClient::Response, Object)>]
168
+ # The response from the server and the result of parsing the responce's body.
169
+ # @raise [RestClient::NotFound]
170
+ # @raise [RestClient::Unauthorized]
171
+ # Bad authentication attempt because of a wrong API Key.
172
+ # @raise [RestClient::Forbidden]
173
+ # Access to the resource is denied.
174
+ # Mainly due to a lack of permissions to access it.
175
+ # @raise [RestClient::BadRequest]
176
+ # @raise [RestClient::Conflict]
177
+ # @raise [GandiV5::Error]
178
+ # @raise [JSON::ParserError]
117
179
  def patch(url, payload = '', **headers)
118
180
  prepare_headers headers, url
119
181
  headers[:'content-type'] ||= 'application/json'
@@ -123,17 +185,24 @@ class GandiV5
123
185
  handle_bad_request(e)
124
186
  end
125
187
 
126
- # Might raise:
127
- # * RestClient::NotFound
128
- # * RestClient::Unauthorized
129
- # Bad authentication attempt because of a wrong API Key.
130
- # * RestClient::Forbidden
131
- # Access to the resource is denied.
132
- # Mainly due to a lack of permissions to access it.
133
- # * RestClient::BadRequest
134
- # * RestClient::Conflict
135
- # * GandiV5::Error
136
- # * JSON::ParserError
188
+ # Make a POST request to a Gandi end point.
189
+ # @param url [String, #to_s]
190
+ # the full URL (including GandiV5::BASE) to fetch.
191
+ # @param payload [String, #to_s] the body for the request.
192
+ # @param headers [Hash{String, Symbol, #to_s => String, Symbol, #to_s}]
193
+ # the headers to send in the request, the authorisation will be added.
194
+ # @return [Array<(RestClient::Response, Object)>]
195
+ # The response from the server and the result of parsing the responce's body.
196
+ # @raise [RestClient::NotFound]
197
+ # @raise [RestClient::Unauthorized]
198
+ # Bad authentication attempt because of a wrong API Key.
199
+ # @raise [RestClient::Forbidden]
200
+ # Access to the resource is denied.
201
+ # Mainly due to a lack of permissions to access it.
202
+ # @raise [RestClient::BadRequest]
203
+ # @raise [RestClient::Conflict]
204
+ # @raise [GandiV5::Error]
205
+ # @raise [JSON::ParserError]
137
206
  def post(url, payload = '', **headers)
138
207
  prepare_headers headers, url
139
208
  headers[:'content-type'] ||= 'application/json'
@@ -143,17 +212,24 @@ class GandiV5
143
212
  handle_bad_request(e)
144
213
  end
145
214
 
146
- # Might raise:
147
- # * RestClient::NotFound
148
- # * RestClient::Unauthorized
149
- # Bad authentication attempt because of a wrong API Key.
150
- # * RestClient::Forbidden
151
- # Access to the resource is denied.
152
- # Mainly due to a lack of permissions to access it.
153
- # * RestClient::BadRequest
154
- # * RestClient::Conflict
155
- # * GandiV5::Error
156
- # * JSON::ParserError
215
+ # Make a PUT request to a Gandi end point.
216
+ # @param url [String, #to_s]
217
+ # the full URL (including GandiV5::BASE) to fetch.
218
+ # @param payload [String, #to_s] the body for the request.
219
+ # @param headers [Hash{String, Symbol, #to_s => String, Symbol, #to_s}]
220
+ # the headers to send in the request, the authorisation will be added
221
+ # @return [Array<(RestClient::Response, Object)>]
222
+ # The response from the server and the result of parsing the responce's body.
223
+ # @raise [RestClient::NotFound]
224
+ # @raise [RestClient::Unauthorized]
225
+ # Bad authentication attempt because of a wrong API Key.
226
+ # @raise [RestClient::Forbidden]
227
+ # Access to the resource is denied.
228
+ # Mainly due to a lack of permissions to access it.
229
+ # @raise [RestClient::BadRequest]
230
+ # @raise [RestClient::Conflict]
231
+ # @raise [GandiV5::Error]
232
+ # @raise [JSON::ParserError]
157
233
  def put(url, payload = '', **headers)
158
234
  prepare_headers headers, url
159
235
  headers[:'content-type'] ||= 'application/json'
@@ -169,16 +245,6 @@ class GandiV5
169
245
  @api_key ||= ENV.fetch('GANDI_API_KEY')
170
246
  end
171
247
 
172
- def authorisation_header(url)
173
- if url.start_with?(BASE)
174
- { Authorization: "Apikey #{api_key}" }
175
- elsif url.start_with?(GandiV5::LiveDNS::BASE)
176
- { 'X-Api-Key': api_key }
177
- else
178
- fail ArgumentError, "Don't know how to authorise for url: #{url}"
179
- end
180
- end
181
-
182
248
  def parse_response(response)
183
249
  type = response.headers.fetch(:content_type).split(';').first.chomp
184
250
  case type
@@ -196,10 +262,11 @@ class GandiV5
196
262
  end
197
263
  end
198
264
 
199
- def prepare_headers(headers, url)
200
- headers.transform_keys!(&:to_sym)
265
+ def prepare_headers(headers, _url)
266
+ headers.transform_keys! { |key| key.to_s.downcase.to_sym }
201
267
  headers[:accept] ||= 'application/json'
202
- headers.merge!(authorisation_header(url))
268
+ headers[:authorization] = "Apikey #{api_key}"
269
+ headers
203
270
  end
204
271
 
205
272
  def handle_bad_request(exception)