record_store 5.5.4 → 5.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f96ae123926fc5ccc32796348a250ed7c0dda8c03e84bc04f00e03502b0d83b
4
- data.tar.gz: 01550ab52e78f3b30cb1512e7406bc471d328ca536e9a80eaeefd622dddd659f
3
+ metadata.gz: f51b768f45c65d0eee98819d583fb206fe4be73f9a8f5410aeee4c6b6ad5ab64
4
+ data.tar.gz: 77bc9dc6603c60096c107c9c304fff3a4e23475866d727b7ae235d7943aa6308
5
5
  SHA512:
6
- metadata.gz: c34de6f849092154933070a7356279e6c790694d6045a70c2792d77fccf4d769ae961a5bdee2fd4cc62d6eeb208d211ca9745f7bb95cb99b0a246aaa586c922b
7
- data.tar.gz: f2ef26d2be53ffcec008c5db964d294a43b10a98abd0c31221d8a31731eb99346412b9624c17d3c8c396e91dfea4b04e798faf4e83138ad570480c56e18f3937
6
+ metadata.gz: 6f9c5c381c14d1509b305c4b2635ced20b701662f99877e5eb42a16ca7efe724a4ad5314d23ce48ef8cdeee6d3bb5912bca0ec7aed6874a7919c2b2d912b422b
7
+ data.tar.gz: 9ea92388f604ebd39fccaea099f54925ad03f23d7146e698d3fbb19e3f255b8057a872b5b9aca67c25cad4c24064f4f884c0e94624b34984df1f6cc6b2cfca7c
@@ -1,4 +1,9 @@
1
1
  # CHANGELOG
2
+ ## 5.6.0
3
+ - add OCI provider [FEATURE]
4
+
5
+ ## 5.5.3
6
+ - add NS1 provider [FEATURE]
2
7
 
3
8
  ## 5.4.3
4
9
  - use fog-dynect 0.4.0 to avoid version override [REFACTOR]
@@ -32,6 +32,7 @@ require 'record_store/provider/dynect'
32
32
  require 'record_store/provider/dnsimple'
33
33
  require 'record_store/provider/google_cloud_dns'
34
34
  require 'record_store/provider/ns1'
35
+ require 'record_store/provider/oracle_cloud_dns'
35
36
  require 'record_store/cli'
36
37
 
37
38
  module RecordStore
@@ -21,6 +21,8 @@ module RecordStore
21
21
  'GoogleCloudDNS'
22
22
  when /\.nsone\.net\z/
23
23
  'NS1'
24
+ when /\.oraclecloud\.net\z/
25
+ 'OracleCloudDNS'
24
26
  end
25
27
  end
26
28
 
@@ -0,0 +1,183 @@
1
+ require 'oci'
2
+
3
+ module RecordStore
4
+ class Provider::OracleCloudDNS < Provider
5
+ class Error < StandardError; end
6
+
7
+ class << self
8
+ def client
9
+ @client ||= begin
10
+ config = OCI::Config.new
11
+ config.user = secrets['user']
12
+ config.fingerprint = secrets['fingerprint']
13
+ config.key_content = secrets['key_content']
14
+ config.tenancy = secrets['tenancy']
15
+ config.region = secrets['region']
16
+ config.validate
17
+ OCI::Dns::DnsClient.new(config: config)
18
+ end
19
+ end
20
+
21
+ # Downloads all the records from the provider.
22
+ #
23
+ # Returns: an array of `Record` for each record in the provider's zone
24
+ def retrieve_current_records(zone:, stdout: $stdout)
25
+ client.get_zone_records(zone)
26
+ .flat_map { |response| response.data.items }
27
+ .flat_map { |api_record| build_from_api(api_record) }
28
+ .compact
29
+ rescue OCI::Errors::HttpRequestBasedError
30
+ stdout.puts "Cannot build record for zone: #{zone}"
31
+ raise
32
+ end
33
+
34
+ # Returns an array of the zones managed by provider as strings
35
+ def zones
36
+ client.list_zones(secrets['compartment_id']).data.map(&:name)
37
+ end
38
+
39
+ private
40
+
41
+ # Creates a new record to the zone. It is expected this call modifies external state.
42
+ #
43
+ # Arguments:
44
+ # record - a kind of `Record`
45
+ def add(record, zone)
46
+ patch_add_record = [
47
+ OCI::Dns::Models::RecordOperation.new(
48
+ domain: record.fqdn,
49
+ rtype: record.type,
50
+ ttl: record.ttl,
51
+ rdata: record.rdata_txt,
52
+ operation: 'ADD',
53
+ ),
54
+ ]
55
+
56
+ client.patch_zone_records(
57
+ zone,
58
+ OCI::Dns::Models::PatchZoneRecordsDetails.new(items: patch_add_record)
59
+ )
60
+ end
61
+
62
+ # Deletes an existing record from the zone. It is expected this call modifies external state.
63
+ #
64
+ # Arguments:
65
+ # record - a kind of `Record`
66
+ def remove(record, zone)
67
+ record_fqdn = Record.ensure_ends_without_dot(record.fqdn)
68
+ found_record = client.get_zone_records(
69
+ zone,
70
+ rtype: record.type,
71
+ domain: record_fqdn,
72
+ ).data.items.select { |r| r.rdata == record.rdata_txt }
73
+
74
+ return unless found_record
75
+ begin
76
+ record_hash = found_record.first.record_hash if found_record.length == 1
77
+ rescue NoMethodError
78
+ puts "No matching record to remove: #{record_fqdn}, #{record.type}"
79
+ else
80
+ patch_remove_record = [
81
+ OCI::Dns::Models::RecordOperation.new(
82
+ domain: record_fqdn,
83
+ record_hash: record_hash,
84
+ rtype: record.type,
85
+ ttl: record.ttl,
86
+ rdata: record.rdata_txt,
87
+ operation: 'REMOVE',
88
+ ),
89
+ ]
90
+
91
+ client.patch_zone_records(
92
+ zone,
93
+ OCI::Dns::Models::PatchZoneRecordsDetails.new(items: patch_remove_record)
94
+ )
95
+ end
96
+ end
97
+
98
+ # Updates an existing record in the zone. It is expected this call modifies external state.
99
+ #
100
+ # Arguments:
101
+ # id - provider specific ID of record to update
102
+ # record - a kind of `Record` which the record with `id` should be updated to
103
+ def update(id, record, zone)
104
+ record_fqdn = Record.ensure_ends_without_dot(record.fqdn)
105
+
106
+ # Retrieve all records that you want to keep before it's updated because it will overwrite
107
+ all_records = client.get_zone_records(zone).map(&:data).map(&:items).flatten
108
+
109
+ update_zone_record_items = all_records.map do |r|
110
+ OCI::Dns::Models::RecordDetails.new(
111
+ domain: r.domain,
112
+ ttl: r.ttl,
113
+ rtype: r.rtype,
114
+ recordHash: r.record_hash,
115
+ rdata: r.rdata,
116
+ rrsetVersion: r.rrset_version,
117
+ isProtected: true,
118
+ )
119
+ end
120
+
121
+ update_zone_record_items << OCI::Dns::Models::RecordDetails.new(
122
+ domain: record_fqdn,
123
+ ttl: record.ttl,
124
+ rtype: record.type,
125
+ rdata: record.rdata_txt
126
+ )
127
+ update_zone_record_items.delete_if { |r| id == r.record_hash }
128
+
129
+ client.update_zone_records(
130
+ zone,
131
+ OCI::Dns::Models::UpdateZoneRecordsDetails.new(items: update_zone_record_items),
132
+ )
133
+ end
134
+
135
+ def secrets
136
+ super.fetch('oracle_cloud_dns')
137
+ end
138
+
139
+ def build_from_api(api_record)
140
+ fqdn = Record.ensure_ends_with_dot(api_record.domain)
141
+
142
+ record_type = api_record.rtype
143
+ return if record_type == 'SOA'
144
+
145
+ record = {
146
+ ttl: api_record.ttl,
147
+ fqdn: fqdn.downcase,
148
+ record_id: api_record.record_hash,
149
+ }
150
+ case record_type
151
+ when 'A', 'AAAA'
152
+ record[:address] = api_record.rdata
153
+ when 'ALIAS'
154
+ record[:alias] = api_record.rdata
155
+ when 'CAA'
156
+ flags, tag, value = api_record.rdata.split
157
+ record[:flags] = flags.to_i
158
+ record[:tag] = tag
159
+ record[:value] = Record.unquote(value)
160
+ when 'CNAME'
161
+ record[:cname] = api_record.rdata
162
+ when 'MX'
163
+ preference, exchange = api_record.rdata.split
164
+ record[:preference] = preference.to_i
165
+ record[:exchange] = exchange
166
+ when 'NS'
167
+ record[:nsdname] = api_record.rdata
168
+ when 'SPF', 'TXT'
169
+ record[:txtdata] = Record.unquote(api_record.rdata)
170
+ when 'SRV'
171
+ priority, weight, port, host = api_record.rdata.split
172
+ record[:priority] = priority.to_i
173
+ record[:weight] = weight.to_i
174
+ record[:port] = port.to_i
175
+ record[:target] = Record.ensure_ends_with_dot(host)
176
+ else
177
+ raise NameError, "Unsupported record type: #{record_type}"
178
+ end
179
+ Record.const_get(record_type).new(record)
180
+ end
181
+ end
182
+ end
183
+ end
@@ -46,6 +46,10 @@ module RecordStore
46
46
  fqdn.end_with?(".") ? fqdn : "#{fqdn}."
47
47
  end
48
48
 
49
+ def ensure_ends_without_dot(fqdn)
50
+ fqdn.sub(/\.$/, '')
51
+ end
52
+
49
53
  def needs_long_quotes?(value)
50
54
  value.length > 255 && value !~ /^((\\)?"((\\"|[^"])){1,255}(\\)?"\s*)+$/
51
55
  end
@@ -1,3 +1,3 @@
1
1
  module RecordStore
2
- VERSION = '5.5.4'.freeze
2
+ VERSION = '5.6.0'.freeze
3
3
  end
@@ -42,4 +42,5 @@ Gem::Specification.new do |spec|
42
42
  spec.add_development_dependency 'pry'
43
43
  spec.add_development_dependency 'webmock'
44
44
  spec.add_development_dependency 'rubocop'
45
+ spec.add_development_dependency 'oci'
45
46
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: record_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.5.4
4
+ version: 5.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Willem van Bergen
@@ -297,6 +297,20 @@ dependencies:
297
297
  - - ">="
298
298
  - !ruby/object:Gem::Version
299
299
  version: '0'
300
+ - !ruby/object:Gem::Dependency
301
+ name: oci
302
+ requirement: !ruby/object:Gem::Requirement
303
+ requirements:
304
+ - - ">="
305
+ - !ruby/object:Gem::Version
306
+ version: '0'
307
+ type: :development
308
+ prerelease: false
309
+ version_requirements: !ruby/object:Gem::Requirement
310
+ requirements:
311
+ - - ">="
312
+ - !ruby/object:Gem::Version
313
+ version: '0'
300
314
  description: Manage DNS through a git-based workflow. If you're looking for the original
301
315
  'record_store', that has been renamed to 'sequel_record_store'.
302
316
  email:
@@ -331,6 +345,7 @@ files:
331
345
  - lib/record_store/provider/google_cloud_dns.rb
332
346
  - lib/record_store/provider/ns1.rb
333
347
  - lib/record_store/provider/ns1/client.rb
348
+ - lib/record_store/provider/oracle_cloud_dns.rb
334
349
  - lib/record_store/record.rb
335
350
  - lib/record_store/record/a.rb
336
351
  - lib/record_store/record/aaaa.rb