kitchen-vra 3.3.2 → 3.3.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.
@@ -22,16 +22,42 @@ require "kitchen"
22
22
  require "highline/import"
23
23
  require "openssl" unless defined?(OpenSSL)
24
24
  require "base64" unless defined?(Base64)
25
- require "digest/sha1" unless defined?(Digest::SHA1)
25
+ require "digest" unless defined?(Digest)
26
+ require "fileutils" unless defined?(FileUtils)
26
27
  require "vra"
27
28
  require_relative "vra_version"
28
29
 
29
30
  module Kitchen
31
+ # Test Kitchen's driver plugins.
30
32
  module Driver
33
+ # Test Kitchen driver for VMware vRealize Automation (vRA) 8.x.
34
+ #
35
+ # Unlike a cloud driver that creates a machine directly, this driver
36
+ # submits a request against a vRA catalog item and waits for vRA's own
37
+ # automation to build a deployment. The blueprint behind that catalog item
38
+ # decides what gets built; this driver only supplies the image, flavor,
39
+ # and project, then waits for a single VM to come back.
40
+ #
41
+ # The blueprint must return exactly one VM. A blueprint returning several,
42
+ # or none, fails the +create+ rather than guessing which one to test.
43
+ #
44
+ # @see https://www.vmware.com/products/vrealize-automation.html vRealize Automation
31
45
  class Vra < Kitchen::Driver::Base # rubocop:disable Metrics/ClassLength
32
46
  kitchen_driver_api_version 2
33
47
  plugin_version Kitchen::Driver::VRA_VERSION
34
48
 
49
+ # Location of the credential cache, relative to the working directory.
50
+ CREDENTIALS_CACHE_FILE = ".kitchen/cached_vra"
51
+
52
+ # Cipher used for the credential cache. GCM is authenticated, so a cache
53
+ # written for a different +base_url+, or one that has been altered on
54
+ # disk, fails to decrypt rather than yielding garbage credentials.
55
+ CREDENTIALS_CIPHER = "aes-256-gcm"
56
+
57
+ # Marker for the cache file layout, so a later format change can reject
58
+ # old files instead of misreading them.
59
+ CREDENTIALS_CACHE_VERSION = "v1"
60
+
35
61
  default_config :username, nil
36
62
  default_config :password, nil
37
63
  required_config :base_url
@@ -68,10 +94,20 @@ module Kitchen
68
94
  In vRA 8.x, the 'tenant' configuration is no longer relevant for authentication.
69
95
  Please use the 'domain' configuration in its place.".dup)
70
96
 
97
+ # @return [String] the driver's display name in `kitchen list`
71
98
  def name
72
99
  "vRA"
73
100
  end
74
101
 
102
+ # Resolves the vRA username and password, prompting if necessary.
103
+ #
104
+ # Sources are tried in order: explicit config, then the +VRA_USER_NAME+
105
+ # and +VRA_USER_PASSWORD+ environment variables, then the credential
106
+ # cache, then an interactive prompt.
107
+ #
108
+ # @param force_change [Boolean] prompt even if credentials already
109
+ # resolved, used to re-ask after an authentication failure
110
+ # @return [void]
75
111
  def check_config(force_change = false)
76
112
  config[:username] = config[:username] || ENV["VRA_USER_NAME"]
77
113
  config[:password] = config[:password] || ENV["VRA_USER_PASSWORD"]
@@ -82,43 +118,104 @@ module Kitchen
82
118
  c_save if config[:cache_credentials]
83
119
  end
84
120
 
121
+ # Writes the resolved credentials to {CREDENTIALS_CACHE_FILE}.
122
+ #
123
+ # The file is obfuscated rather than secured: the key is derived from
124
+ # +base_url+, which is not a secret, so anyone holding both the file and
125
+ # the kitchen config can recover the credentials. It keeps passwords out
126
+ # of plain sight on disk; it is not a substitute for a secret store.
127
+ #
128
+ # @return [void]
85
129
  def c_save
86
- cipher = OpenSSL::Cipher.new("cip-her-aes")
87
- cipher.encrypt
88
- cipher.key = Digest::SHA1.hexdigest(config[:base_url])
89
- iv_user = cipher.random_iv
90
- cipher.iv = iv_user
91
- username = cipher.update(config[:username]) + cipher.final
92
- iv_pwd = cipher.random_iv
93
- cipher.iv = iv_pwd
94
- password = cipher.update(config[:password]) + cipher.final
95
- output = "#{Base64.encode64(iv_user).strip!}:#{Base64.encode64(username).strip!}:#{Base64.encode64(iv_pwd).strip!}:#{Base64.encode64(password).strip!}"
96
- file = File.open(".kitchen/cached_vra", "w")
97
- file.write(output)
98
- file.close
99
- rescue
100
- puts "Unable to save credentials"
130
+ FileUtils.mkdir_p(File.dirname(CREDENTIALS_CACHE_FILE))
131
+ fields = [config[:username], config[:password]].flat_map { |value| encrypt_credential(value) }
132
+
133
+ File.open(CREDENTIALS_CACHE_FILE, File::WRONLY | File::CREAT | File::TRUNC, 0o600) do |file|
134
+ file.write(([CREDENTIALS_CACHE_VERSION] + fields).join(":"))
135
+ end
136
+ # The mode above only applies when the file is created, so narrow the
137
+ # permissions of a cache left behind by an earlier run as well.
138
+ File.chmod(0o600, CREDENTIALS_CACHE_FILE)
139
+ rescue => e
140
+ warn("Unable to save credentials to #{CREDENTIALS_CACHE_FILE}: #{e.message}")
101
141
  end
102
142
 
143
+ # Reads credentials back from {CREDENTIALS_CACHE_FILE}.
144
+ #
145
+ # A cache that cannot be decrypted -- a different +base_url+, a truncated
146
+ # or edited file, an older layout -- is reported and ignored, leaving the
147
+ # credentials unset so the caller falls through to prompting.
148
+ #
149
+ # @return [void]
103
150
  def c_load
104
- if File.exist? ".kitchen/cached_vra"
105
- encrypted = File.read(".kitchen/cached_vra")
106
- iv_user = Base64.decode64(encrypted.split(":")[0] + '\n')
107
- username = Base64.decode64(encrypted.split(":")[1] + "\n")
108
- iv_pwd = Base64.decode64(encrypted.split(":")[2] + "\n")
109
- password = Base64.decode64(encrypted.split(":")[3] + "\n")
110
- cipher = OpenSSL::Cipher.new("cip-her-aes")
111
- cipher.decrypt
112
- cipher.key = Digest::SHA1.hexdigest(config[:base_url])
113
- cipher.iv = iv_user
114
- config[:username] = cipher.update(username) + cipher.final
115
- cipher.iv = iv_pwd
116
- config[:password] = cipher.update(password) + cipher.final
117
- end
118
- rescue
119
- puts "Failed to load cached credentials"
151
+ return unless File.exist?(CREDENTIALS_CACHE_FILE)
152
+
153
+ version, *fields = File.read(CREDENTIALS_CACHE_FILE).strip.split(":")
154
+ raise "unrecognized cache format" unless version == CREDENTIALS_CACHE_VERSION && fields.length == 6
155
+
156
+ # Decrypt both before assigning either, so a partially readable cache
157
+ # cannot leave half the credentials set.
158
+ username = decrypt_credential(*fields[0, 3])
159
+ password = decrypt_credential(*fields[3, 3])
160
+
161
+ config[:username] = username
162
+ config[:password] = password
163
+ rescue => e
164
+ warn("Failed to load cached credentials from #{CREDENTIALS_CACHE_FILE}: #{e.message}")
165
+ end
166
+
167
+ # Encrypts one credential for the cache file.
168
+ #
169
+ # @param value [String] the credential to encrypt
170
+ # @return [Array<String>] Base64-encoded IV, authentication tag, and
171
+ # ciphertext, in that order
172
+ def encrypt_credential(value)
173
+ cipher = OpenSSL::Cipher.new(CREDENTIALS_CIPHER)
174
+ cipher.encrypt
175
+ cipher.key = credentials_key
176
+ iv = cipher.random_iv
177
+ encrypted = cipher.update(value.to_s) + cipher.final
178
+
179
+ [iv, cipher.auth_tag, encrypted].map { |part| Base64.strict_encode64(part) }
180
+ end
181
+
182
+ # Decrypts one credential from the cache file.
183
+ #
184
+ # @param iv [String] Base64-encoded initialization vector
185
+ # @param auth_tag [String] Base64-encoded GCM authentication tag
186
+ # @param encrypted [String] Base64-encoded ciphertext
187
+ # @return [String] the decrypted credential
188
+ # @raise [OpenSSL::Cipher::CipherError] if the key or tag does not match
189
+ def decrypt_credential(iv, auth_tag, encrypted)
190
+ cipher = OpenSSL::Cipher.new(CREDENTIALS_CIPHER)
191
+ cipher.decrypt
192
+ cipher.key = credentials_key
193
+ cipher.iv = Base64.strict_decode64(iv)
194
+ cipher.auth_tag = Base64.strict_decode64(auth_tag)
195
+
196
+ cipher.update(Base64.strict_decode64(encrypted)) + cipher.final
197
+ end
198
+
199
+ # Derives the cache key from +base_url+.
200
+ #
201
+ # SHA-256 is used for its digest length: {CREDENTIALS_CIPHER} requires a
202
+ # 32-byte key, which +Digest::SHA256.digest+ returns exactly.
203
+ #
204
+ # @return [String] a 32-byte key
205
+ def credentials_key
206
+ Digest::SHA256.digest(config[:base_url].to_s)
120
207
  end
121
208
 
209
+ # Requests a deployment from vRA and waits until it can be logged into.
210
+ #
211
+ # Returns immediately if the state already names a deployment, so a
212
+ # re-run does not build a second one.
213
+ #
214
+ # @param state [Hash] mutable instance state; gains +deployment_id+,
215
+ # +hostname+, and +ssh_key+
216
+ # @return [void]
217
+ # @raise [RuntimeError] if the vRA request fails or does not yield
218
+ # exactly one VM
122
219
  def create(state)
123
220
  return if state[:deployment_id]
124
221
 
@@ -131,6 +228,15 @@ module Kitchen
131
228
  info("Server #{server.deployment_id} (#{server.name}) ready.")
132
229
  end
133
230
 
231
+ # Works out the address Test Kitchen should connect to.
232
+ #
233
+ # With +use_dns+ set, the server's name is used, optionally suffixed with
234
+ # +dns_suffix+. Otherwise the IP address is preferred, falling back to
235
+ # the name with a warning when vRA reports no address.
236
+ #
237
+ # @param server [Vra::Resource] the VM vRA built
238
+ # @return [String] a hostname or IP address
239
+ # @raise [RuntimeError] if +use_dns+ is set but vRA returned no name
134
240
  def hostname_for(server)
135
241
  if config[:use_dns]
136
242
  raise "No server name returned for the vRA request" if server.name.nil?
@@ -147,6 +253,11 @@ module Kitchen
147
253
  end
148
254
  end
149
255
 
256
+ # Submits the catalog request and waits for vRA to finish building it.
257
+ #
258
+ # @return [Vra::Resource] the single VM the blueprint produced
259
+ # @raise [RuntimeError] if the request failed, or produced zero or more
260
+ # than one VM
150
261
  def request_server
151
262
  info("Building vRA catalog request...")
152
263
 
@@ -167,6 +278,16 @@ module Kitchen
167
278
  servers.first
168
279
  end
169
280
 
281
+ # Waits for the transport to accept a connection, retrying on failure.
282
+ #
283
+ # Backs off in five-second steps up to thirty seconds between attempts.
284
+ # Once +server_ready_retries+ is exceeded the deployment is destroyed
285
+ # before the error is re-raised, so a machine that never comes up is not
286
+ # left running and billable.
287
+ #
288
+ # @param state [Hash] instance state describing how to connect
289
+ # @param server [Vra::Resource] the VM being waited on
290
+ # @return [void]
170
291
  def wait_for_server(state, server)
171
292
  info("Server #{server.id} (#{server.name}) created. Waiting until ready...")
172
293
 
@@ -193,6 +314,14 @@ module Kitchen
193
314
  end
194
315
  end
195
316
 
317
+ # Destroys the vRA deployment, if one exists.
318
+ #
319
+ # A deployment that vRA no longer knows about, or that offers no destroy
320
+ # action, is treated as already gone rather than an error. The cached
321
+ # credentials file is removed afterwards.
322
+ #
323
+ # @param state [Hash] instance state naming the deployment
324
+ # @return [void]
196
325
  def destroy(state)
197
326
  return if state[:deployment_id].nil?
198
327
 
@@ -217,6 +346,14 @@ module Kitchen
217
346
  info("Removed cached file")
218
347
  end
219
348
 
349
+ # Builds the vRA catalog request for the configured blueprint.
350
+ #
351
+ # When +catalog_name+ is given it is resolved to a catalog ID first.
352
+ # A deployment name is only sent when +unique_name+ is false; otherwise
353
+ # vRA is left to name the deployment after its request ID.
354
+ #
355
+ # @return [Vra::CatalogRequest] a request ready to submit
356
+ # @raise [Kitchen::InstanceFailure] if no catalog could be resolved
220
357
  def catalog_request # rubocop:disable Metrics/MethodLength
221
358
  unless config[:catalog_name].nil?
222
359
  info("Fetching Catalog ID by Catalog Name")
@@ -251,6 +388,12 @@ module Kitchen
251
388
  catalog_request
252
389
  end
253
390
 
391
+ # The vRA API client, built from the resolved credentials.
392
+ #
393
+ # On any failure the credentials are re-prompted, on the assumption that
394
+ # what failed was authentication.
395
+ #
396
+ # @return [Vra::Client]
254
397
  def vra_client
255
398
  check_config config[:cache_credentials]
256
399
  @client ||= ::Vra::Client.new(
@@ -264,6 +407,14 @@ module Kitchen
264
407
  check_config true
265
408
  end
266
409
 
410
+ # Polls a vRA request until it completes or times out.
411
+ #
412
+ # Polls every +request_refresh_rate+ seconds, logging each change of
413
+ # status, and gives up after +request_timeout+ seconds.
414
+ #
415
+ # @param request [Vra::Request] the request to poll
416
+ # @return [void]
417
+ # @raise [Timeout::Error] if the request does not complete in time
267
418
  def wait_for_request(request)
268
419
  # config = check_config config
269
420
 
@@ -18,8 +18,11 @@
18
18
  # limitations under the License.
19
19
  #
20
20
 
21
+ # Test Kitchen's top-level namespace.
21
22
  module Kitchen
23
+ # Test Kitchen's driver plugins.
22
24
  module Driver
23
- VRA_VERSION = "3.3.2"
25
+ # The version of the kitchen-vra gem.
26
+ VRA_VERSION = "3.3.4"
24
27
  end
25
28
  end
@@ -0,0 +1,12 @@
1
+ {
2
+ "packages": {
3
+ ".": {
4
+ "package-name": "kitchen-vra",
5
+ "changelog-path": "CHANGELOG.md",
6
+ "release-type": "ruby",
7
+ "include-component-in-tag": false,
8
+ "version-file": "lib/kitchen/driver/vra_version.rb"
9
+ }
10
+ },
11
+ "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
12
+ }
data/renovate.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3
+ "extends": [
4
+ "config:recommended",
5
+ ":disableDependencyDashboard",
6
+ "schedule:automergeEarlyMondays"
7
+ ]
8
+ }
data/spec/vra_spec.rb CHANGED
@@ -19,6 +19,8 @@
19
19
  #
20
20
 
21
21
  require "spec_helper"
22
+ require "tmpdir"
23
+ require "fileutils"
22
24
  require "kitchen/driver/vra"
23
25
  require "kitchen/provisioner/dummy"
24
26
  require "kitchen/transport/dummy"
@@ -447,7 +449,7 @@ describe Kitchen::Driver::Vra do
447
449
  }
448
450
  end
449
451
 
450
- it "sets extra parmeters" do
452
+ it "sets extra parameters" do
451
453
  expect(catalog_request).to receive(:set_parameters).with("key1", { type: "string", value: "value1" })
452
454
  expect(catalog_request).to receive(:set_parameters).with("key2", { type: "integer", value: 123 })
453
455
  driver.catalog_request
@@ -510,4 +512,99 @@ describe Kitchen::Driver::Vra do
510
512
  end
511
513
  end
512
514
  end
515
+
516
+ describe "credential caching" do
517
+ let(:cache_dir) { Dir.mktmpdir("kitchen-vra-spec") }
518
+ let(:cache_file) { File.join(cache_dir, ".kitchen", "cached_vra") }
519
+
520
+ # c_save/c_load address the cache by a path relative to the working
521
+ # directory, so each example runs inside a throwaway directory.
522
+ around do |example|
523
+ Dir.chdir(cache_dir) { example.run }
524
+ end
525
+
526
+ after { FileUtils.remove_entry(cache_dir) }
527
+
528
+ describe "#c_save" do
529
+ it "creates the cache file" do
530
+ driver.c_save
531
+ expect(File.exist?(cache_file)).to be true
532
+ end
533
+
534
+ it "creates the .kitchen directory when it does not exist" do
535
+ expect { driver.c_save }.to change { Dir.exist?(File.join(cache_dir, ".kitchen")) }.from(false).to(true)
536
+ end
537
+
538
+ it "writes the file readable only by its owner" do
539
+ driver.c_save
540
+ expect(File.stat(cache_file).mode & 0o777).to eq(0o600)
541
+ end
542
+
543
+ it "does not write the password in the clear" do
544
+ driver.c_save
545
+ expect(File.read(cache_file)).not_to include("mypassword")
546
+ end
547
+ end
548
+
549
+ describe "#c_load" do
550
+ it "restores credentials written by #c_save" do
551
+ driver.c_save
552
+
553
+ reader = Kitchen::Driver::Vra.new(config.reject { |k, _v| %i{username password}.include?(k) })
554
+ allow(reader).to receive(:instance).and_return(instance)
555
+ reader.c_load
556
+
557
+ expect(reader[:username]).to eq("myuser")
558
+ expect(reader[:password]).to eq("mypassword")
559
+ end
560
+
561
+ it "does nothing when no cache file exists" do
562
+ driver.c_load
563
+ expect(driver[:username]).to eq("myuser")
564
+ end
565
+
566
+ it "refuses a cache written against a different base_url" do
567
+ driver.c_save
568
+
569
+ other = Kitchen::Driver::Vra.new(config.merge(base_url: "https://other.corp.local")
570
+ .reject { |k, _v| %i{username password}.include?(k) })
571
+ allow(other).to receive(:instance).and_return(instance)
572
+ expect(other).to receive(:warn).with(/Failed to load cached credentials/)
573
+ other.c_load
574
+
575
+ expect(other[:username]).to be_nil
576
+ expect(other[:password]).to be_nil
577
+ end
578
+
579
+ it "refuses a corrupted cache rather than returning garbage" do
580
+ driver.c_save
581
+ File.write(cache_file, File.read(cache_file).succ)
582
+
583
+ loader = Kitchen::Driver::Vra.new(config.reject { |k, _v| %i{username password}.include?(k) })
584
+ allow(loader).to receive(:instance).and_return(instance)
585
+ expect(loader).to receive(:warn).with(/Failed to load cached credentials/)
586
+ loader.c_load
587
+
588
+ expect(loader[:username]).to be_nil
589
+ end
590
+ end
591
+
592
+ describe "#check_config" do
593
+ it "uses the cache instead of prompting" do
594
+ driver.c_save
595
+
596
+ reader = Kitchen::Driver::Vra.new(config.reject { |k, _v| %i{username password}.include?(k) })
597
+ allow(reader).to receive(:instance).and_return(instance)
598
+ allow(ENV).to receive(:[]).and_call_original
599
+ allow(ENV).to receive(:[]).with("VRA_USER_NAME").and_return(nil)
600
+ allow(ENV).to receive(:[]).with("VRA_USER_PASSWORD").and_return(nil)
601
+ expect(reader).not_to receive(:ask)
602
+
603
+ reader.check_config
604
+
605
+ expect(reader[:username]).to eq("myuser")
606
+ expect(reader[:password]).to eq("mypassword")
607
+ end
608
+ end
609
+ end
513
610
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-vra
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.2
4
+ version: 3.3.4
5
5
  platform: ruby
6
6
  authors:
7
- - Chef Commmunity Tools Team
7
+ - Chef Community Tools Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-05 00:00:00.000000000 Z
11
+ date: 2026-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-kitchen
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: 2.2.3
88
88
  - - "<"
89
89
  - !ruby/object:Gem::Version
90
- version: 2.5.0
90
+ version: 3.1.0
91
91
  type: :runtime
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
@@ -97,77 +97,7 @@ dependencies:
97
97
  version: 2.2.3
98
98
  - - "<"
99
99
  - !ruby/object:Gem::Version
100
- version: 2.5.0
101
- - !ruby/object:Gem::Dependency
102
- name: rake
103
- requirement: !ruby/object:Gem::Requirement
104
- requirements:
105
- - - "~>"
106
- - !ruby/object:Gem::Version
107
- version: '13.0'
108
- type: :development
109
- prerelease: false
110
- version_requirements: !ruby/object:Gem::Requirement
111
- requirements:
112
- - - "~>"
113
- - !ruby/object:Gem::Version
114
- version: '13.0'
115
- - !ruby/object:Gem::Dependency
116
- name: rspec
117
- requirement: !ruby/object:Gem::Requirement
118
- requirements:
119
- - - "~>"
120
- - !ruby/object:Gem::Version
121
- version: '3.2'
122
- type: :development
123
- prerelease: false
124
- version_requirements: !ruby/object:Gem::Requirement
125
- requirements:
126
- - - "~>"
127
- - !ruby/object:Gem::Version
128
- version: '3.2'
129
- - !ruby/object:Gem::Dependency
130
- name: simplecov
131
- requirement: !ruby/object:Gem::Requirement
132
- requirements:
133
- - - "~>"
134
- - !ruby/object:Gem::Version
135
- version: '0.10'
136
- type: :development
137
- prerelease: false
138
- version_requirements: !ruby/object:Gem::Requirement
139
- requirements:
140
- - - "~>"
141
- - !ruby/object:Gem::Version
142
- version: '0.10'
143
- - !ruby/object:Gem::Dependency
144
- name: webmock
145
- requirement: !ruby/object:Gem::Requirement
146
- requirements:
147
- - - "~>"
148
- - !ruby/object:Gem::Version
149
- version: '3.14'
150
- type: :development
151
- prerelease: false
152
- version_requirements: !ruby/object:Gem::Requirement
153
- requirements:
154
- - - "~>"
155
- - !ruby/object:Gem::Version
156
- version: '3.14'
157
- - !ruby/object:Gem::Dependency
158
- name: chefstyle
159
- requirement: !ruby/object:Gem::Requirement
160
- requirements:
161
- - - "~>"
162
- - !ruby/object:Gem::Version
163
- version: 2.2.1
164
- type: :development
165
- prerelease: false
166
- version_requirements: !ruby/object:Gem::Requirement
167
- requirements:
168
- - - "~>"
169
- - !ruby/object:Gem::Version
170
- version: 2.2.1
100
+ version: 3.1.0
171
101
  description: A Test Kitchen driver for VMware vRealize Automation (vRA)
172
102
  email:
173
103
  - oss@chef.io
@@ -176,15 +106,16 @@ extensions: []
176
106
  extra_rdoc_files: []
177
107
  files:
178
108
  - ".github/CODEOWNERS"
179
- - ".github/dependabot.yml"
180
109
  - ".github/workflows/linters.yml"
181
- - ".github/workflows/please-release.yml"
182
110
  - ".github/workflows/publish.yml"
183
111
  - ".gitignore"
184
112
  - ".markdownlint.yaml"
185
- - ".mdlrc"
113
+ - ".release-please-manifest.json"
186
114
  - ".rubocop.yml"
115
+ - ".yamllint"
116
+ - ".yardopts"
187
117
  - CHANGELOG.md
118
+ - CONTRIBUTING.md
188
119
  - Gemfile
189
120
  - LICENSE.txt
190
121
  - README.md
@@ -192,6 +123,8 @@ files:
192
123
  - kitchen-vra.gemspec
193
124
  - lib/kitchen/driver/vra.rb
194
125
  - lib/kitchen/driver/vra_version.rb
126
+ - release-please-config.json
127
+ - renovate.json
195
128
  - spec/spec_helper.rb
196
129
  - spec/vra_spec.rb
197
130
  homepage: https://github.com/test-kitchen/kitchen-vra
@@ -206,17 +139,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
206
139
  requirements:
207
140
  - - ">="
208
141
  - !ruby/object:Gem::Version
209
- version: '2.7'
142
+ version: '3.1'
210
143
  required_rubygems_version: !ruby/object:Gem::Requirement
211
144
  requirements:
212
145
  - - ">="
213
146
  - !ruby/object:Gem::Version
214
147
  version: '0'
215
148
  requirements: []
216
- rubygems_version: 3.3.3
149
+ rubygems_version: 3.5.9
217
150
  signing_key:
218
151
  specification_version: 4
219
152
  summary: A Test Kitchen driver for VMware vRealize Automation (vRA)
220
- test_files:
221
- - spec/spec_helper.rb
222
- - spec/vra_spec.rb
153
+ test_files: []
@@ -1,8 +0,0 @@
1
- ---
2
- version: 2
3
- updates:
4
- - package-ecosystem: bundler
5
- directory: "/"
6
- schedule:
7
- interval: daily
8
- open-pull-requests-limit: 10
@@ -1,16 +0,0 @@
1
- ---
2
- 'on':
3
- push:
4
- branches:
5
- - main
6
-
7
- name: release-please
8
- jobs:
9
- release-please:
10
- runs-on: ubuntu-latest
11
- steps:
12
- - uses: google-github-actions/release-please-action@v3
13
- with:
14
- release-type: ruby
15
- package-name: kitchen-vra
16
- version-file: lib/kitchen/driver/vra_version.rb
data/.mdlrc DELETED
@@ -1 +0,0 @@
1
- rules "~MD036", "~MD013", "~MD024", "~MD029"