kitchen-verifier-awspec 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 439b2fa25d3c19394ff49322bb6bb8ee0c79fc07
4
+ data.tar.gz: 0cc6b65b38db8950f8ede043aec10e3eabda80d2
5
+ SHA512:
6
+ metadata.gz: 716f3a29a0b99d27b66f565e5d1263f9f6ce50f5377dd0b100a1cd46ebc7a653edf78ca316c1bfb0862c351fabb639a6dbae14dd877433518b0b301a2d551a16
7
+ data.tar.gz: dc4d1de954472fba80ab691bb704565692624162845d478db743d8bad34879e7f91c525b03caa8a319aa98f120d54d80bcd0bd4207d23f867d1f33ae235591a1
@@ -0,0 +1,154 @@
1
+ [![Gem Version](https://badge.fury.io/rb/kitchen-verifier-awspec.svg)](http://badge.fury.io/rb/kitchen-verifier-awspec)
2
+ [![Gem Downloads](http://ruby-gem-downloads-badge.herokuapp.com/kitchen-verifier-awspec?type=total&color=brightgreen)](https://rubygems.org/gems/kitchen-verifier-awspec)
3
+ [![Build Status](https://travis-ci.org/neillturner/kitchen-verifier-awspec.png)](https://travis-ci.org/neillturner/kitchen-verifier-awspec)
4
+
5
+ # Kitchen::Verifier::Awspec
6
+
7
+ A Test Kitchen Awspec Verifer.
8
+
9
+ Can by used in conjunction with kitchen-cloudformation and kitchen-terraform to validate AWS infrastructure changes.
10
+
11
+
12
+ ## Installation
13
+
14
+ On your workstation add this line to your Gemfile:
15
+
16
+ gem 'kitchen-verifier-awspec'
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ Or install it yourself as:
23
+
24
+ $ gem install kitchen-verifier-awspec
25
+
26
+ When it runs it installs awspec on the workstation.
27
+ This can be configured by passing a Gemfile like this:
28
+
29
+ ```
30
+ source 'https://rubygems.org'
31
+
32
+ gem 'net-ssh','~> 2.9'
33
+ gem 'awspec'
34
+ ```
35
+
36
+ This allows extra dependencies to be specified and the version of awspec specified.
37
+
38
+ # Awspec Verifier Options
39
+
40
+ key | default value | Notes
41
+ ----|---------------|--------
42
+ additional_install_commmand | nil | Additional shell command to be used at install stage. Can be multiline. See examples below.
43
+ additional_awspec_command | nil | additional command to run awspec. Can be multiline. See examples below.
44
+ bundler_path | | override path for bundler command
45
+ color | true | enable color in the output
46
+ custom_install_commmand | nil | Custom shell command to be used at install stage. Can be multiline. See examples below.
47
+ custom_awspec_command | nil | custom command to run awspec. Can be multiline. See examples below.
48
+ default_path | '/tmp/kitchen' | Set the default path where awspec looks for patterns
49
+ default_pattern | false | use default dir behaviour of busser i.e. test/integration/SUIT_NAME/awspec/*_spec.rb
50
+ env_vars | {} | environment variable to set for rspec and can be used in the spec_helper. It will automatically pickup any environment variables set with a KITCHEN_ prefix.
51
+ extra_flags | nil | extra flags to add to ther awspec command
52
+ format | 'documentation' | format of awspec output
53
+ gemfile | nil | custom gemfile to use to install awspec
54
+ http_proxy | nil | use http proxy when installing ruby, awspec and running awspec
55
+ https_proxy | nil | use https proxy when installing puppet, ruby, awspec and running awspec
56
+ patterns | [] | array of patterns for spec test files
57
+ remove_default_path | false | remove the default_path after successful awspec run
58
+ rspec_path | | override path for rspec command
59
+ sleep | 0 |
60
+ sudo | nil | use sudo to run commands
61
+ sudo_command | 'sudo -E -H' | sudo command to run when sudo set to true
62
+ test_awspec_installed | true | only run install_command if awspec not installed
63
+
64
+
65
+ ## Usage
66
+
67
+ Verifier awspec runs locally on your workstation and uses aws sdk to verify the aws resources.
68
+
69
+ Verifier Awspec allows the awspec files to be anywhere in the repository or in the awspec default location i.e /spec.
70
+
71
+
72
+ ## Example
73
+
74
+ .kitchen.yml file. See example directory for a full example.
75
+ ```yaml
76
+ ---
77
+ driver:
78
+ name: cloudformation
79
+ stack_name: awspecTest
80
+ ssh_key: spec/test.pem
81
+ template_file: EC2InstanceSample.yml
82
+ # parameters:
83
+ # - KeyName: test
84
+
85
+ provisioner:
86
+ name: dummy
87
+
88
+ platforms:
89
+ - name: aws
90
+
91
+ verifier:
92
+ name: awspec
93
+
94
+ suites:
95
+ - name: base
96
+ verifier:
97
+ patterns:
98
+ - spec/test_spec.rb
99
+
100
+ ```
101
+
102
+ In a command line run the follow line commands to setup environment variables for AWS and run test-kitchen
103
+
104
+ ```
105
+ cd kitchen-verifier-awspec/example
106
+
107
+ # configure aws keys via either a profile
108
+ export AWS_DEFAULT_PROFILE=myprofile
109
+ # or set keys directly
110
+ export AWS_ACCESS_KEY_ID=myaccesskey
111
+ export AWS_SECRET_ACCESS_KEY=mysecretkey
112
+
113
+ export AWS_REGION=eu-west-1
114
+ # for windows set the ssl cert file
115
+ set SSL_CERT_FILE=C:/repository/kitchen-verifier-awspec/example/ca-bundle.crt
116
+
117
+ kitchen list
118
+
119
+ kitchen create base-aws -l debug
120
+
121
+ kitchen converge base-aws -l debug
122
+
123
+ kitchen verify base-aws -l debug
124
+
125
+ kitchen destroy base-aws -l debug
126
+ ```
127
+
128
+ #### custom_install_command example usage
129
+
130
+ * One liner
131
+ ```yaml
132
+ custom_install_command: yum install -y git
133
+ ```
134
+ * Multiple lines, a.k.a embed shell script
135
+ ```yaml
136
+ custom_install_command: |
137
+ command1
138
+ command2
139
+ ```
140
+ * Multiple lines join without new line
141
+ ```yaml
142
+ custom_install_command: >
143
+ command1 &&
144
+ command2
145
+ ```
146
+
147
+ ## Contributing
148
+
149
+ 1. Fork it
150
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
151
+ 3. Run style checks and RSpec tests (`bundle exec rake`)
152
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
153
+ 5. Push to the branch (`git push origin my-new-feature`)
154
+ 6. Create new Pull Request
@@ -0,0 +1,30 @@
1
+
2
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
3
+
4
+ require 'kitchen/verifier/awspec_version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'kitchen-verifier-awspec'
8
+ s.license = 'Apache-2.0'
9
+ s.version = Kitchen::Verifier::AWSPEC_VERSION
10
+ s.authors = ['Neill Turner']
11
+ s.email = ['neillwturner@gmail.com']
12
+ s.homepage = 'https://github.com/neillturner/kitchen-verifier-awspec'
13
+ s.summary = 'Awspec verifier for Test-Kitchen'
14
+ candidates = Dir.glob('{lib}/**/*') + ['README.md', 'kitchen-verifier-awspec.gemspec']
15
+ s.files = candidates.sort
16
+ s.platform = Gem::Platform::RUBY
17
+ s.require_paths = ['lib']
18
+ s.rubyforge_project = '[none]'
19
+ s.add_dependency 'test-kitchen', '~> 1.4'
20
+ if RUBY_VERSION >= '2.0'
21
+ s.add_dependency 'net-ssh', '~> 3'
22
+ else
23
+ s.add_dependency 'json', '~> 1.8'
24
+ s.add_dependency 'net-ssh', '~> 2.9'
25
+ s.add_dependency 'rubocop', '~> 0.41.2'
26
+ end
27
+ s.description = <<-EOF
28
+ Awspec verifier for Test-Kitchen
29
+ EOF
30
+ end
@@ -0,0 +1,322 @@
1
+ #
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+
14
+ require 'kitchen/verifier/base'
15
+
16
+ module Kitchen
17
+ module Verifier
18
+ # Awspec verifier for Kitchen.
19
+ class Awspec < Kitchen::Verifier::Base
20
+ require 'mixlib/shellout'
21
+
22
+ kitchen_verifier_api_version 1
23
+
24
+ plugin_version Kitchen::VERSION
25
+
26
+ default_config :sleep, 0
27
+ default_config :awspec_command, nil
28
+ default_config :custom_awspec_command, nil
29
+ default_config :additional_awspec_command, nil
30
+ default_config :shellout_opts, {}
31
+ default_config :live_stream, $stdout
32
+ default_config :sudo_command, 'sudo -E -H'
33
+ default_config :format, 'documentation'
34
+ default_config :color, true
35
+ default_config :default_path, '/tmp/kitchen'
36
+ default_config :patterns, []
37
+ default_config :default_pattern, false
38
+ default_config :gemfile, nil
39
+ default_config :custom_install_command, nil
40
+ default_config :additional_install_command, nil
41
+ default_config :test_awspec_installed, true
42
+ default_config :extra_flags, nil
43
+ default_config :remove_default_path, false
44
+ default_config :env_vars, {}
45
+ default_config :bundler_path, nil
46
+ default_config :rspec_path, nil
47
+
48
+ # (see Base#call)
49
+ def call(state)
50
+ info("[#{name}] Verify on instance=#{instance} with state=#{state}")
51
+ sleep_if_set
52
+ merge_state_to_env(state)
53
+ config[:default_path] = Dir.pwd if config[:default_path] == '/tmp/kitchen'
54
+ install_command
55
+ awspec_commands
56
+ debug("[#{name}] Verify completed.")
57
+ end
58
+
59
+ ## for legacy drivers.
60
+ def run_command
61
+ sleep_if_set
62
+ awspec_commands
63
+ end
64
+
65
+ def setup_cmd
66
+ sleep_if_set
67
+ install_command
68
+ end
69
+
70
+ # (see Base#create_sandbox)
71
+ def create_sandbox
72
+ super
73
+ prepare_suites
74
+ end
75
+
76
+ def awspec_commands
77
+ if custom_awspec_command
78
+ shellout custom_awspec_command
79
+ else
80
+ if config[:additional_awspec_command]
81
+ c = config[:additional_awspec_command]
82
+ shellout c
83
+ end
84
+ c = rspec_commands
85
+ shellout c
86
+ end
87
+ end
88
+
89
+ def install_command
90
+ info('Installing with custom install command') if config[:custom_install_command]
91
+ return config[:custom_install_command] if config[:custom_install_command]
92
+ info('Installing bundler and awspec locally on workstation')
93
+ if config[:additional_install_command]
94
+ c = config[:additional_install_command]
95
+ shellout c
96
+ end
97
+ install_bundler
98
+ install_awspec
99
+ end
100
+
101
+ # private
102
+
103
+ def install_bundler
104
+ require 'bundler'
105
+ rescue LoadError
106
+ shellout `gem install --no-ri --no-rdoc bundler`
107
+ end
108
+
109
+ # rubocop:disable Metrics/CyclomaticComplexity
110
+ def install_awspec
111
+ if config[:test_awspec_installed]
112
+ begin
113
+ require 'awspec'
114
+ return
115
+ rescue LoadError
116
+ info('awspec not installed installing ...')
117
+ end
118
+ end
119
+ unless config[:gemfile]
120
+ gemfile = "#{config[:default_path]}/Gemfile"
121
+ unless File.exist?(gemfile)
122
+ File.open(gemfile, 'w') do |f|
123
+ f.write("source 'https://rubygems.org'\ngem 'net-ssh','~> 2.9.4'\ngem 'awspec'")
124
+ end
125
+ end
126
+ end
127
+ gemfile = config[:gemfile] if config[:gemfile]
128
+ begin
129
+ shellout "#{bundler_local_cmd} install --gemfile=#{gemfile}"
130
+ rescue
131
+ raise ActionFailed, 'Awspec install failed'
132
+ end
133
+ nil
134
+ end
135
+
136
+ def install_gemfile
137
+ if config[:gemfile]
138
+ <<-INSTALL
139
+ #{read_gemfile}
140
+ INSTALL
141
+ else
142
+ <<-INSTALL
143
+ #{sudo('rm')} -f #{config[:default_path]}/Gemfile
144
+ #{sudo('echo')} "source 'https://rubygems.org'" >> #{config[:default_path]}/Gemfile
145
+ #{sudo('echo')} "gem 'net-ssh','~> 2.9'" >> #{config[:default_path]}/Gemfile
146
+ #{sudo('echo')} "gem 'awspec'" >> #{config[:default_path]}/Gemfile
147
+ INSTALL
148
+ end
149
+ end
150
+
151
+ def read_gemfile
152
+ data = "#{sudo('rm')} -f #{config[:default_path]}/Gemfile\n"
153
+ f = File.open(config[:gemfile], 'r')
154
+ f.each_line do |line|
155
+ data = "#{data}#{sudo('echo')} \"#{line}\" >> #{config[:default_path]}/Gemfile\n"
156
+ end
157
+ f.close
158
+ data
159
+ end
160
+
161
+ def remove_default_path
162
+ info('Removing default path') if config[:remove_default_path]
163
+ config[:remove_default_path] ? "rm -rf #{config[:default_path]}" : nil
164
+ end
165
+
166
+ def test_awspec_installed
167
+ config[:test_awspec_installed] ? "if [ $(#{sudo('gem')} list awspec -i) == 'false' ]; then" : nil
168
+ end
169
+
170
+ def fi_test_awspec_installed
171
+ config[:test_awspec_installed] ? 'fi' : nil
172
+ end
173
+
174
+ def rspec_commands
175
+ info('Running Awspec')
176
+ if config[:default_pattern]
177
+ info("Using default pattern #{config[:default_path]}/spec/*_spec.rb")
178
+ config[:patterns] = ["#{config[:default_path]}/spec/*_spec.rb"]
179
+ end
180
+ config[:patterns].map { |s| "#{env_vars} #{sudo_env(rspec_cmd)} #{color} -f #{config[:format]} --default-path #{config[:default_path]} #{config[:extra_flags]} -P #{s}" }.join(';')
181
+ end
182
+
183
+ def rspec_cmd
184
+ "#{rspec_path}rspec"
185
+ end
186
+
187
+ def env_vars
188
+ return nil if config[:env_vars].none?
189
+ cmd = nil
190
+ config[:env_vars].map do |k, v|
191
+ info("Environment variable #{k} value #{v}")
192
+ ENV[k.to_s] = v.to_s
193
+ end
194
+ cmd
195
+ end
196
+
197
+ def sudo_env(pm)
198
+ # TODO: handle proxies
199
+ pm
200
+ end
201
+
202
+ def custom_awspec_command
203
+ return config[:custom_awspec_command] if config[:custom_awspec_command]
204
+ config[:awspec_command]
205
+ end
206
+
207
+ def bundler_cmd
208
+ config[:bundler_path] ? "#{config[:bundler_path]}/bundle" : '$(which bundle)'
209
+ end
210
+
211
+ def bundler_local_cmd
212
+ config[:bundler_path] ? "#{config[:bundler_path]}/bundle" : 'bundle'
213
+ end
214
+
215
+ def rspec_bash_cmd
216
+ config[:rspec_path] ? "#{config[:rspec_path]}/rspec" : '$(which rspec)'
217
+ end
218
+
219
+ def rspec_path
220
+ config[:rspec_path] ? "#{config[:rspec_path]}/" : nil
221
+ end
222
+
223
+ def rspec_path_option
224
+ config[:rspec_path] ? "--rspec-path #{config[:rspec_path]}/" : nil
225
+ end
226
+
227
+ def http_proxy
228
+ config[:http_proxy]
229
+ end
230
+
231
+ def https_proxy
232
+ config[:https_proxy]
233
+ end
234
+
235
+ def gem_proxy_parm
236
+ http_proxy ? "--http-proxy #{http_proxy}" : nil
237
+ end
238
+
239
+ def color
240
+ config[:color] ? '-c' : nil
241
+ end
242
+
243
+ # Sleep for a period of time, if a value is set in the config.
244
+ #
245
+ # @api private
246
+ def sleep_if_set
247
+ config[:sleep].to_i.times do
248
+ print '.'
249
+ sleep 1
250
+ end
251
+ end
252
+
253
+ def shellout(command)
254
+ command = command.strip
255
+ info("Running command: #{command}")
256
+ cmd = Mixlib::ShellOut.new(command, config[:shellout_opts])
257
+ cmd.live_stream = config[:live_stream]
258
+ cmd.run_command
259
+ begin
260
+ cmd.error!
261
+ rescue Mixlib::ShellOut::ShellCommandFailed
262
+ raise ActionFailed, "Command #{command.inspect} failed for #{instance.to_str}"
263
+ end
264
+ end
265
+
266
+ def merge_state_to_env(state)
267
+ env_state = { :environment => {} }
268
+ env_state[:environment]['KITCHEN_INSTANCE'] = instance.name
269
+ env_state[:environment]['KITCHEN_PLATFORM'] = instance.platform.name
270
+ env_state[:environment]['KITCHEN_SUITE'] = instance.suite.name
271
+ state.each_pair do |key, value|
272
+ env_state[:environment]['KITCHEN_' + key.to_s.upcase] = value.to_s
273
+ ENV['KITCHEN_' + key.to_s.upcase] = value.to_s
274
+ info("Environment variable #{'KITCHEN_' + key.to_s.upcase} value #{value}")
275
+ end
276
+ # if using a driver that uses transport expose those too
277
+ %w(username password ssh_key port).each do |key|
278
+ next if instance.transport[key.to_sym].nil?
279
+ value = instance.transport[key.to_sym].to_s
280
+ ENV['KITCHEN_' + key.to_s.upcase] = value
281
+ info("Transport Environment variable #{'KITCHEN_' + key.to_s.upcase} value #{value}")
282
+ end
283
+ config[:shellout_opts].merge!(env_state)
284
+ end
285
+
286
+ def chef_data_dir?(base, file)
287
+ file =~ %r{^#{base}/(data|data_bags|environments|nodes|roles)/}
288
+ end
289
+
290
+ # Returns an Array of test suite filenames for the related suite currently
291
+ # residing on the local workstation. Any special provisioner-specific
292
+ # directories (such as a Chef roles/ directory) are excluded.
293
+ #
294
+ # @return [Array<String>] array of suite files
295
+ # @api private
296
+ def local_suite_files
297
+ base = File.join(config[:test_base_path], config[:suite_name])
298
+ glob = File.join(base, '*/**/*')
299
+ Dir.glob(glob).reject do |f|
300
+ chef_data_dir?(base, f) || File.directory?(f)
301
+ end
302
+ end
303
+
304
+ # Copies all test suite files into the suites directory in the sandbox.
305
+ def prepare_suites
306
+ base = File.join(config[:test_base_path], config[:suite_name])
307
+ debug("Creating local sandbox of all test suite files in #{base}")
308
+ local_suite_files.each do |src|
309
+ dest = File.join(sandbox_suites_dir, src.sub("#{base}/", ''))
310
+ FileUtils.mkdir_p(File.dirname(dest))
311
+ FileUtils.cp(src, dest, :preserve => true)
312
+ end
313
+ end
314
+
315
+ # @return [String] path to suites directory under sandbox path
316
+ # @api private
317
+ def sandbox_suites_dir
318
+ File.join(sandbox_path, 'suites')
319
+ end
320
+ end
321
+ end
322
+ end
@@ -0,0 +1,5 @@
1
+ module Kitchen
2
+ module Verifier
3
+ AWSPEC_VERSION = '0.1.0'.freeze
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kitchen-verifier-awspec
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Neill Turner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: test-kitchen
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: net-ssh
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3'
41
+ description: |
42
+ Awspec verifier for Test-Kitchen
43
+ email:
44
+ - neillwturner@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - README.md
50
+ - kitchen-verifier-awspec.gemspec
51
+ - lib/kitchen/verifier/awspec.rb
52
+ - lib/kitchen/verifier/awspec_version.rb
53
+ homepage: https://github.com/neillturner/kitchen-verifier-awspec
54
+ licenses:
55
+ - Apache-2.0
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubyforge_project: "[none]"
73
+ rubygems_version: 2.2.2
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: Awspec verifier for Test-Kitchen
77
+ test_files: []