record_store 5.5.4 → 5.6.0

Sign up to get free protection for your applications and to get access to all the features.
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