test-kitchen 3.5.1 → 3.7.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: 43f3ba1a55d6f333784b955cda9e822970cd2226b9312f5dad31eb061e459688
4
- data.tar.gz: a4f73825f0766b4fa61e5206eab8fcb48bc77ff5eb4c17173b1c4ebe5a00ff14
3
+ metadata.gz: 78dcb8180d72d9ce32f3cf860d2dbb90d4c66ba2920cdf03252717bd4674a3f5
4
+ data.tar.gz: fc68fb60b6fa811425c3079a317946414cfca980198e4e668fbcc0e4c507841a
5
5
  SHA512:
6
- metadata.gz: c99da65b2481b02024d48852f700ad4b314319b12509b939370308f19866a5ee20145ffc0f1a840becd3eff6ecc28606394f9f3e3817ec88d9c5a2bcb230c0e8
7
- data.tar.gz: 8e09b252dc4ada45de3c3cae80c22762ad418db5ed765e0441653c43a6d25f7117d17108ede0ac0cf7eef5996b73289ac8e6e08af25ade71511525236244fc7c
6
+ metadata.gz: 04e4ddf2b8c612db3a71ef7a7d720c5f586813f8ba3263415d56385f41e90b89663e2c4091fbbd03f60ff4c8922413988df086c71a93fbf7a396f903303b03d9
7
+ data.tar.gz: 93131c18cdc7889dd9c2e477c598a409ae4d1b47a865fdf4bba6ae54da6b48de59bfc1c7b57015b0dc011a311762e18b13c13955e8e45cc95f852807845d4073
data/Gemfile CHANGED
@@ -1,15 +1,26 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- # Specify your gem"s dependencies in test-kitchen.gemspec
4
3
  gemspec
5
4
 
5
+ group :test do
6
+ gem "rake"
7
+ gem "rb-readline"
8
+ gem "aruba", ">= 0.11", "< 3.0"
9
+ gem "countloc", "~> 0.4"
10
+ gem "cucumber", ">= 9.2", "< 10"
11
+ gem "fakefs", "~> 2.0"
12
+ gem "maruku", "~> 0.6"
13
+ gem "minitest", "~> 5.3", "< 6.0"
14
+ gem "mocha", "~> 2.0"
15
+ end
16
+
6
17
  group :integration do
7
- gem "berkshelf"
18
+ gem "chef-cli"
8
19
  gem "kitchen-dokken"
9
20
  gem "kitchen-inspec"
10
21
  gem "kitchen-vagrant"
11
22
  end
12
23
 
13
24
  group :chefstyle do
14
- gem "chefstyle", "2.2.2"
15
- end
25
+ gem "chefstyle", "2.2.3"
26
+ end
data/lib/kitchen/cli.rb CHANGED
@@ -44,7 +44,7 @@ module Kitchen
44
44
  action: task,
45
45
  help: -> { help(task) },
46
46
  config: @config,
47
- shell: shell,
47
+ shell:,
48
48
  }.merge(additional_options)
49
49
 
50
50
  str_const = Thor::Util.camel_case(command)
@@ -33,7 +33,7 @@ module Kitchen
33
33
  loader = record_failure { load_loader }
34
34
 
35
35
  puts YAML.dump(Kitchen::Diagnostic.new(
36
- loader: loader, instances: instances, plugins: plugins?
36
+ loader:, instances:, plugins: plugins?
37
37
  ).read)
38
38
  end
39
39
 
@@ -216,11 +216,11 @@ module Kitchen
216
216
  /^win/i.match?(platform) ? "winrm" : Transport::DEFAULT_PLUGIN
217
217
  end,
218
218
  },
219
- kitchen_root: kitchen_root,
220
- test_base_path: test_base_path,
221
- log_level: log_level,
222
- log_overwrite: log_overwrite,
223
- debug: debug,
219
+ kitchen_root:,
220
+ test_base_path:,
221
+ log_level:,
222
+ log_overwrite:,
223
+ debug:,
224
224
  }
225
225
  end
226
226
 
@@ -250,8 +250,8 @@ module Kitchen
250
250
  driver: new_driver(suite, platform),
251
251
  lifecycle_hooks: new_lifecycle_hooks(suite, platform, sf),
252
252
  logger: new_instance_logger(suite, platform, index),
253
- suite: suite,
254
- platform: platform,
253
+ suite:,
254
+ platform:,
255
255
  provisioner: new_provisioner(suite, platform),
256
256
  transport: new_transport(suite, platform),
257
257
  verifier: new_verifier(suite, platform),
@@ -275,7 +275,7 @@ module Kitchen
275
275
  color: Color::COLORS[index % Color::COLORS.size].to_sym,
276
276
  logdev: log_location,
277
277
  level: Util.to_logger_level(log_level),
278
- log_overwrite: log_overwrite,
278
+ log_overwrite:,
279
279
  progname: name,
280
280
  colorize: @colorize
281
281
  )
@@ -299,7 +299,7 @@ module Kitchen
299
299
  # @param options [Hash] configuration hash (default: `{}`)
300
300
  # @api private
301
301
  def wait_for_sshd(hostname, username = nil, options = {})
302
- pseudo_state = { hostname: hostname }
302
+ pseudo_state = { hostname: }
303
303
  pseudo_state[:username] = username if username
304
304
  pseudo_state.merge!(options)
305
305
 
@@ -38,7 +38,7 @@ module Kitchen
38
38
  config[:kitchen_root]
39
39
  end
40
40
  # Build the options for mixlib-shellout.
41
- opts = {}.merge(user).merge(cwd: cwd, environment: environment)
41
+ opts = {}.merge(user).merge(cwd:, environment:)
42
42
  run_command(command, opts)
43
43
  end
44
44
 
@@ -58,7 +58,7 @@ module Kitchen
58
58
  #
59
59
  # @return [Hash] a diagnostic hash
60
60
  def diagnose
61
- { os_type: os_type, shell_type: shell_type }
61
+ { os_type:, shell_type: }
62
62
  end
63
63
  end
64
64
  end
@@ -26,7 +26,7 @@ module Kitchen
26
26
  # @author Baptiste Courtois <b.courtois@criteo.com>
27
27
  class PlatformFilter
28
28
  # Pattern used to determine whether a filter should be handled as a Regexp
29
- REGEXP_LIKE_PATTERN = %r{^/(?<pattern>.*)/(?<options>[ix]*)$}.freeze
29
+ REGEXP_LIKE_PATTERN = %r{^/(?<pattern>.*)/(?<options>[ix]*)$}
30
30
 
31
31
  # Converts platform filters into an array of PlatformFilter handling both strings and Regexp.
32
32
  # A string "looks-like" a regexp if it starts by / and end by / + Regexp options i or x
@@ -287,9 +287,9 @@ module Kitchen
287
287
  def update_dna_for_policyfile
288
288
  policy = Chef::Policyfile.new(
289
289
  policyfile, sandbox_path,
290
- logger: logger,
290
+ logger:,
291
291
  always_update: config[:always_update_cookbooks],
292
- policy_group: policy_group,
292
+ policy_group:,
293
293
  license: config[:chef_license]
294
294
  )
295
295
  Kitchen.mutex.synchronize do
@@ -297,7 +297,7 @@ module Kitchen
297
297
  end
298
298
  policy_name = JSON.parse(IO.read(policy.lockfile))["name"]
299
299
  policy_group = config[:policy_group] || "local"
300
- config[:attributes].merge(policy_name: policy_name, policy_group: policy_group)
300
+ config[:attributes].merge(policy_name:, policy_group:)
301
301
  end
302
302
 
303
303
  # Performs a Policyfile cookbook resolution inside a common mutex.
@@ -307,7 +307,7 @@ module Kitchen
307
307
  Kitchen.mutex.synchronize do
308
308
  Chef::Policyfile.new(
309
309
  policyfile, sandbox_path,
310
- logger: logger,
310
+ logger:,
311
311
  always_update: config[:always_update_cookbooks],
312
312
  policy_group: config[:policy_group],
313
313
  license: config[:chef_license]
@@ -321,7 +321,7 @@ module Kitchen
321
321
  def resolve_with_berkshelf
322
322
  Kitchen.mutex.synchronize do
323
323
  Chef::Berkshelf.new(berksfile, tmpbooks_dir,
324
- logger: logger,
324
+ logger:,
325
325
  always_update: config[:always_update_cookbooks]).resolve
326
326
  end
327
327
  end
@@ -244,6 +244,7 @@ module Kitchen
244
244
  end
245
245
 
246
246
  def doctor(state)
247
+ deprecated_config = instance.driver.instance_variable_get(:@deprecated_config)
247
248
  deprecated_config.each do |attr, msg|
248
249
  info("**** #{attr} deprecated\n#{msg}")
249
250
  end
@@ -347,7 +348,7 @@ module Kitchen
347
348
  omnibus_url: config[:chef_omnibus_url],
348
349
  project: project.nil? ? nil : project[1],
349
350
  install_flags: config[:chef_omnibus_install_options],
350
- sudo_command: sudo_command,
351
+ sudo_command:,
351
352
  }.tap do |opts|
352
353
  opts[:root] = config[:chef_omnibus_root] if config.key? :chef_omnibus_root
353
354
  %i{install_msi_url http_proxy https_proxy}.each do |key|
@@ -482,10 +483,10 @@ module Kitchen
482
483
  super
483
484
  if File.exist?(policyfile)
484
485
  debug("Policyfile found at #{policyfile}, using Policyfile to resolve cookbook dependencies")
485
- Chef::Policyfile.load!(logger: logger)
486
+ Chef::Policyfile.load!(logger:)
486
487
  elsif File.exist?(berksfile)
487
488
  debug("Berksfile found at #{berksfile}, using Berkshelf to resolve cookbook dependencies")
488
- Chef::Berkshelf.load!(logger: logger)
489
+ Chef::Berkshelf.load!(logger:)
489
490
  end
490
491
  end
491
492
 
@@ -0,0 +1,130 @@
1
+ #
2
+ # Author:: Thomas Heinen (<thomas.heinen@gmail.com>)
3
+ #
4
+ # Copyright (C) 2023, Thomas Heinen
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require_relative "chef_infra"
19
+
20
+ module Kitchen
21
+ module Provisioner
22
+ # Chef Target provisioner.
23
+ #
24
+ # @author Thomas Heinen <thomas.heinen@gmail.com>
25
+ class ChefTarget < ChefInfra
26
+ MIN_VERSION_REQUIRED = "19.0.0".freeze
27
+ class ChefVersionTooLow < UserError; end
28
+ class ChefClientNotFound < UserError; end
29
+ class RequireTrainTransport < UserError; end
30
+
31
+ default_config :install_strategy, "none"
32
+ default_config :sudo, true
33
+
34
+ def install_command; ""; end
35
+ def init_command; ""; end
36
+ def prepare_command; ""; end
37
+
38
+ def chef_args(client_rb_filename)
39
+ # Dummy execution to initialize and test remote connection
40
+ connection = instance.remote_exec("echo Connection established")
41
+
42
+ check_transport(connection)
43
+ check_local_chef_client
44
+
45
+ instance_name = instance.name
46
+ credentials_file = File.join(kitchen_basepath, ".kitchen", instance_name + ".ini")
47
+ File.write(credentials_file, connection.credentials_file)
48
+
49
+ super.concat([
50
+ "--target #{instance_name}",
51
+ "--credentials #{credentials_file}",
52
+ ])
53
+ end
54
+
55
+ def check_transport(connection)
56
+ debug("Checking for active transport")
57
+
58
+ unless connection.respond_to? "train_uri"
59
+ error("Chef Target Mode provisioner requires a Train-based transport like kitchen-transport-train")
60
+ raise RequireTrainTransport.new("No Train transport")
61
+ end
62
+
63
+ debug("Kitchen transport responds to train_uri function call, as required")
64
+ end
65
+
66
+ def check_local_chef_client
67
+ debug("Checking for chef-client version")
68
+
69
+ begin
70
+ client_version = `chef-client -v`.chop.split(":")[-1]
71
+ rescue Errno::ENOENT => e
72
+ error("Error determining Chef Infra version: #{e.exception.message}")
73
+ raise ChefClientNotFound.new("Need chef-client installed locally")
74
+ end
75
+
76
+ minimum_version = Gem::Version.new(MIN_VERSION_REQUIRED)
77
+ installed_version = Gem::Version.new(client_version)
78
+
79
+ if installed_version < minimum_version
80
+ error("Found Chef Infra version #{installed_version}, but require #{minimum_version} for Target Mode")
81
+ raise ChefVersionTooLow.new("Need version #{MIN_VERSION_REQUIRED} or higher")
82
+ end
83
+
84
+ debug("Chef Infra found and version constraints match")
85
+ end
86
+
87
+ def kitchen_basepath
88
+ instance.driver.config[:kitchen_root]
89
+ end
90
+
91
+ def create_sandbox
92
+ super
93
+
94
+ # Change config.rb to point to the local sandbox path, not to /tmp/kitchen
95
+ config[:root_path] = sandbox_path
96
+ prepare_config_rb
97
+ end
98
+
99
+ def call(state)
100
+ remote_connection = instance.transport.connection(state)
101
+
102
+ config[:uploads].to_h.each do |locals, remote|
103
+ debug("Uploading #{Array(locals).join(", ")} to #{remote}")
104
+ remote_connection.upload(locals.to_s, remote)
105
+ end
106
+
107
+ # no installation
108
+ create_sandbox
109
+ # no prepare command
110
+
111
+ # Stream output to logger
112
+ require "open3"
113
+ Open3.popen2e(run_command) do |_stdin, output, _thread|
114
+ output.each { |line| logger << line }
115
+ end
116
+
117
+ info("Downloading files from #{instance.to_str}")
118
+ config[:downloads].to_h.each do |remotes, local|
119
+ debug("Downloading #{Array(remotes).join(", ")} to #{local}")
120
+ remote_connection.download(remotes, local)
121
+ end
122
+ debug("Download complete")
123
+ rescue Kitchen::Transport::TransportFailed => ex
124
+ raise ActionFailed, ex.message
125
+ ensure
126
+ cleanup_sandbox
127
+ end
128
+ end
129
+ end
130
+ end
@@ -225,7 +225,7 @@ module Kitchen
225
225
  delay = 3
226
226
  session(
227
227
  retries: max_wait_until_ready / delay,
228
- delay: delay,
228
+ delay:,
229
229
  message: "Waiting for SSH service on #{hostname}:#{port}, " \
230
230
  "retrying in #{delay} seconds"
231
231
  )
@@ -468,7 +468,7 @@ module Kitchen
468
468
  # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
469
469
  def connection_options(data)
470
470
  opts = {
471
- logger: logger,
471
+ logger:,
472
472
  user_known_hosts_file: "/dev/null",
473
473
  hostname: data[:hostname],
474
474
  port: data[:port],
@@ -444,8 +444,8 @@ module Kitchen
444
444
  opts = {
445
445
  instance_name: instance.name,
446
446
  kitchen_root: data[:kitchen_root],
447
- logger: logger,
448
- endpoint: endpoint,
447
+ logger:,
448
+ endpoint:,
449
449
  user: data[:username],
450
450
  password: data[:password],
451
451
  rdp_port: data[:rdp_port],
@@ -457,7 +457,7 @@ module Kitchen
457
457
  transport: data[:winrm_transport],
458
458
  elevated: data[:elevated],
459
459
  elevated_username: data[:elevated_username] || data[:username],
460
- elevated_password: elevated_password,
460
+ elevated_password:,
461
461
  }
462
462
  opts.merge!(additional_transport_args(data, opts[:transport]))
463
463
  if opts[:transport].to_sym == :ssl && opts.key?(:client_cert) && opts.key?(:client_key)
@@ -16,5 +16,5 @@
16
16
  # limitations under the License.
17
17
 
18
18
  module Kitchen
19
- VERSION = "3.5.1".freeze
19
+ VERSION = "3.7.0".freeze
20
20
  end
data/lib/kitchen.rb CHANGED
@@ -91,7 +91,7 @@ module Kitchen
91
91
  stdout: $stdout,
92
92
  logdev: log_location,
93
93
  level: Util.to_logger_level(level),
94
- log_overwrite: log_overwrite
94
+ log_overwrite:
95
95
  )
96
96
  end
97
97
 
data/test-kitchen.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |gem|
20
20
  gem.executables = %w{kitchen}
21
21
  gem.require_paths = ["lib"]
22
22
 
23
- gem.required_ruby_version = ">= 2.7"
23
+ gem.required_ruby_version = ">= 3.1"
24
24
 
25
25
  gem.add_dependency "bcrypt_pbkdf", "~> 1.0" # ed25519 ssh key support
26
26
  gem.add_dependency "chef-utils", ">= 16.4.35"
@@ -37,15 +37,4 @@ Gem::Specification.new do |gem|
37
37
  # Required to run the Chef provisioner local license check for remote systems
38
38
  # TK is not under Chef EULA
39
39
  gem.add_dependency "license-acceptance", ">= 1.0.11", "< 3.0" # pinning until we can confirm 3+ works
40
-
41
- gem.add_development_dependency "rake"
42
- gem.add_development_dependency "rb-readline"
43
-
44
- gem.add_development_dependency "aruba", ">= 0.11", "< 3.0"
45
- gem.add_development_dependency "countloc", "~> 0.4"
46
- gem.add_development_dependency "cucumber", ">= 2.1", "< 8.0"
47
- gem.add_development_dependency "fakefs", "~> 2.0"
48
- gem.add_development_dependency "maruku", "~> 0.6"
49
- gem.add_development_dependency "minitest", "~> 5.3", "< 5.16"
50
- gem.add_development_dependency "mocha", "~> 2.0"
51
40
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: test-kitchen
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.1
4
+ version: 3.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fletcher Nichol
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-15 00:00:00.000000000 Z
11
+ date: 2024-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bcrypt_pbkdf
@@ -228,150 +228,6 @@ dependencies:
228
228
  - - "<"
229
229
  - !ruby/object:Gem::Version
230
230
  version: '3.0'
231
- - !ruby/object:Gem::Dependency
232
- name: rake
233
- requirement: !ruby/object:Gem::Requirement
234
- requirements:
235
- - - ">="
236
- - !ruby/object:Gem::Version
237
- version: '0'
238
- type: :development
239
- prerelease: false
240
- version_requirements: !ruby/object:Gem::Requirement
241
- requirements:
242
- - - ">="
243
- - !ruby/object:Gem::Version
244
- version: '0'
245
- - !ruby/object:Gem::Dependency
246
- name: rb-readline
247
- requirement: !ruby/object:Gem::Requirement
248
- requirements:
249
- - - ">="
250
- - !ruby/object:Gem::Version
251
- version: '0'
252
- type: :development
253
- prerelease: false
254
- version_requirements: !ruby/object:Gem::Requirement
255
- requirements:
256
- - - ">="
257
- - !ruby/object:Gem::Version
258
- version: '0'
259
- - !ruby/object:Gem::Dependency
260
- name: aruba
261
- requirement: !ruby/object:Gem::Requirement
262
- requirements:
263
- - - ">="
264
- - !ruby/object:Gem::Version
265
- version: '0.11'
266
- - - "<"
267
- - !ruby/object:Gem::Version
268
- version: '3.0'
269
- type: :development
270
- prerelease: false
271
- version_requirements: !ruby/object:Gem::Requirement
272
- requirements:
273
- - - ">="
274
- - !ruby/object:Gem::Version
275
- version: '0.11'
276
- - - "<"
277
- - !ruby/object:Gem::Version
278
- version: '3.0'
279
- - !ruby/object:Gem::Dependency
280
- name: countloc
281
- requirement: !ruby/object:Gem::Requirement
282
- requirements:
283
- - - "~>"
284
- - !ruby/object:Gem::Version
285
- version: '0.4'
286
- type: :development
287
- prerelease: false
288
- version_requirements: !ruby/object:Gem::Requirement
289
- requirements:
290
- - - "~>"
291
- - !ruby/object:Gem::Version
292
- version: '0.4'
293
- - !ruby/object:Gem::Dependency
294
- name: cucumber
295
- requirement: !ruby/object:Gem::Requirement
296
- requirements:
297
- - - ">="
298
- - !ruby/object:Gem::Version
299
- version: '2.1'
300
- - - "<"
301
- - !ruby/object:Gem::Version
302
- version: '8.0'
303
- type: :development
304
- prerelease: false
305
- version_requirements: !ruby/object:Gem::Requirement
306
- requirements:
307
- - - ">="
308
- - !ruby/object:Gem::Version
309
- version: '2.1'
310
- - - "<"
311
- - !ruby/object:Gem::Version
312
- version: '8.0'
313
- - !ruby/object:Gem::Dependency
314
- name: fakefs
315
- requirement: !ruby/object:Gem::Requirement
316
- requirements:
317
- - - "~>"
318
- - !ruby/object:Gem::Version
319
- version: '2.0'
320
- type: :development
321
- prerelease: false
322
- version_requirements: !ruby/object:Gem::Requirement
323
- requirements:
324
- - - "~>"
325
- - !ruby/object:Gem::Version
326
- version: '2.0'
327
- - !ruby/object:Gem::Dependency
328
- name: maruku
329
- requirement: !ruby/object:Gem::Requirement
330
- requirements:
331
- - - "~>"
332
- - !ruby/object:Gem::Version
333
- version: '0.6'
334
- type: :development
335
- prerelease: false
336
- version_requirements: !ruby/object:Gem::Requirement
337
- requirements:
338
- - - "~>"
339
- - !ruby/object:Gem::Version
340
- version: '0.6'
341
- - !ruby/object:Gem::Dependency
342
- name: minitest
343
- requirement: !ruby/object:Gem::Requirement
344
- requirements:
345
- - - "~>"
346
- - !ruby/object:Gem::Version
347
- version: '5.3'
348
- - - "<"
349
- - !ruby/object:Gem::Version
350
- version: '5.16'
351
- type: :development
352
- prerelease: false
353
- version_requirements: !ruby/object:Gem::Requirement
354
- requirements:
355
- - - "~>"
356
- - !ruby/object:Gem::Version
357
- version: '5.3'
358
- - - "<"
359
- - !ruby/object:Gem::Version
360
- version: '5.16'
361
- - !ruby/object:Gem::Dependency
362
- name: mocha
363
- requirement: !ruby/object:Gem::Requirement
364
- requirements:
365
- - - "~>"
366
- - !ruby/object:Gem::Version
367
- version: '2.0'
368
- type: :development
369
- prerelease: false
370
- version_requirements: !ruby/object:Gem::Requirement
371
- requirements:
372
- - - "~>"
373
- - !ruby/object:Gem::Version
374
- version: '2.0'
375
231
  description: Test Kitchen is an integration tool for developing and testing infrastructure
376
232
  code and software on isolated target platforms.
377
233
  email:
@@ -438,6 +294,7 @@ files:
438
294
  - lib/kitchen/provisioner/chef_base.rb
439
295
  - lib/kitchen/provisioner/chef_infra.rb
440
296
  - lib/kitchen/provisioner/chef_solo.rb
297
+ - lib/kitchen/provisioner/chef_target.rb
441
298
  - lib/kitchen/provisioner/chef_zero.rb
442
299
  - lib/kitchen/provisioner/dummy.rb
443
300
  - lib/kitchen/provisioner/shell.rb
@@ -500,7 +357,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
500
357
  requirements:
501
358
  - - ">="
502
359
  - !ruby/object:Gem::Version
503
- version: '2.7'
360
+ version: '3.1'
504
361
  required_rubygems_version: !ruby/object:Gem::Requirement
505
362
  requirements:
506
363
  - - ">="