record_store 5.5.3 → 5.5.4

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