record_store 5.5.3 → 5.5.4

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.
@@ -0,0 +1,19 @@
1
+ inherit_from:
2
+ - https://shopify.github.io/ruby-style-guide/rubocop.yml
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.4
6
+ Exclude:
7
+ - vendor/**/*
8
+ UseCache: true
9
+ CacheRootDirectory: tmp/rubocop
10
+
11
+ Style/FrozenStringLiteralComment:
12
+ Enabled: false
13
+
14
+ Style/MethodCallWithArgsParentheses:
15
+ Include:
16
+ - '**/*.rb'
17
+
18
+ Style/ClassAndModuleChildren:
19
+ Enabled: false
@@ -8,4 +8,5 @@ before_install:
8
8
  - gem --version
9
9
 
10
10
  before_script:
11
+ - bin/rubocop --version && bin/rubocop
11
12
  - bin/setup
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $:.unshift File.expand_path('../../lib', __FILE__)
3
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
4
  require 'bundler/setup'
5
5
  require 'record_store'
6
6
 
@@ -8,4 +8,4 @@ RecordStore.zones_path = File.expand_path('../../dev/zones', __FILE__)
8
8
  RecordStore.config_path = File.expand_path('../../dev/config.yml', __FILE__)
9
9
 
10
10
  require 'pry'
11
- binding.pry(RecordStore)
11
+ binding.pry(RecordStore) # rubocop:disable Lint/Debugger
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $:.unshift File.expand_path('../../lib', __FILE__)
3
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
4
  require 'bundler/setup'
5
5
  require 'record_store'
6
6
 
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rubocop' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rubocop", "rubocop")
data/dev.yml CHANGED
@@ -17,3 +17,7 @@ commands:
17
17
  else
18
18
  bundle exec ruby -Itest "$@"
19
19
  fi
20
+ style:
21
+ syntax: ""
22
+ desc: 'Run rubocop'
23
+ run: 'bin/rubocop'
@@ -46,7 +46,10 @@ module RecordStore
46
46
  end
47
47
 
48
48
  def zones_path
49
- @zones_path ||= Pathname.new(File.expand_path(config.fetch('zones_path'), File.dirname(config_path))).realpath.to_s
49
+ @zones_path ||= Pathname.new(
50
+ File.expand_path(config.fetch('zones_path'),
51
+ File.dirname(config_path)),
52
+ ).realpath.to_s
50
53
  end
51
54
 
52
55
  def config_path
@@ -4,7 +4,9 @@ module RecordStore
4
4
  attr_accessor :type, :record, :id
5
5
 
6
6
  def initialize(type: nil, record: nil, id: nil)
7
- @type, @record, @id = type, record, id
7
+ @type = type
8
+ @record = record
9
+ @id = id
8
10
  end
9
11
 
10
12
  def self.addition(record)
@@ -37,7 +39,7 @@ module RecordStore
37
39
  def self.build_from(provider:, zone:)
38
40
  current_zone = provider.build_zone(zone_name: zone.unrooted_name, config: zone.config)
39
41
 
40
- self.new(
42
+ new(
41
43
  current_records: current_zone.records,
42
44
  desired_records: zone.records,
43
45
  provider: provider,
@@ -51,7 +53,9 @@ module RecordStore
51
53
  @provider = provider
52
54
  @zone = zone
53
55
 
54
- @additions, @removals, @updates = [], [], []
56
+ @additions = []
57
+ @removals = []
58
+ @updates = []
55
59
 
56
60
  build_changeset
57
61
  end
@@ -81,7 +85,7 @@ module RecordStore
81
85
  def build_changeset
82
86
  current_records_set = (current_records - unchanged).sort_by(&:to_s).group_by(&:key)
83
87
  desired_records_set = (desired_records - unchanged).sort_by(&:to_s).group_by(&:key)
84
- current_records_set.default_proc = desired_records_set.default_proc = Proc.new{Array.new}
88
+ current_records_set.default_proc = desired_records_set.default_proc = proc { [] }
85
89
 
86
90
  record_keys = current_records_set.keys | desired_records_set.keys
87
91
 
@@ -1,3 +1,5 @@
1
+ require 'English'
2
+
1
3
  module RecordStore
2
4
  class CLI < Thor
3
5
  class_option :config, desc: 'Path to config.yml', aliases: '-c'
@@ -34,9 +36,7 @@ module RecordStore
34
36
  def list
35
37
  Zone.each do |name, zone|
36
38
  puts "Zone: #{name}"
37
- zone.records.each do |record|
38
- record.log!
39
- end
39
+ zone.records.each(&:log!)
40
40
  end
41
41
  end
42
42
 
@@ -60,34 +60,33 @@ module RecordStore
60
60
  next if !options.fetch('verbose') && changeset.changes.empty?
61
61
 
62
62
  puts '-' * 20
63
- puts "Provider: #{changeset.provider.to_s}"
63
+ puts "Provider: #{changeset.provider}"
64
64
 
65
65
  if !changeset.additions.empty? || options.fetch('verbose')
66
66
  puts "Add:"
67
67
  changeset.additions.map(&:record).each do |record|
68
- puts " - #{record.to_s}"
68
+ puts " - #{record}"
69
69
  end
70
70
  end
71
71
 
72
72
  if !changeset.removals.empty? || options.fetch('verbose')
73
73
  puts "Remove:"
74
74
  changeset.removals.map(&:record).each do |record|
75
- puts " - #{record.to_s}"
75
+ puts " - #{record}"
76
76
  end
77
77
  end
78
78
 
79
79
  if !changeset.updates.empty? || options.fetch('verbose')
80
80
  puts "Update:"
81
81
  changeset.updates.map(&:record).each do |record|
82
- puts " - #{record.to_s}"
82
+ puts " - #{record}"
83
83
  end
84
84
  end
85
85
 
86
- if options.fetch('verbose')
87
- puts "Unchanged:"
88
- changeset.unchanged.each do |record|
89
- puts " - #{record.to_s}"
90
- end
86
+ next unless options.fetch('verbose')
87
+ puts "Unchanged:"
88
+ changeset.unchanged.each do |record|
89
+ puts " - #{record}"
91
90
  end
92
91
  end
93
92
  puts '=' * 20
@@ -105,7 +104,7 @@ module RecordStore
105
104
  end
106
105
 
107
106
  zones.each do |zone|
108
- abort "Attempted to apply invalid zone: #{zone.name}" unless zone.valid?
107
+ abort("Attempted to apply invalid zone: #{zone.name}") unless zone.valid?
109
108
 
110
109
  changesets = zone.build_changesets
111
110
  changesets.each(&:apply)
@@ -116,11 +115,12 @@ module RecordStore
116
115
 
117
116
  option :name, desc: 'Zone to download', aliases: '-n', type: :string, required: true
118
117
  option :provider, desc: 'Provider in which this zone exists', aliases: '-p', type: :string
119
- desc 'download', 'Downloads all records from zone and creates YAML zone definition in zones/ e.g. record-store download --name=shopify.io'
118
+ desc 'download', 'Downloads all records from zone and creates YAML zone definition in zones/ '\
119
+ 'e.g. record-store download --name=shopify.io'
120
120
  def download
121
121
  name = options.fetch('name')
122
- abort 'Please omit the period at the end of the zone' if name.ends_with?('.')
123
- abort 'Zone with this name already exists in zones/' if File.exist?("#{RecordStore.zones_path}/#{name}.yml")
122
+ abort('Please omit the period at the end of the zone') if name.ends_with?('.')
123
+ abort('Zone with this name already exists in zones/') if File.exist?("#{RecordStore.zones_path}/#{name}.yml")
124
124
 
125
125
  provider = options.fetch('provider', Provider.provider_for(name))
126
126
  if provider.nil?
@@ -151,11 +151,12 @@ module RecordStore
151
151
  desc 'sort', 'Sorts the zonefile alphabetically e.g. record-store sort --name=shopify.io'
152
152
  def sort
153
153
  name = options.fetch('name')
154
- abort "Please omit the period at the end of the zone" if name.ends_with?('.')
154
+ abort("Please omit the period at the end of the zone") if name.ends_with?('.')
155
155
 
156
156
  yaml = YAML.load_file("#{RecordStore.zones_path}/#{name}.yml")
157
- yaml.fetch(name).fetch('records').sort_by! { |r| [r.fetch('fqdn'), r.fetch('type'), r['nsdname'] || r['address']] }
158
-
157
+ yaml.fetch(name).fetch('records').sort_by! do |r|
158
+ [r.fetch('fqdn'), r.fetch('type'), r['nsdname'] || r['address']]
159
+ end
159
160
  File.write("#{RecordStore.zones_path}/#{name}.yml", yaml.deep_stringify_keys.to_yaml.gsub("---\n", ''))
160
161
  end
161
162
 
@@ -171,11 +172,11 @@ module RecordStore
171
172
  end
172
173
  end
173
174
 
174
- secrets = `ejson decrypt #{RecordStore.secrets_path.sub(/\.json\z/, ".#{environment}.ejson")}`
175
- if $?.exitstatus == 0
175
+ secrets = %x(ejson decrypt #{RecordStore.secrets_path.sub(/\.json\z/, ".#{environment}.ejson")})
176
+ if $CHILD_STATUS.success?
176
177
  File.write(RecordStore.secrets_path, secrets)
177
178
  else
178
- abort secrets
179
+ abort(secrets)
179
180
  end
180
181
  end
181
182
 
@@ -184,7 +185,7 @@ module RecordStore
184
185
  zones = Zone.modified.map(&:name)
185
186
 
186
187
  unless zones.empty?
187
- abort "The following zones have diverged: #{zones.join(', ')}"
188
+ abort("The following zones have diverged: #{zones.join(', ')}")
188
189
  end
189
190
  end
190
191
 
@@ -200,18 +201,18 @@ module RecordStore
200
201
  end
201
202
 
202
203
  invalid_records = zone.records.reject(&:valid?)
203
- puts ' Invalid records' if invalid_records.size > 0
204
+ puts ' Invalid records' unless invalid_records.empty?
204
205
 
205
206
  invalid_records.each do |record|
206
- puts " #{record.to_s}"
207
+ puts " #{record}"
207
208
  record.errors.each do |field, msg|
208
209
  puts " - #{field}: #{msg}"
209
210
  end
210
211
  end
211
212
  end
212
213
 
213
- if invalid_zones.size > 0
214
- abort "The following zones were invalid: #{invalid_zones.join(', ')}"
214
+ if invalid_zones.present?
215
+ abort("The following zones were invalid: #{invalid_zones.join(', ')}")
215
216
  else
216
217
  puts "All zones have valid definitions."
217
218
  end
@@ -227,7 +228,10 @@ module RecordStore
227
228
  end
228
229
 
229
230
  unless removals.empty?
230
- abort "As a safety measure, you cannot remove more than #{MAXIMUM_REMOVALS} records at a time per zone. (zones failing this: #{removals.map(&:name).join(', ')})"
231
+ error = +"As a safety measure, you cannot remove more than #{MAXIMUM_REMOVALS} "
232
+ error << 'records at a time per zone. '
233
+ error << "(zones failing this: #{removals.map(&:name).join(', ')})"
234
+ abort(error)
231
235
  end
232
236
  end
233
237
  end
@@ -235,30 +239,28 @@ module RecordStore
235
239
  SKIP_CHECKS = 'SKIP_DEPLOY_VALIDATIONS'
236
240
  desc 'validate_initial_state', "Validates state hasn't diverged since the last deploy"
237
241
  def validate_initial_state
238
- begin
239
- assert_empty_diff
240
- puts "Deploy will cause no changes, no need to validate initial state"
241
- rescue SystemExit
242
- if File.exist?(File.expand_path(SKIP_CHECKS, Dir.pwd))
243
- puts "Found '#{SKIP_CHECKS}', skipping predeploy validations"
244
- else
245
- puts "Checkout git SHA #{ENV['LAST_DEPLOYED_SHA']}"
246
- `git checkout #{ENV['LAST_DEPLOYED_SHA']}`
247
- abort "Checkout of old commit failed" if $?.exitstatus != 0
242
+ assert_empty_diff
243
+ puts "Deploy will cause no changes, no need to validate initial state"
244
+ rescue SystemExit
245
+ if File.exist?(File.expand_path(SKIP_CHECKS, Dir.pwd))
246
+ puts "Found '#{SKIP_CHECKS}', skipping predeploy validations"
247
+ else
248
+ puts "Checkout git SHA #{ENV['LAST_DEPLOYED_SHA']}"
249
+ %x(git checkout #{ENV['LAST_DEPLOYED_SHA']})
250
+ abort("Checkout of old commit failed") unless $CHILD_STATUS.success?
248
251
 
249
- `record-store secrets`
250
- abort "Decrypt secrets failed" if $?.exitstatus != 0
252
+ %x(record-store secrets)
253
+ abort("Decrypt secrets failed") unless $CHILD_STATUS.success?
251
254
 
252
- `record-store assert_empty_diff`
253
- abort "Dyn status has diverged!" if $?.exitstatus != 0
255
+ %x(record-store assert_empty_diff)
256
+ abort("Dyn status has diverged!") unless $CHILD_STATUS.success?
254
257
 
255
- puts "Checkout git SHA #{ENV['REVISION']}"
256
- `git checkout #{ENV['REVISION']}`
257
- abort "Checkout of new commit failed" if $?.exitstatus != 0
258
+ puts "Checkout git SHA #{ENV['REVISION']}"
259
+ %x(git checkout #{ENV['REVISION']})
260
+ abort("Checkout of new commit failed") unless $CHILD_STATUS.success?
258
261
 
259
- `record-store secrets`
260
- abort "Decrypt secrets failed" if $?.exitstatus != 0
261
- end
262
+ %x(record-store secrets)
263
+ abort("Decrypt secrets failed") unless $CHILD_STATUS.success?
262
264
  end
263
265
  end
264
266
 
@@ -9,20 +9,18 @@ module RecordStore
9
9
  begin
10
10
  ns_server = dns.getresource(zone_name, Resolv::DNS::Resource::IN::SOA).mname.to_s
11
11
  rescue Resolv::ResolvError
12
- abort "Domain doesn't exist"
12
+ abort("Domain doesn't exist")
13
13
  end
14
14
 
15
15
  case ns_server
16
- when /dnsimple\.com\z/
16
+ when /\.dnsimple\.com\z/
17
17
  'DNSimple'
18
- when /dynect\.net\z/
18
+ when /\.dynect\.net\z/
19
19
  'DynECT'
20
- when /googledomains\.com\z/
20
+ when /\.googledomains\.com\z/
21
21
  'GoogleCloudDNS'
22
22
  when /\.nsone\.net\z/
23
23
  'NS1'
24
- else
25
- nil
26
24
  end
27
25
  end
28
26
 
@@ -54,7 +52,7 @@ module RecordStore
54
52
  end
55
53
 
56
54
  # returns an array of Record objects that match the records which exist in the provider
57
- def retrieve_current_records(zone:, stdout: $stdout)
55
+ def retrieve_current_records(zone:, stdout: $stdout) # rubocop:disable Lint/UnusedMethodArgument
58
56
  raise NotImplementedError
59
57
  end
60
58
 
@@ -91,28 +89,28 @@ module RecordStore
91
89
  end
92
90
 
93
91
  def thawable?
94
- self.respond_to?(:thaw_zone)
92
+ respond_to?(:thaw_zone)
95
93
  end
96
94
 
97
95
  def freezable?
98
- self.respond_to?(:freeze_zone)
96
+ respond_to?(:freeze_zone)
99
97
  end
100
98
 
101
99
  def to_s
102
- self.name.demodulize
100
+ name.demodulize
103
101
  end
104
102
 
105
103
  private
106
104
 
107
- def add(record)
105
+ def add(record) # rubocop:disable Lint/UnusedMethodArgument
108
106
  raise NotImplementedError
109
107
  end
110
108
 
111
- def remove(record)
109
+ def remove(record) # rubocop:disable Lint/UnusedMethodArgument
112
110
  raise NotImplementedError
113
111
  end
114
112
 
115
- def update(id, record)
113
+ def update(id, record) # rubocop:disable Lint/UnusedMethodArgument
116
114
  raise NotImplementedError
117
115
  end
118
116
  end
@@ -113,7 +113,7 @@ module RecordStore
113
113
 
114
114
  def api_hash(record, zone)
115
115
  record_hash = {
116
- name: record.fqdn.gsub("#{Record.ensure_ends_with_dot(zone)}", '').chomp('.'),
116
+ name: record.fqdn.gsub(Record.ensure_ends_with_dot(zone).to_s, '').chomp('.'),
117
117
  ttl: record.ttl,
118
118
  type: record.type,
119
119
  }
@@ -138,7 +138,6 @@ module RecordStore
138
138
  record_hash[:content] = "#{record.weight} #{record.port} #{record.target.chomp('.')}"
139
139
  record_hash[:priority] = record.priority
140
140
  end
141
-
142
141
  record_hash
143
142
  end
144
143
  end
@@ -1,8 +1,8 @@
1
1
  require 'fog/dynect'
2
2
  require 'limiter'
3
3
 
4
- Fog::DNS::Dynect::Real.extend Limiter::Mixin
5
- Fog::DNS::Dynect::Real.limit_method :request, rate: 5, interval: 1 # 5 RPS == 300 RPM
4
+ Fog::DNS::Dynect::Real.extend(Limiter::Mixin)
5
+ Fog::DNS::Dynect::Real.limit_method(:request, rate: 5, interval: 1) # 5 RPS == 300 RPM
6
6
 
7
7
  module RecordStore
8
8
  class Provider::DynECT < Provider
@@ -34,7 +34,7 @@ module RecordStore
34
34
 
35
35
  # returns an array of Record objects that match the records which exist in the provider
36
36
  def retrieve_current_records(zone:, stdout: $stdout)
37
- session.get_all_records(zone).body.fetch('data').flat_map do |type, records|
37
+ session.get_all_records(zone).body.fetch('data').flat_map do |_type, records|
38
38
  records.map do |record_body|
39
39
  begin
40
40
  build_from_api(record_body)
@@ -88,8 +88,8 @@ module RecordStore
88
88
 
89
89
  def api_rdata(record)
90
90
  case record.type
91
- when 'TXT'
92
- { txtdata: record.rdata_txt }
91
+ when 'SPF', 'TXT'
92
+ { txtdata: Record.long_quote(record.rdata_txt) }
93
93
  else
94
94
  record.rdata
95
95
  end
@@ -102,7 +102,7 @@ module RecordStore
102
102
  type = record.fetch(:record_type)
103
103
  return if type == 'SOA'
104
104
 
105
- record[:txtdata] = Record.unescape(record[:txtdata]) if %w[SPF TXT].include?(type)
105
+ record[:txtdata] = Record.unlong_quote(Record.unescape(record[:txtdata])) if %w[SPF TXT].include?(type)
106
106
 
107
107
  fqdn = record.fetch(:fqdn)
108
108
  fqdn = "#{fqdn}." unless fqdn.ends_with?('.')