kitchen-pulumi 0.1.0.pre.beta → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +71 -2
- data/lib/kitchen/driver/pulumi.rb +193 -34
- data/lib/kitchen/provisioner/pulumi.rb +13 -3
- data/lib/kitchen/pulumi.rb +25 -0
- data/lib/kitchen/pulumi/config_attribute/backend.rb +1 -1
- data/lib/kitchen/pulumi/config_attribute/preserve_config.rb +35 -0
- data/lib/kitchen/pulumi/config_attribute/{stack.rb → secrets_provider.rb} +4 -4
- data/lib/kitchen/pulumi/config_attribute/test_stack_name.rb +34 -0
- data/lib/kitchen/pulumi/config_schemas/system.rb +2 -2
- data/lib/kitchen/pulumi/deep_merge.rb +8 -0
- data/lib/kitchen/pulumi/inspec_options_mapper.rb +1 -1
- data/lib/kitchen/pulumi/shell_out.rb +2 -2
- data/lib/kitchen/pulumi/system_attrs_resolver.rb +5 -9
- data/lib/kitchen/pulumi/version.rb +1 -1
- data/lib/kitchen/verifier/pulumi.rb +20 -4
- metadata +105 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6c0ce9de8379c66a261cbc65cf916a72cc46f44b1dd1fa75351807a9a38d828
|
4
|
+
data.tar.gz: 7e346277daebaa03ca622ca61a694004d412d6a0b6f2fc1badea8d8f752b33f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88631c7633e26c60539e22deefb778bf44e5f438d2af53101ea5645a02d3633997358ef04747f85f3f12a405ad797e76a96b469eceb262850bd0b4e275eec0d5
|
7
|
+
data.tar.gz: b1ec83259b24dad3c038c77f471655ee34ead9b3478cbf5db9942f5c8db4c264d801fae99e14bc889e9f13a4a0b1d9eaeaebb820a1de779d4b13d1b7f8719fd9
|
data/README.md
CHANGED
@@ -1,4 +1,73 @@
|
|
1
|
+
# Kitchen-Pulumi
|
2
|
+
|
3
|
+
[![Gem](https://img.shields.io/gem/v/kitchen-pulumi.svg)](https://rubygems.org/gems/kitchen-pulumi/)
|
4
|
+
[![Gem](https://img.shields.io/gem/dt/kitchen-pulumi.svg)](https://rubygems.org/gems/kitchen-pulumi/)
|
5
|
+
[![Gem](https://img.shields.io/gem/dtv/kitchen-pulumi.svg)](https://rubygems.org/gems/kitchen-pulumi/)
|
1
6
|
[![CircleCI](https://circleci.com/gh/jacoblearned/kitchen-pulumi/tree/master.svg?style=shield)](https://circleci.com/gh/jacoblearned/kitchen-pulumi/tree/master)
|
7
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/35afd25bac772504e2a0/test_coverage)](https://codeclimate.com/github/jacoblearned/kitchen-pulumi/test_coverage)
|
8
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/35afd25bac772504e2a0/maintainability)](https://codeclimate.com/github/jacoblearned/kitchen-pulumi/maintainability)
|
9
|
+
|
10
|
+
Kitchen-Pulumi is a collection of [Test-Kitchen](https://kitchen.ci/) plugins for developing test-driven [Pulumi](https://www.pulumi.com/)-based cloud infrastructure projects.
|
11
|
+
With Kitchen-Pulumi you can provision ephemeral test stacks, verify they are in a desired state using [InSpec](https://www.inspec.io/), and tear them down to gain
|
12
|
+
confidence in your infrastructure code before it hits production.
|
13
|
+
|
14
|
+
## Features
|
15
|
+
|
16
|
+
Kitchen-Pulumi provides a Kitchen [driver](https://kitchen.ci/docs/drivers/), [provisioner](https://kitchen.ci/docs/provisioners/),
|
17
|
+
and [verifier](https://kitchen.ci/docs/verifiers/) which collectively support the following features:
|
18
|
+
|
19
|
+
* **Language-agnostic**: Create and test Pulumi stacks in any of their [supported languages](https://www.pulumi.com/docs/reference/languages/).
|
20
|
+
* **Backend-agnostic**: Use the Pulumi SaaS backend, a local backend, or your organization's internal backend.
|
21
|
+
* **Configurable**: Easily define/override stack config values in your `.kitchen.yml` file for flexible testing across environments or scenarios.
|
22
|
+
* **Test changes over time**: Simulate changes in stack config values over time to test how your infrastructure reacts to ever-shifting user-provided values.
|
23
|
+
* **Custom state verification**: Code any validation logic you desire, provided it can be ran within an [InSpec profile](https://www.inspec.io/docs/reference/profiles/).
|
24
|
+
|
25
|
+
If there's a feature you would like to see in Kitchen-Pulumi, please create an issue with the suggested feature and its intended use case.
|
26
|
+
|
27
|
+
## Installation
|
28
|
+
|
29
|
+
Kitchen-Pulumi is compatible with Ruby 2.6 and above. Add this line to your application's Gemfile:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
# Gemfile
|
33
|
+
|
34
|
+
gem 'kitchen-pulumi', require: false
|
35
|
+
```
|
36
|
+
|
37
|
+
And then execute:
|
38
|
+
|
39
|
+
```
|
40
|
+
$ bundle
|
41
|
+
```
|
42
|
+
|
43
|
+
Or install it yourself as:
|
44
|
+
|
45
|
+
```
|
46
|
+
$ gem install kitchen-pulumi
|
47
|
+
```
|
48
|
+
|
49
|
+
## Quick Start / Tutorial
|
50
|
+
|
51
|
+
Check out the [serverless-rest-api-lambda example](examples/aws/serverless-rest-api-lambda) and follow the instructions in its `README`.
|
52
|
+
|
53
|
+
## Usage
|
54
|
+
|
55
|
+
TODO: Write usage instructions here
|
56
|
+
|
57
|
+
## Development
|
58
|
+
|
59
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
60
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
61
|
+
|
62
|
+
## Contributing
|
63
|
+
|
64
|
+
Bug reports and pull requests are always welcome on GitHub at https://github.com/jacoblearned/kitchen-pulumi. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
65
|
+
|
66
|
+
## License
|
67
|
+
|
68
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
69
|
+
|
70
|
+
## Code of Conduct
|
71
|
+
|
72
|
+
Everyone interacting in the Kitchen-Pulumi’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/jacoblearned/kitchen-pulumi/blob/master/CODE_OF_CONDUCT.md).
|
2
73
|
|
3
|
-
# kitchen-pulumi
|
4
|
-
Test-Kitchen plugins for Pulumi projects
|
@@ -1,9 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'yaml'
|
3
4
|
require 'kitchen'
|
4
5
|
require 'kitchen/driver/base'
|
5
6
|
require 'kitchen/pulumi/error'
|
6
7
|
require 'kitchen/pulumi/shell_out'
|
8
|
+
require 'kitchen/pulumi/deep_merge'
|
7
9
|
require 'kitchen/pulumi/configurable'
|
8
10
|
require 'kitchen/pulumi/command/input'
|
9
11
|
require 'kitchen/pulumi/command/output'
|
@@ -13,17 +15,25 @@ require 'kitchen/pulumi/config_attribute/directory'
|
|
13
15
|
require 'kitchen/pulumi/config_attribute/plugins'
|
14
16
|
require 'kitchen/pulumi/config_attribute/backend'
|
15
17
|
require 'kitchen/pulumi/config_attribute/secrets'
|
16
|
-
require 'kitchen/pulumi/config_attribute/
|
18
|
+
require 'kitchen/pulumi/config_attribute/test_stack_name'
|
17
19
|
require 'kitchen/pulumi/config_attribute/stack_evolution'
|
18
20
|
require 'kitchen/pulumi/config_attribute/refresh_config'
|
21
|
+
require 'kitchen/pulumi/config_attribute/secrets_provider'
|
22
|
+
require 'kitchen/pulumi/config_attribute/preserve_config'
|
19
23
|
|
20
24
|
module Kitchen
|
25
|
+
# This namespace is defined by Kitchen.
|
26
|
+
#
|
27
|
+
# @see https://www.rubydoc.info/gems/test-kitchen/Kitchen/Driver
|
21
28
|
module Driver
|
22
29
|
# Driver class implementing the CLI equivalency between Kitchen and Pulumi
|
30
|
+
#
|
31
|
+
# @author Jacob Learned
|
23
32
|
class Pulumi < ::Kitchen::Driver::Base
|
24
33
|
kitchen_driver_api_version 2
|
25
34
|
|
26
35
|
include ::Kitchen::Pulumi::Configurable
|
36
|
+
include ::Kitchen::Logging
|
27
37
|
|
28
38
|
# Include config attributes consumable via .kitchen.yml
|
29
39
|
include ::Kitchen::Pulumi::ConfigAttribute::Config
|
@@ -32,47 +42,107 @@ module Kitchen
|
|
32
42
|
include ::Kitchen::Pulumi::ConfigAttribute::Plugins
|
33
43
|
include ::Kitchen::Pulumi::ConfigAttribute::Backend
|
34
44
|
include ::Kitchen::Pulumi::ConfigAttribute::Secrets
|
35
|
-
include ::Kitchen::Pulumi::ConfigAttribute::
|
45
|
+
include ::Kitchen::Pulumi::ConfigAttribute::TestStackName
|
36
46
|
include ::Kitchen::Pulumi::ConfigAttribute::StackEvolution
|
37
47
|
include ::Kitchen::Pulumi::ConfigAttribute::RefreshConfig
|
48
|
+
include ::Kitchen::Pulumi::ConfigAttribute::SecretsProvider
|
49
|
+
include ::Kitchen::Pulumi::ConfigAttribute::PreserveConfig
|
38
50
|
|
51
|
+
# Initializes a stack via `pulumi stack init`
|
52
|
+
#
|
53
|
+
# @param _state [::Hash] the current kitchen state
|
54
|
+
# @return [void]
|
39
55
|
def create(_state)
|
40
56
|
dir = "-C #{config_directory}"
|
41
|
-
stack = config_stack.empty? ? instance.suite.name : config_stack
|
42
|
-
conf_file = config_file
|
43
|
-
|
44
57
|
login
|
45
58
|
initialize_stack(stack, dir)
|
46
|
-
configure(config_config, stack, dir, conf_file)
|
47
|
-
configure(config_secrets, stack, dir, conf_file, is_secret: true)
|
48
59
|
end
|
49
60
|
|
50
|
-
|
61
|
+
# Sets stack config values via `pulumi config` and updates the stack via `pulumi up`
|
62
|
+
#
|
63
|
+
# @param _state [::Hash] the current kitchen state
|
64
|
+
# @param config_only [Boolean] specify true to update the stack config without
|
65
|
+
# applying changes to the stack via `pulumi up`
|
66
|
+
#
|
67
|
+
# for block {|temp_conf_file| ...}
|
68
|
+
# @yield [temp_conf_file] provides the path to the temporary config file used
|
69
|
+
#
|
70
|
+
# @return [void]
|
71
|
+
def update(_state, config_only: false)
|
51
72
|
dir = "-C #{config_directory}"
|
52
|
-
stack = config_stack.empty? ? instance.suite.name : config_stack
|
53
|
-
conf_file = config_file
|
54
73
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
74
|
+
::Kitchen::Pulumi.with_temp_conf(config_file) do |temp_conf_file|
|
75
|
+
login
|
76
|
+
refresh_config(stack, temp_conf_file, dir) if config_refresh_config
|
77
|
+
configure(config_config, stack, temp_conf_file, dir)
|
78
|
+
configure(config_secrets, stack, temp_conf_file, dir, is_secret: true)
|
79
|
+
update_stack(stack, temp_conf_file, dir) unless config_only
|
80
|
+
|
81
|
+
unless config_stack_evolution.empty?
|
82
|
+
evolve_stack(stack, temp_conf_file, dir, config_only: config_only)
|
83
|
+
end
|
84
|
+
|
85
|
+
yield temp_conf_file if block_given?
|
86
|
+
end
|
59
87
|
end
|
60
88
|
|
89
|
+
# Destroys a stack via `pulumi destroy`
|
90
|
+
#
|
91
|
+
# @param _state [::Hash] the current kitchen state
|
92
|
+
# @return [void]
|
61
93
|
def destroy(_state)
|
62
94
|
dir = "-C #{config_directory}"
|
63
|
-
stack = config_stack.empty? ? instance.suite.name : config_stack
|
64
95
|
|
65
96
|
cmds = [
|
66
97
|
"destroy -y -r --show-config -s #{stack} #{dir}",
|
67
|
-
"stack rm
|
98
|
+
"stack rm #{preserve_config} -y -s #{stack} #{dir}",
|
68
99
|
]
|
69
100
|
|
70
101
|
login
|
71
102
|
::Kitchen::Pulumi::ShellOut.run(cmd: cmds, logger: logger)
|
72
103
|
rescue ::Kitchen::Pulumi::Error => e
|
73
|
-
|
104
|
+
if e.message.match?(/no stack named '#{stack}' found/) || (
|
105
|
+
e.message.match?(/failed to load checkpoint/) && config_backend == 'local'
|
106
|
+
)
|
107
|
+
puts "Stack '#{stack}' does not exist, continuing..."
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Returns `--preserve-config` if the `preserve_config` instance attribute is set
|
112
|
+
#
|
113
|
+
# @return [String] either `''` or `--preserve-config`
|
114
|
+
def preserve_config
|
115
|
+
return '' unless config_preserve_config
|
116
|
+
|
117
|
+
'--preserve-config'
|
118
|
+
end
|
119
|
+
|
120
|
+
# Returns the name of the current stack to use. If the `test_stack_name` driver
|
121
|
+
# attribute is set, then it uses that one, otherwise it will be
|
122
|
+
# `<suite name>-<platform name>`
|
123
|
+
#
|
124
|
+
# @return [String] either the empty string or '--preserve-config'
|
125
|
+
def stack
|
126
|
+
return config_test_stack_name unless config_test_stack_name.empty?
|
127
|
+
|
128
|
+
"#{instance.suite.name}-#{instance.platform.name}"
|
129
|
+
end
|
130
|
+
|
131
|
+
# Returns the name of the secrets provider, if set, optionally as a Pulumi CLI flag
|
132
|
+
#
|
133
|
+
# @param flag [Boolean] specify true to prepend `--secrets-provider=`` to the name
|
134
|
+
# @return [String] value to use for the secrets provider
|
135
|
+
def secrets_provider(flag: false)
|
136
|
+
return '' if config_secrets_provider.empty?
|
137
|
+
|
138
|
+
return "--secrets-provider=\"#{config_secrets_provider}\"" if flag
|
139
|
+
|
140
|
+
config_secrets_provider
|
74
141
|
end
|
75
142
|
|
143
|
+
# Logs in to the Pulumi backend set for the instance via `pulumi login`
|
144
|
+
#
|
145
|
+
# @return [void]
|
76
146
|
def login
|
77
147
|
backend = config_backend == 'local' ? '--local' : config_backend
|
78
148
|
::Kitchen::Pulumi::ShellOut.run(
|
@@ -81,18 +151,31 @@ module Kitchen
|
|
81
151
|
)
|
82
152
|
end
|
83
153
|
|
154
|
+
# Initializes a stack in the current directory unless another is provided
|
155
|
+
#
|
156
|
+
# @param stack [String] name of the stack to initialize
|
157
|
+
# @param dir [String] path to the directory to run Pulumi commands in
|
84
158
|
def initialize_stack(stack, dir = '')
|
85
159
|
::Kitchen::Pulumi::ShellOut.run(
|
86
|
-
cmd: "stack init #{stack} #{dir}",
|
160
|
+
cmd: "stack init #{stack} #{dir} #{secrets_provider(flag: true)}",
|
87
161
|
logger: logger,
|
88
162
|
)
|
89
163
|
rescue ::Kitchen::Pulumi::Error => e
|
90
164
|
puts 'Continuing...' if e.message.match?(/stack '#{stack}' already exists/)
|
91
165
|
end
|
92
166
|
|
167
|
+
# Configures a stack in the current directory unless another is provided
|
168
|
+
#
|
169
|
+
# @param stack_confs [::Hash] hash specifying the stack config for the instance
|
170
|
+
# @param stack [String] name of the stack to configure
|
171
|
+
# @param conf_file [String] path to a stack config file to use for configuration
|
172
|
+
# @param dir [String] path to the directory to run Pulumi commands in
|
173
|
+
# @param is_secret [Boolean] specify true to set the given stack config as secrets
|
174
|
+
# @return [void]
|
93
175
|
def configure(stack_confs, stack, conf_file, dir = '', is_secret: false)
|
94
176
|
secret = is_secret ? '--secret' : ''
|
95
|
-
|
177
|
+
config_flag = config_file(conf_file, flag: true)
|
178
|
+
base_cmd = "config set #{secret} -s #{stack} #{dir} #{config_flag}"
|
96
179
|
|
97
180
|
stack_confs.each do |namespace, stack_settings|
|
98
181
|
stack_settings.each do |key, val|
|
@@ -104,59 +187,127 @@ module Kitchen
|
|
104
187
|
end
|
105
188
|
end
|
106
189
|
|
190
|
+
# Refreshes a stack's config on the specified config file
|
191
|
+
#
|
192
|
+
# @param stack [String] name of the stack being refreshed
|
193
|
+
# @param conf_file [String] path to a stack config file to use for configuration
|
194
|
+
# @param dir [String] path to the directory to run Pulumi commands in
|
195
|
+
# @return [void]
|
107
196
|
def refresh_config(stack, conf_file, dir = '')
|
108
197
|
::Kitchen::Pulumi::ShellOut.run(
|
109
|
-
cmd: "config refresh -s #{stack} #{dir} #{conf_file}",
|
198
|
+
cmd: "config refresh -s #{stack} #{dir} #{config_file(conf_file, flag: true)}",
|
110
199
|
logger: logger,
|
111
200
|
)
|
112
201
|
rescue ::Kitchen::Pulumi::Error => e
|
113
202
|
puts 'Continuing...' if e.message.match?(/no previous deployment/)
|
114
203
|
end
|
115
204
|
|
116
|
-
|
205
|
+
# Get the value of the config file to use, if set on instance or provided as param,
|
206
|
+
# optionally as a command line flag `--config-file`
|
207
|
+
#
|
208
|
+
# @param conf_file [String] path to a stack config file to use for configuration
|
209
|
+
# @param flag [Boolean] specify true to prepend '--config-file ' to the config file
|
210
|
+
# @return [String] the path to the config file or its corresponding CLI flag
|
211
|
+
def config_file(conf_file = '', flag: false)
|
117
212
|
file = conf_file.empty? ? config_config_file : conf_file
|
118
213
|
return '' if File.directory?(file) || file.empty?
|
119
214
|
|
120
|
-
"--config-file #{file}"
|
215
|
+
return "--config-file #{file}" if flag
|
216
|
+
|
217
|
+
file
|
121
218
|
end
|
122
219
|
|
220
|
+
# Updates a stack via `pulumi up` according to instance attributes
|
221
|
+
#
|
222
|
+
# @param (see #refresh_config)
|
223
|
+
# @return [void]
|
123
224
|
def update_stack(stack, conf_file, dir = '')
|
225
|
+
base_cmd = "up -y -r --show-config -s #{stack} #{dir}"
|
124
226
|
::Kitchen::Pulumi::ShellOut.run(
|
125
|
-
cmd: "
|
227
|
+
cmd: "#{base_cmd} #{config_file(conf_file, flag: true)}",
|
126
228
|
logger: logger,
|
127
229
|
)
|
128
230
|
end
|
129
231
|
|
130
|
-
|
232
|
+
# Evolves a stack via successive calls to `pulumi config set` and `pulumi up`
|
233
|
+
# according to the `stack_evolution` instance attribute, if set. This permits
|
234
|
+
# testing stack config changes over time.
|
235
|
+
#
|
236
|
+
# @param (see #refresh_config)
|
237
|
+
# @param config_only [Boolean] specify true to prevent running `pulumi up`
|
238
|
+
# @return [void]
|
239
|
+
def evolve_stack(stack, conf_file, dir = '', config_only: false)
|
131
240
|
config_stack_evolution.each do |evolution|
|
132
|
-
|
241
|
+
new_conf_file = config_file(evolution.fetch(:config_file, ''))
|
133
242
|
new_stack_confs = evolution.fetch(:config, {})
|
134
243
|
new_stack_secrets = evolution.fetch(:secrets, {})
|
135
244
|
|
245
|
+
rewrite_config_file(new_conf_file, conf_file)
|
246
|
+
|
136
247
|
configure(new_stack_confs, stack, conf_file, dir)
|
137
248
|
configure(new_stack_secrets, stack, conf_file, dir, is_secret: true)
|
138
|
-
update_stack(stack, conf_file, dir)
|
249
|
+
update_stack(stack, conf_file, dir) unless config_only
|
139
250
|
end
|
140
251
|
end
|
141
252
|
|
253
|
+
# Rewrites a temporary config file by merging the contents of the new config file
|
254
|
+
# into the old config file. This is used during stack evolution to ensure that
|
255
|
+
# stack config changes for each evolution step are implemented correctly if the
|
256
|
+
# user has provided a new config file to use for a step.
|
257
|
+
#
|
258
|
+
# @param new_conf_file [String] the path to the new config file to use
|
259
|
+
# @param old_conf_file [String] the path to the config file to overwrite
|
260
|
+
# @return [void]
|
261
|
+
def rewrite_config_file(new_conf_file, old_conf_file)
|
262
|
+
return if new_conf_file.empty?
|
263
|
+
|
264
|
+
old_conf = YAML.load_file(old_conf_file)
|
265
|
+
new_conf_file = File.join(config_directory, new_conf_file)
|
266
|
+
return unless File.exist?(new_conf_file)
|
267
|
+
|
268
|
+
new_conf = old_conf.deep_merge(YAML.load_file(new_conf_file))
|
269
|
+
File.write(old_conf_file, new_conf.to_yaml)
|
270
|
+
end
|
271
|
+
|
272
|
+
# Retrieves the fully resolved stack inputs based on the current configuration
|
273
|
+
# of the stack via `pulumi config`
|
274
|
+
#
|
275
|
+
# @param block [Block] block to run with stack inputs yielded to it
|
276
|
+
#
|
277
|
+
# for block {|stack_inputs| ... }
|
278
|
+
# @yield [stack_inputs] yields a hash of stack inputs
|
279
|
+
#
|
280
|
+
# @raise [Kitchen::ActionFailed] if an error occurs retrieving stack inputs
|
281
|
+
# @return [self]
|
142
282
|
def stack_inputs(&block)
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
283
|
+
update({}, config_only: true) do |temp_conf_file|
|
284
|
+
::Kitchen::Pulumi::Command::Input.run(
|
285
|
+
directory: config_directory,
|
286
|
+
stack: stack,
|
287
|
+
conf_file: config_file(temp_conf_file, flag: true),
|
288
|
+
logger: logger,
|
289
|
+
&block
|
290
|
+
)
|
291
|
+
end
|
150
292
|
|
151
293
|
self
|
152
294
|
rescue ::Kitchen::Pulumi::Error => e
|
153
295
|
raise ::Kitchen::ActionFailed, e.message
|
154
296
|
end
|
155
297
|
|
298
|
+
# Retrieves stack outputs via `pulumi stack output`
|
299
|
+
#
|
300
|
+
# @param block [Block] block to run with stack outputs yielded to it
|
301
|
+
#
|
302
|
+
# for block {|stack_outputs| ... }
|
303
|
+
# @yield [stack_outputs] yields a hash of stack outputs
|
304
|
+
#
|
305
|
+
# @raise [Kitchen::ActionFailed] if an error occurs retrieving stack outputs
|
306
|
+
# @return [self]
|
156
307
|
def stack_outputs(&block)
|
157
308
|
::Kitchen::Pulumi::Command::Output.run(
|
158
309
|
directory: config_directory,
|
159
|
-
stack:
|
310
|
+
stack: stack,
|
160
311
|
logger: logger,
|
161
312
|
&block
|
162
313
|
)
|
@@ -165,6 +316,14 @@ module Kitchen
|
|
165
316
|
rescue ::Kitchen::Pulumi::Error => e
|
166
317
|
raise ::Kitchen::ActionFailed, e.message
|
167
318
|
end
|
319
|
+
|
320
|
+
private
|
321
|
+
|
322
|
+
# @return [Logger] the common logger
|
323
|
+
# @api private
|
324
|
+
def logger
|
325
|
+
Kitchen.logger
|
326
|
+
end
|
168
327
|
end
|
169
328
|
end
|
170
329
|
end
|
@@ -5,15 +5,25 @@ require 'kitchen/provisioner/base'
|
|
5
5
|
require 'kitchen/pulumi/configurable'
|
6
6
|
|
7
7
|
module Kitchen
|
8
|
+
# This namespace is defined by Kitchen.
|
9
|
+
#
|
10
|
+
# @see https://www.rubydoc.info/gems/test-kitchen/Kitchen/Provisioner
|
8
11
|
module Provisioner
|
9
|
-
#
|
10
|
-
# run kitchen converge
|
12
|
+
# Provisioner class whose call method is invoked when users
|
13
|
+
# run `kitchen converge`
|
14
|
+
#
|
15
|
+
# @author Jacob Learned
|
11
16
|
class Pulumi < ::Kitchen::Provisioner::Base
|
12
17
|
kitchen_provisioner_api_version 2
|
13
18
|
|
14
19
|
include ::Kitchen::Pulumi::Configurable
|
15
20
|
|
16
|
-
# Runs stack updates via the instance driver
|
21
|
+
# Runs stack updates via the instance driver which shells out
|
22
|
+
# to `pulumi up`
|
23
|
+
#
|
24
|
+
# @param state [::Hash] the current kitchen state
|
25
|
+
# @raise [Kitchen::ActionFailed] if an error occurs during update
|
26
|
+
# @return void
|
17
27
|
def call(state)
|
18
28
|
instance.driver.update(state)
|
19
29
|
rescue ::Kitchen::Pulumi::Error => e
|
data/lib/kitchen/pulumi.rb
CHANGED
@@ -1,8 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'tempfile'
|
4
|
+
|
3
5
|
# Global kitchen module
|
4
6
|
module Kitchen
|
5
7
|
# Namespace for Kitchen-Pulumi logic
|
8
|
+
# @author Jacob Learned
|
6
9
|
module Pulumi
|
10
|
+
# Copies the contents of the given config file to a temporary file and yields the
|
11
|
+
# path of the temporary file to the block given
|
12
|
+
#
|
13
|
+
# @param config_file [String] the path to the config file to copy into the temp file
|
14
|
+
#
|
15
|
+
# for block {|temp_conf| ... }
|
16
|
+
# @yield [temp_conf] gives the path to the temporary config file
|
17
|
+
def self.with_temp_conf(config_file = '')
|
18
|
+
temp_conf = Tempfile.new(['kitchen-pulumi', '.yaml'])
|
19
|
+
|
20
|
+
if config_file.empty?
|
21
|
+
yield('') if block_given?
|
22
|
+
else
|
23
|
+
begin
|
24
|
+
IO.copy_stream(config_file, temp_conf.path)
|
25
|
+
yield(temp_conf.path) if block_given?
|
26
|
+
ensure
|
27
|
+
temp_conf.close
|
28
|
+
temp_conf.unlink
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
7
32
|
end
|
8
33
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kitchen/pulumi'
|
4
|
+
require 'kitchen/pulumi/config_schemas/boolean'
|
5
|
+
require 'kitchen/pulumi/config_attribute_cacher'
|
6
|
+
require 'kitchen/pulumi/config_attribute_definer'
|
7
|
+
|
8
|
+
module Kitchen
|
9
|
+
module Pulumi
|
10
|
+
module ConfigAttribute
|
11
|
+
# Attribute used to determine if the stack config should be
|
12
|
+
# preserved after stack is removed with `pulumi stack rm`
|
13
|
+
# during destroy.
|
14
|
+
module PreserveConfig
|
15
|
+
def self.included(plugin_class)
|
16
|
+
definer = ConfigAttributeDefiner.new(
|
17
|
+
attribute: self,
|
18
|
+
schema: ConfigSchemas::Boolean,
|
19
|
+
)
|
20
|
+
definer.define(plugin_class: plugin_class)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.to_sym
|
24
|
+
:preserve_config
|
25
|
+
end
|
26
|
+
|
27
|
+
extend ConfigAttributeCacher
|
28
|
+
|
29
|
+
def config_preserve_config_default_value
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -8,8 +8,8 @@ require 'kitchen/pulumi/config_attribute_definer'
|
|
8
8
|
module Kitchen
|
9
9
|
module Pulumi
|
10
10
|
module ConfigAttribute
|
11
|
-
# Attribute used to specify the
|
12
|
-
module
|
11
|
+
# Attribute used to specify the secrets provider a stack should use
|
12
|
+
module SecretsProvider
|
13
13
|
def self.included(plugin_class)
|
14
14
|
definer = ConfigAttributeDefiner.new(
|
15
15
|
attribute: self,
|
@@ -19,12 +19,12 @@ module Kitchen
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.to_sym
|
22
|
-
:
|
22
|
+
:secrets_provider
|
23
23
|
end
|
24
24
|
|
25
25
|
extend ConfigAttributeCacher
|
26
26
|
|
27
|
-
def
|
27
|
+
def config_secrets_provider_default_value
|
28
28
|
''
|
29
29
|
end
|
30
30
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kitchen/pulumi'
|
4
|
+
require 'kitchen/pulumi/config_schemas/string'
|
5
|
+
require 'kitchen/pulumi/config_attribute_cacher'
|
6
|
+
require 'kitchen/pulumi/config_attribute_definer'
|
7
|
+
|
8
|
+
module Kitchen
|
9
|
+
module Pulumi
|
10
|
+
module ConfigAttribute
|
11
|
+
# Attribute used to override the stack name to use for the stack
|
12
|
+
# created for an instance.
|
13
|
+
module TestStackName
|
14
|
+
def self.included(plugin_class)
|
15
|
+
definer = ConfigAttributeDefiner.new(
|
16
|
+
attribute: self,
|
17
|
+
schema: ConfigSchemas::String,
|
18
|
+
)
|
19
|
+
definer.define(plugin_class: plugin_class)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.to_sym
|
23
|
+
:test_stack_name
|
24
|
+
end
|
25
|
+
|
26
|
+
extend ConfigAttributeCacher
|
27
|
+
|
28
|
+
def config_test_stack_name_default_value
|
29
|
+
''
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'dry/validation'
|
4
4
|
require 'kitchen/pulumi/config_schemas'
|
5
5
|
|
6
|
-
# rubocop:disable
|
6
|
+
# rubocop:disable Layout/LineLength
|
7
7
|
# rubocop:disable Metrics/BlockLength
|
8
8
|
module Kitchen
|
9
9
|
module Pulumi
|
@@ -574,4 +574,4 @@ module Kitchen
|
|
574
574
|
end
|
575
575
|
end
|
576
576
|
# rubocop:enable Metrics/BlockLength
|
577
|
-
# rubocop:enable
|
577
|
+
# rubocop:enable Layout/LineLength
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ::Hash
|
4
|
+
def deep_merge(second)
|
5
|
+
merger = proc { |_key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : Array === v1 && Array === v2 ? v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
|
6
|
+
merge(second.to_h, &merger)
|
7
|
+
end
|
8
|
+
end
|
@@ -62,7 +62,7 @@ module Kitchen
|
|
62
62
|
attr_accessor :system_attributes_to_options
|
63
63
|
|
64
64
|
def initialize
|
65
|
-
self.system_attributes_to_options = ::Kitchen::Pulumi::InSpecOptionsMapper::SYSTEM_ATTRIBUTES_TO_OPTIONS.dup # rubocop:disable
|
65
|
+
self.system_attributes_to_options = ::Kitchen::Pulumi::InSpecOptionsMapper::SYSTEM_ATTRIBUTES_TO_OPTIONS.dup # rubocop:disable Layout/LineLength
|
66
66
|
end
|
67
67
|
end
|
68
68
|
end
|
@@ -9,7 +9,7 @@ module Kitchen
|
|
9
9
|
# Module orchestrating calls to the Pulumi CLI
|
10
10
|
module ShellOut
|
11
11
|
# Shells out to the Pulumi CLI
|
12
|
-
def self.run(cmd:, duration: 7200,
|
12
|
+
def self.run(cmd:, logger:, duration: 7200, &block)
|
13
13
|
cmds = Array(cmd)
|
14
14
|
block ||= ->(stdout) { stdout }
|
15
15
|
shell_out(commands: cmds, duration: duration, logger: logger, &block)
|
@@ -20,7 +20,7 @@ module Kitchen
|
|
20
20
|
raise(::Kitchen::Pulumi::Error, "Error: #{e.message}")
|
21
21
|
end
|
22
22
|
|
23
|
-
def self.shell_out(commands:, duration: 7200
|
23
|
+
def self.shell_out(commands:, logger:, duration: 7200)
|
24
24
|
commands.each do |command|
|
25
25
|
shell_out = ::Mixlib::ShellOut.new(
|
26
26
|
"pulumi #{command}",
|
@@ -38,19 +38,15 @@ module Kitchen
|
|
38
38
|
# @param inputs [#to_hash] the config inputs provided to a stack
|
39
39
|
# @param outputs [#to_hash] the outputs of the Pulumi stack under test.
|
40
40
|
def initialize(inputs:, outputs:)
|
41
|
-
@inputs = inputs.
|
42
|
-
|
43
|
-
end
|
44
|
-
@inputs.merge!(@inputs.
|
45
|
-
["input_#{key}", value]
|
46
|
-
end.to_h)
|
41
|
+
@inputs = inputs.transform_values do |value|
|
42
|
+
value.fetch('value', nil)
|
43
|
+
end
|
44
|
+
@inputs.merge!(@inputs.transform_keys { |key| "input_#{key}" })
|
47
45
|
|
48
46
|
@outputs = Hash[outputs].map do |key, value|
|
49
47
|
[key, value]
|
50
48
|
end.to_h
|
51
|
-
@outputs.merge!(@outputs.
|
52
|
-
["output_#{key}", value]
|
53
|
-
end.to_h)
|
49
|
+
@outputs.merge!(@outputs.transform_keys { |key| "output_#{key}" })
|
54
50
|
rescue ::KeyError => e
|
55
51
|
raise ::Kitchen::Pulumi::Error, "System attrs resolution failed\n#{e}"
|
56
52
|
end
|
@@ -13,7 +13,7 @@ module Kitchen
|
|
13
13
|
#
|
14
14
|
# @see https://www.rubydoc.info/gems/test-kitchen/Kitchen/Verifier
|
15
15
|
module Verifier
|
16
|
-
# The verifier utilizes the {https://www.inspec.io/ InSpec infrastructure
|
16
|
+
# The verifier utilizes the {https://www.inspec.io/ InSpec} infrastructure
|
17
17
|
# testing framework to verify the behaviour and
|
18
18
|
# state of resources in the Pulumi state.
|
19
19
|
#
|
@@ -63,7 +63,7 @@ module Kitchen
|
|
63
63
|
# :reek:MissingSafeMethod {
|
64
64
|
# exclude: [ finalize_config!, load_needed_dependencies! ]
|
65
65
|
# }
|
66
|
-
class Pulumi
|
66
|
+
class Pulumi < ::Kitchen::Verifier::Base
|
67
67
|
include ::Kitchen::Configurable
|
68
68
|
include ::Kitchen::Logging
|
69
69
|
include ::Kitchen::Pulumi::ConfigAttribute::Color
|
@@ -75,7 +75,7 @@ module Kitchen
|
|
75
75
|
attr_reader :inputs, :outputs
|
76
76
|
|
77
77
|
def initialize(configuration = {})
|
78
|
-
|
78
|
+
super(configuration)
|
79
79
|
self.inspec_options_mapper = ::Kitchen::Pulumi::InSpecOptionsMapper.new
|
80
80
|
self.error_messages = []
|
81
81
|
self.inputs = {}
|
@@ -100,7 +100,7 @@ module Kitchen
|
|
100
100
|
raise ::Kitchen::ActionFailed, e.message
|
101
101
|
end
|
102
102
|
|
103
|
-
#
|
103
|
+
# Checks the system and configuration for common errors.
|
104
104
|
#
|
105
105
|
# @param _kitchen_state [::Hash] the mutable Kitchen instance state.
|
106
106
|
# @return [Boolean] false
|
@@ -114,6 +114,10 @@ module Kitchen
|
|
114
114
|
attr_accessor :inspec_options_mapper, :error_messages
|
115
115
|
attr_writer :inputs, :outputs
|
116
116
|
|
117
|
+
# Raises an error immediately if the `fail_fast` config attribute is set on the
|
118
|
+
# or collects all errors until execution has ended verifier
|
119
|
+
#
|
120
|
+
# @return [void]
|
117
121
|
def handle_error(message:)
|
118
122
|
raise ::Kitchen::Pulumi::Error, message if config_fail_fast
|
119
123
|
|
@@ -121,6 +125,10 @@ module Kitchen
|
|
121
125
|
error_messages.push message
|
122
126
|
end
|
123
127
|
|
128
|
+
# Populates the `stack_inputs` and `stack_outputs` with the fully resolved stack
|
129
|
+
# inputs and outputs produced by the appropriate Pulumi commands
|
130
|
+
#
|
131
|
+
# @return [void]
|
124
132
|
def load_variables
|
125
133
|
instance.driver.stack_outputs do |outputs:|
|
126
134
|
self.outputs.replace(outputs)
|
@@ -151,6 +159,10 @@ module Kitchen
|
|
151
159
|
)
|
152
160
|
end
|
153
161
|
|
162
|
+
# Runs verification logic of the given system
|
163
|
+
#
|
164
|
+
# @param system [::Hash] the system to verify
|
165
|
+
# @return [void]
|
154
166
|
def verify(system:)
|
155
167
|
::Kitchen::Pulumi::System.new(
|
156
168
|
mapping: {
|
@@ -167,6 +179,10 @@ module Kitchen
|
|
167
179
|
handle_error message: e.message
|
168
180
|
end
|
169
181
|
|
182
|
+
# Runs verification logic for each system defined on the verifier's `systems` config
|
183
|
+
# attribute
|
184
|
+
#
|
185
|
+
# @return [void]
|
170
186
|
def verify_systems
|
171
187
|
config_systems.each do |system|
|
172
188
|
verify system: system
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kitchen-pulumi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jacob Learned
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: guard
|
@@ -44,42 +44,42 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0.
|
47
|
+
version: '0.13'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0.
|
54
|
+
version: '0.13'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: pry-byebug
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '3.
|
61
|
+
version: '3.8'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '3.
|
68
|
+
version: '3.8'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '13.0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '13.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,14 +128,70 @@ dependencies:
|
|
128
128
|
requirements:
|
129
129
|
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
131
|
+
version: '1.9'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1.9'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rubocop-rake
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.5'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0.5'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rubocop-rspec
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '2.1'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '2.1'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: simplecov
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0.21'
|
132
174
|
type: :development
|
133
175
|
prerelease: false
|
134
176
|
version_requirements: !ruby/object:Gem::Requirement
|
135
177
|
requirements:
|
136
178
|
- - "~>"
|
137
179
|
- !ruby/object:Gem::Version
|
138
|
-
version: '0.
|
180
|
+
version: '0.21'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: yard
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - "~>"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0.9'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - "~>"
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0.9'
|
139
195
|
- !ruby/object:Gem::Dependency
|
140
196
|
name: logger
|
141
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -182,44 +238,62 @@ dependencies:
|
|
182
238
|
name: inspec
|
183
239
|
requirement: !ruby/object:Gem::Requirement
|
184
240
|
requirements:
|
185
|
-
- - "
|
241
|
+
- - ">="
|
186
242
|
- !ruby/object:Gem::Version
|
187
|
-
version: '3
|
243
|
+
version: '3'
|
244
|
+
- - "<"
|
245
|
+
- !ruby/object:Gem::Version
|
246
|
+
version: '5'
|
188
247
|
type: :runtime
|
189
248
|
prerelease: false
|
190
249
|
version_requirements: !ruby/object:Gem::Requirement
|
191
250
|
requirements:
|
192
|
-
- - "
|
251
|
+
- - ">="
|
193
252
|
- !ruby/object:Gem::Version
|
194
|
-
version: '3
|
253
|
+
version: '3'
|
254
|
+
- - "<"
|
255
|
+
- !ruby/object:Gem::Version
|
256
|
+
version: '5'
|
195
257
|
- !ruby/object:Gem::Dependency
|
196
258
|
name: json
|
197
259
|
requirement: !ruby/object:Gem::Requirement
|
198
260
|
requirements:
|
199
|
-
- - "
|
261
|
+
- - ">="
|
200
262
|
- !ruby/object:Gem::Version
|
201
|
-
version: 2.1
|
263
|
+
version: '2.1'
|
264
|
+
- - "<"
|
265
|
+
- !ruby/object:Gem::Version
|
266
|
+
version: '2.4'
|
202
267
|
type: :runtime
|
203
268
|
prerelease: false
|
204
269
|
version_requirements: !ruby/object:Gem::Requirement
|
205
270
|
requirements:
|
206
|
-
- - "
|
271
|
+
- - ">="
|
207
272
|
- !ruby/object:Gem::Version
|
208
|
-
version: 2.1
|
273
|
+
version: '2.1'
|
274
|
+
- - "<"
|
275
|
+
- !ruby/object:Gem::Version
|
276
|
+
version: '2.4'
|
209
277
|
- !ruby/object:Gem::Dependency
|
210
278
|
name: mixlib-shellout
|
211
279
|
requirement: !ruby/object:Gem::Requirement
|
212
280
|
requirements:
|
213
|
-
- - "
|
281
|
+
- - ">="
|
214
282
|
- !ruby/object:Gem::Version
|
215
283
|
version: '2.3'
|
284
|
+
- - "<"
|
285
|
+
- !ruby/object:Gem::Version
|
286
|
+
version: '4.0'
|
216
287
|
type: :runtime
|
217
288
|
prerelease: false
|
218
289
|
version_requirements: !ruby/object:Gem::Requirement
|
219
290
|
requirements:
|
220
|
-
- - "
|
291
|
+
- - ">="
|
221
292
|
- !ruby/object:Gem::Version
|
222
293
|
version: '2.3'
|
294
|
+
- - "<"
|
295
|
+
- !ruby/object:Gem::Version
|
296
|
+
version: '4.0'
|
223
297
|
- !ruby/object:Gem::Dependency
|
224
298
|
name: test-kitchen
|
225
299
|
requirement: !ruby/object:Gem::Requirement
|
@@ -243,7 +317,7 @@ dependencies:
|
|
243
317
|
description: 'Kitchen-Pulumi makes it easy to add integration tests to Pulumi-based
|
244
318
|
infrastructure projects.
|
245
319
|
|
246
|
-
|
320
|
+
'
|
247
321
|
email:
|
248
322
|
- jacobmlearned@gmail.com
|
249
323
|
executables: []
|
@@ -266,11 +340,13 @@ files:
|
|
266
340
|
- lib/kitchen/pulumi/config_attribute/directory.rb
|
267
341
|
- lib/kitchen/pulumi/config_attribute/fail_fast.rb
|
268
342
|
- lib/kitchen/pulumi/config_attribute/plugins.rb
|
343
|
+
- lib/kitchen/pulumi/config_attribute/preserve_config.rb
|
269
344
|
- lib/kitchen/pulumi/config_attribute/refresh_config.rb
|
270
345
|
- lib/kitchen/pulumi/config_attribute/secrets.rb
|
271
|
-
- lib/kitchen/pulumi/config_attribute/
|
346
|
+
- lib/kitchen/pulumi/config_attribute/secrets_provider.rb
|
272
347
|
- lib/kitchen/pulumi/config_attribute/stack_evolution.rb
|
273
348
|
- lib/kitchen/pulumi/config_attribute/systems.rb
|
349
|
+
- lib/kitchen/pulumi/config_attribute/test_stack_name.rb
|
274
350
|
- lib/kitchen/pulumi/config_attribute_cacher.rb
|
275
351
|
- lib/kitchen/pulumi/config_attribute_definer.rb
|
276
352
|
- lib/kitchen/pulumi/config_schemas.rb
|
@@ -284,6 +360,7 @@ files:
|
|
284
360
|
- lib/kitchen/pulumi/config_schemas/system.rb
|
285
361
|
- lib/kitchen/pulumi/config_schemas/systems.rb
|
286
362
|
- lib/kitchen/pulumi/configurable.rb
|
363
|
+
- lib/kitchen/pulumi/deep_merge.rb
|
287
364
|
- lib/kitchen/pulumi/error.rb
|
288
365
|
- lib/kitchen/pulumi/file_path_config_attribute_definer.rb
|
289
366
|
- lib/kitchen/pulumi/inspec.rb
|
@@ -300,7 +377,8 @@ files:
|
|
300
377
|
homepage: https://github.com/jacoblearned/kitchen-pulumi
|
301
378
|
licenses:
|
302
379
|
- MIT
|
303
|
-
metadata:
|
380
|
+
metadata:
|
381
|
+
yard.run: yri
|
304
382
|
post_install_message:
|
305
383
|
rdoc_options: []
|
306
384
|
require_paths:
|
@@ -309,14 +387,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
309
387
|
requirements:
|
310
388
|
- - ">="
|
311
389
|
- !ruby/object:Gem::Version
|
312
|
-
version: '
|
390
|
+
version: '2.6'
|
313
391
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
314
392
|
requirements:
|
315
|
-
- - "
|
393
|
+
- - ">="
|
316
394
|
- !ruby/object:Gem::Version
|
317
|
-
version:
|
395
|
+
version: '0'
|
318
396
|
requirements: []
|
319
|
-
rubygems_version: 3.
|
397
|
+
rubygems_version: 3.1.4
|
320
398
|
signing_key:
|
321
399
|
specification_version: 4
|
322
400
|
summary: Test-Kitchen plugins for Pulumi projects
|