record_store 6.1.2 → 6.2.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: 4d05ecb06f048975b797baa10df042222f03ee4f0b1b5e268afa87e97b16ede6
4
- data.tar.gz: 4ca96a597c88f5d17df9f85ea50e8743b0cab6fa4d57196447d3808cc22711a6
3
+ metadata.gz: 7c401c0dafc01955edd90912d793cdd0f27bd698df86f18ed4132e3ae0a8d1bc
4
+ data.tar.gz: 261f5a6a0c768d417e247746fe95955393075c643322fb7a5c701d39edef218d
5
5
  SHA512:
6
- metadata.gz: 98581b53f61499cb2f83d92ae2de4cf132ce2784cf56f8dc81531228f4090995f8e7a5a2c70f0a8fcac0cc5a3bdea29dd5c1d7b6996eef61e416c0c65c6a252d
7
- data.tar.gz: 8e753593bc358e83f82a0191f07528e14aa793305570afae5fcc865e1bdd97fffb48319fec43642e662c7b62e1070dd3b384464b9ca55a39e2a590fcf0f6738b
6
+ metadata.gz: 7160e11eec16c8ecea7fa7cf02ae7437a5093ec58f6f932a7e9e63feb85413ff5d9c28e0a90f8960ff76a94dd0bc7992e0712a0a6f40a2158062755079a16bac
7
+ data.tar.gz: 7d81f1268810c177bd785b8ab5610175d2e9b7f20db743d12996df2ab6f145c522a354a1f7e94e86e91b90c7a44b1b63bcbe1a92a1e93e0f1f5eefb13d76a659
@@ -52,6 +52,10 @@ module RecordStore
52
52
  false
53
53
  end
54
54
 
55
+ def empty_non_terminal_over_wildcard?
56
+ true
57
+ end
58
+
55
59
  def build_zone(zone_name:, config:)
56
60
  zone = Zone.new(name: zone_name)
57
61
  zone.records = retrieve_current_records(zone: zone_name)
@@ -136,6 +140,13 @@ module RecordStore
136
140
  backoff_multiplier: 2,
137
141
  max_backoff: 10
138
142
  )
143
+ waiter = BackoffWaiter.new(
144
+ "Waiting to retry after a connection reset",
145
+ initial_delay: delay,
146
+ multiplier: backoff_multiplier,
147
+ max_delay: max_backoff,
148
+ )
149
+
139
150
  loop do
140
151
  begin
141
152
  return yield
@@ -148,16 +159,10 @@ module RecordStore
148
159
  raise if max_conn_resets <= 0
149
160
  max_conn_resets -= 1
150
161
 
151
- $stderr.puts("Retrying in #{delay}s after a connection reset")
152
- backoff_sleep(delay)
153
- delay = [delay * backoff_multiplier, max_backoff].min
162
+ waiter.wait
154
163
  end
155
164
  end
156
165
  end
157
-
158
- def backoff_sleep(delay)
159
- sleep(delay)
160
- end
161
166
  end
162
167
  end
163
168
  end
@@ -12,6 +12,10 @@ module RecordStore
12
12
  true
13
13
  end
14
14
 
15
+ def empty_non_terminal_over_wildcard?
16
+ false
17
+ end
18
+
15
19
  # returns an array of Record objects that match the records which exist in the provider
16
20
  def retrieve_current_records(zone:, stdout: $stdout)
17
21
  retry_on_connection_errors do
@@ -1,4 +1,4 @@
1
- require_relative '../provider_utils/rate_limit'
1
+ require_relative '../provider_utils/waiter'
2
2
 
3
3
  # Patch Dnsimple client method which retrieves headers for API rate limit dynamically
4
4
  module Dnsimple
@@ -26,8 +26,8 @@ module Dnsimple
26
26
  rate_limit_periods = rate_limit_remaining + 1
27
27
  sleep_time = rate_limit_reset_in / rate_limit_periods.to_f
28
28
 
29
- rate_limit = RateLimit.new('DNSimple')
30
- rate_limit.sleep_for(sleep_time)
29
+ rate_limit = RateLimitWaiter.new('DNSimple')
30
+ rate_limit.wait(sleep_time)
31
31
  end
32
32
  end
33
33
  end
@@ -1,5 +1,5 @@
1
1
  require 'net/http'
2
- require_relative '../provider_utils/rate_limit'
2
+ require_relative '../provider_utils/waiter'
3
3
 
4
4
  # Patch the method which retrieves headers for API rate limit dynamically
5
5
  module NS1::Transport
@@ -14,8 +14,8 @@ module NS1::Transport
14
14
  sleep_time = response_hash[X_RATELIMIT_PERIOD].first.to_i /
15
15
  [1, response_hash[X_RATELIMIT_REMAINING].first.to_i].max.to_f
16
16
 
17
- rate_limit = RateLimit.new('NS1')
18
- rate_limit.sleep_for(sleep_time)
17
+ rate_limit = RateLimitWaiter.new('NS1')
18
+ rate_limit.wait(sleep_time)
19
19
  end
20
20
 
21
21
  body = JSON.parse(response.body)
@@ -0,0 +1,41 @@
1
+ class Waiter
2
+ def initialize(message = nil)
3
+ @message = message || 'Waiting'
4
+ end
5
+
6
+ attr_accessor :message
7
+
8
+ def wait(sleep_time)
9
+ while sleep_time > 0
10
+ wait_time = [10, sleep_time].min
11
+ puts "#{message} (#{sleep_time}s left)" if wait_time > 1
12
+ sleep(wait_time)
13
+ sleep_time -= wait_time
14
+ end
15
+ end
16
+ end
17
+
18
+ class RateLimitWaiter < Waiter
19
+ def initialize(provider)
20
+ super("Waiting on #{provider} rate-limit")
21
+ end
22
+ end
23
+
24
+ class BackoffWaiter < Waiter
25
+ def initialize(message, initial_delay:, multiplier:, max_delay: nil)
26
+ super(message)
27
+
28
+ @initial_delay = @current_delay = initial_delay
29
+ @multiplier = multiplier
30
+ @max_delay = max_delay
31
+ end
32
+
33
+ def reset
34
+ @current_delay = @initial_delay
35
+ end
36
+
37
+ def wait
38
+ super(@current_delay)
39
+ @current_delay = [@current_delay * @multiplier, @max_delay].compact.min
40
+ end
41
+ end
@@ -112,6 +112,10 @@ module RecordStore
112
112
  "[#{type}Record] #{fqdn} #{ttl} IN #{type} #{rdata_txt}"
113
113
  end
114
114
 
115
+ def wildcard?
116
+ fqdn.match?(/^\*\./)
117
+ end
118
+
115
119
  protected
116
120
 
117
121
  def validate_label_length
@@ -1,3 +1,3 @@
1
1
  module RecordStore
2
- VERSION = '6.1.2'.freeze
2
+ VERSION = '6.2.0'.freeze
3
3
  end
@@ -18,6 +18,7 @@ module RecordStore
18
18
  validate :validate_cname_records_dont_point_to_root
19
19
  validate :validate_same_ttl_for_records_sharing_fqdn_and_type
20
20
  validate :validate_provider_can_handle_zone_records
21
+ validate :validate_no_empty_non_terminal
21
22
  validate :validate_can_handle_alias_records
22
23
 
23
24
  class << self
@@ -258,6 +259,28 @@ module RecordStore
258
259
  end
259
260
  end
260
261
 
262
+ def validate_no_empty_non_terminal
263
+ return unless config.empty_non_terminal_over_wildcard?
264
+
265
+ wildcards = records.select(&:wildcard?).map(&:fqdn).uniq
266
+ wildcards.each do |wildcard|
267
+ suffix = wildcard[1..-1]
268
+
269
+ terminal_records = records.map(&:fqdn)
270
+ .select { |record| record.match?(/^([a-zA-Z0-9-_]+\.[a-zA-Z0-9-_])#{Regexp.escape(suffix)}$/) }
271
+ next unless terminal_records.any?
272
+
273
+ intermediate_records = records.map(&:fqdn)
274
+ .select { |record| record.match?(/^([a-zA-Z0-9-_]+)#{Regexp.escape(suffix)}$/) }
275
+ terminal_records.each do |terminal_record|
276
+ non_terminal = terminal_record.partition('.').last
277
+ errors.add(:records, "found empty non-terminal #{non_terminal} "\
278
+ "(caused by existing records #{wildcard} and #{terminal_record})")\
279
+ unless intermediate_records.include?(non_terminal)
280
+ end
281
+ end
282
+ end
283
+
261
284
  def validate_can_handle_alias_records
262
285
  return unless records.any? { |record| record.is_a?(Record::ALIAS) }
263
286
  return if config.supports_alias?
@@ -24,6 +24,10 @@ module RecordStore
24
24
  end
25
25
  end
26
26
 
27
+ def empty_non_terminal_over_wildcard?
28
+ valid_providers? && providers.any? { |provider| Provider.const_get(provider).empty_non_terminal_over_wildcard? }
29
+ end
30
+
27
31
  def to_hash
28
32
  config_hash = {
29
33
  providers: providers,
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: 6.1.2
4
+ version: 6.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Willem van Bergen
@@ -362,7 +362,7 @@ files:
362
362
  - lib/record_store/provider/ns1/client.rb
363
363
  - lib/record_store/provider/ns1/patch_api_header.rb
364
364
  - lib/record_store/provider/oracle_cloud_dns.rb
365
- - lib/record_store/provider/provider_utils/rate_limit.rb
365
+ - lib/record_store/provider/provider_utils/waiter.rb
366
366
  - lib/record_store/record.rb
367
367
  - lib/record_store/record/a.rb
368
368
  - lib/record_store/record/aaaa.rb
@@ -1,14 +0,0 @@
1
- class RateLimit
2
- def initialize(provider)
3
- @provider = provider
4
- end
5
-
6
- def sleep_for(sleep_time)
7
- while sleep_time > 0
8
- wait = [10, sleep_time].min
9
- puts "Waiting on #{@provider} rate-limit" if wait > 1
10
- sleep(wait)
11
- sleep_time -= wait
12
- end
13
- end
14
- end