test-kitchen 0.7.0 → 1.0.0.alpha.0
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.
- data/.gitignore +20 -0
- data/.travis.yml +11 -0
- data/.yardopts +3 -0
- data/Gemfile +13 -0
- data/Guardfile +11 -0
- data/LICENSE +15 -0
- data/README.md +131 -0
- data/Rakefile +69 -0
- data/bin/kitchen +9 -4
- data/features/cli.feature +17 -0
- data/features/cli_init.feature +156 -0
- data/features/support/env.rb +14 -0
- data/lib/kitchen/busser.rb +166 -0
- data/lib/kitchen/chef_data_uploader.rb +156 -0
- data/lib/kitchen/cli.rb +540 -0
- data/lib/kitchen/collection.rb +55 -0
- data/lib/kitchen/color.rb +46 -0
- data/lib/kitchen/config.rb +223 -0
- data/lib/kitchen/driver/base.rb +180 -0
- data/lib/kitchen/driver/dummy.rb +81 -0
- data/lib/kitchen/driver/ssh_base.rb +192 -0
- data/lib/kitchen/driver.rb +42 -0
- data/lib/kitchen/errors.rb +52 -0
- data/lib/kitchen/instance.rb +327 -0
- data/lib/kitchen/instance_actor.rb +42 -0
- data/lib/kitchen/loader/yaml.rb +105 -0
- data/lib/kitchen/logger.rb +145 -0
- data/{cookbooks/test-kitchen/libraries/helpers.rb → lib/kitchen/logging.rb} +13 -9
- data/lib/kitchen/manager.rb +45 -0
- data/lib/kitchen/metadata_chopper.rb +52 -0
- data/lib/kitchen/platform.rb +61 -0
- data/lib/kitchen/rake_tasks.rb +59 -0
- data/lib/kitchen/shell_out.rb +65 -0
- data/lib/kitchen/state_file.rb +88 -0
- data/lib/kitchen/suite.rb +76 -0
- data/lib/kitchen/thor_tasks.rb +62 -0
- data/lib/kitchen/util.rb +79 -0
- data/{cookbooks/test-kitchen/recipes/erlang.rb → lib/kitchen/version.rb} +9 -6
- data/lib/kitchen.rb +98 -0
- data/lib/vendor/hash_recursive_merge.rb +74 -0
- data/spec/kitchen/collection_spec.rb +80 -0
- data/spec/kitchen/color_spec.rb +54 -0
- data/spec/kitchen/config_spec.rb +201 -0
- data/spec/kitchen/driver/dummy_spec.rb +191 -0
- data/spec/kitchen/instance_spec.rb +162 -0
- data/spec/kitchen/loader/yaml_spec.rb +243 -0
- data/spec/kitchen/platform_spec.rb +48 -0
- data/spec/kitchen/state_file_spec.rb +122 -0
- data/spec/kitchen/suite_spec.rb +64 -0
- data/spec/spec_helper.rb +47 -0
- data/templates/plugin/driver.rb.erb +23 -0
- data/templates/plugin/license_apachev2.erb +15 -0
- data/templates/plugin/license_gplv2.erb +18 -0
- data/templates/plugin/license_gplv3.erb +16 -0
- data/templates/plugin/license_mit.erb +22 -0
- data/templates/plugin/license_reserved.erb +5 -0
- data/templates/plugin/version.rb.erb +12 -0
- data/test-kitchen.gemspec +44 -0
- metadata +290 -82
- data/config/Cheffile +0 -47
- data/config/Kitchenfile +0 -39
- data/config/Vagrantfile +0 -114
- data/cookbooks/test-kitchen/attributes/default.rb +0 -25
- data/cookbooks/test-kitchen/metadata.rb +0 -27
- data/cookbooks/test-kitchen/recipes/chef.rb +0 -19
- data/cookbooks/test-kitchen/recipes/compat.rb +0 -39
- data/cookbooks/test-kitchen/recipes/default.rb +0 -51
- data/cookbooks/test-kitchen/recipes/ruby.rb +0 -29
- data/lib/test-kitchen/cli/destroy.rb +0 -36
- data/lib/test-kitchen/cli/init.rb +0 -37
- data/lib/test-kitchen/cli/platform_list.rb +0 -37
- data/lib/test-kitchen/cli/project_info.rb +0 -44
- data/lib/test-kitchen/cli/ssh.rb +0 -36
- data/lib/test-kitchen/cli/status.rb +0 -36
- data/lib/test-kitchen/cli/test.rb +0 -68
- data/lib/test-kitchen/cli.rb +0 -282
- data/lib/test-kitchen/dsl.rb +0 -63
- data/lib/test-kitchen/environment.rb +0 -166
- data/lib/test-kitchen/platform.rb +0 -79
- data/lib/test-kitchen/project/base.rb +0 -159
- data/lib/test-kitchen/project/cookbook.rb +0 -97
- data/lib/test-kitchen/project/cookbook_copy.rb +0 -58
- data/lib/test-kitchen/project/ruby.rb +0 -37
- data/lib/test-kitchen/project/supported_platforms.rb +0 -75
- data/lib/test-kitchen/project.rb +0 -23
- data/lib/test-kitchen/runner/base.rb +0 -154
- data/lib/test-kitchen/runner/openstack/dsl.rb +0 -39
- data/lib/test-kitchen/runner/openstack/environment.rb +0 -141
- data/lib/test-kitchen/runner/openstack.rb +0 -147
- data/lib/test-kitchen/runner/vagrant.rb +0 -95
- data/lib/test-kitchen/runner.rb +0 -21
- data/lib/test-kitchen/scaffold.rb +0 -88
- data/lib/test-kitchen/ui.rb +0 -73
- data/lib/test-kitchen/version.rb +0 -21
- data/lib/test-kitchen.rb +0 -34
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
guard 'minitest' do
|
2
|
+
watch(%r|^spec/(.*)_spec\.rb|)
|
3
|
+
watch(%r|^lib/(.*)([^/]+)\.rb|) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
4
|
+
watch(%r|^spec/spec_helper\.rb|) { "spec" }
|
5
|
+
end
|
6
|
+
|
7
|
+
guard 'cucumber' do
|
8
|
+
watch(%r{^features/.+\.feature$})
|
9
|
+
watch(%r{^features/support/.+$}) { 'features' }
|
10
|
+
watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
|
11
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
2
|
+
|
3
|
+
Copyright 2012 Fletcher Nichol
|
4
|
+
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
you may not use this file except in compliance with the License.
|
7
|
+
You may obtain a copy of the License at
|
8
|
+
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
See the License for the specific language governing permissions and
|
15
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
# Test Kitchen
|
2
|
+
|
3
|
+
[](https://travis-ci.org/opscode/test-kitchen)
|
4
|
+
[](https://codeclimate.com/github/opscode/test-kitchen)
|
5
|
+
|
6
|
+
A convergence integration test harness for configuration management systems.
|
7
|
+
|
8
|
+
# Getting started
|
9
|
+
|
10
|
+
|
11
|
+
Project Setup
|
12
|
+
-------------
|
13
|
+
|
14
|
+
In your `Gemfile`, add `test-kitchen` as a
|
15
|
+
dependency:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'test-kitchen', git: 'git://github.com/opscode/test-kitchen.git', branch: '1.0'
|
19
|
+
```
|
20
|
+
|
21
|
+
and run the `bundle` command to install:
|
22
|
+
|
23
|
+
$ bundle install
|
24
|
+
|
25
|
+
This will expose the `test-kitchen` CLI. Run `bundle exec kitchen init` to get started:
|
26
|
+
|
27
|
+
$ kitchen init
|
28
|
+
|
29
|
+
You will be prompted with a series of questions. In this guide, we
|
30
|
+
will be using the [kitchen vagrant driver](https://github.com/opscode/kitchen-vagrant).
|
31
|
+
|
32
|
+
```text
|
33
|
+
$ bundle exec kitchen init
|
34
|
+
create .kitchen.yml
|
35
|
+
append Rakefile
|
36
|
+
create test/integration/default
|
37
|
+
append .gitignore
|
38
|
+
append .gitignore
|
39
|
+
Add a Driver plugin to your Gemfile?
|
40
|
+
(y/n)> y
|
41
|
+
Enter gem name, `list', or `skip'>
|
42
|
+
kitchen-vagrant
|
43
|
+
append Gemfile
|
44
|
+
You must run `bundle install' to fetch any new gems.
|
45
|
+
```
|
46
|
+
|
47
|
+
Run the `bundle` command again to install the new vagrant driver:
|
48
|
+
|
49
|
+
$ bundle install
|
50
|
+
|
51
|
+
Open up the `.kitchen.yml` file created in the root of your
|
52
|
+
repository.
|
53
|
+
|
54
|
+
Now, it is time to get testing. Use the `--parallel` option to run
|
55
|
+
your tests in parallel. Trust us, it's faster!
|
56
|
+
|
57
|
+
$ bundle exec kitchen test
|
58
|
+
|
59
|
+
## The Kitchen YAML format
|
60
|
+
|
61
|
+
Test-Kitchen reads its configuration from the .kitchen.yml
|
62
|
+
configuration file at the root of your cookbook. It closely resembles
|
63
|
+
the format of .travis.yml which is intentional.
|
64
|
+
|
65
|
+
There are 4 stanzas in .kitchen.yml, driver_plugin, driver_config,
|
66
|
+
platforms, and suites. driver_plugin, platforms, and suites are
|
67
|
+
currently required. driver_config can optionally be used to set values
|
68
|
+
for all platforms defined.
|
69
|
+
|
70
|
+
The driver_plugin stanza is only one line long and defines which
|
71
|
+
driver is used by test-kitchen.
|
72
|
+
|
73
|
+
The platforms stanza defines individual virtual machines. Additional
|
74
|
+
driver_config, node attributes, and run_list can be defined in this stanza
|
75
|
+
|
76
|
+
The suites stanza defines sets of tests that you intend to be run on
|
77
|
+
each platform. A run_list and node attributes can be defined for each
|
78
|
+
suite. The run_list and node attributes will be merged with that of
|
79
|
+
each platform. In case of the conflict, the attributes defined on the
|
80
|
+
suite will triumph.
|
81
|
+
|
82
|
+
```yaml
|
83
|
+
|
84
|
+
---
|
85
|
+
driver_plugin: vagrant
|
86
|
+
|
87
|
+
platforms:
|
88
|
+
- name: ubuntu-12.04
|
89
|
+
driver_config:
|
90
|
+
box: opscode-ubuntu-12.04
|
91
|
+
box_url: https://opscode-vm.s3.amazonaws.com/vagrant/boxes/opscode-ubuntu-12.04.box
|
92
|
+
|
93
|
+
- name: centos-6.3
|
94
|
+
driver_config:
|
95
|
+
box: opscode-centos-6.3
|
96
|
+
box_url: https://opscode-vm.s3.amazonaws.com/vagrant/boxes/opscode-centos-6.3.box
|
97
|
+
run_list:
|
98
|
+
- recipe[yum::epel]
|
99
|
+
|
100
|
+
suites:
|
101
|
+
- name: stock_system_and_user
|
102
|
+
run_list:
|
103
|
+
- recipe[user::data_bag]
|
104
|
+
- recipe[rvm::system]
|
105
|
+
- recipe[rvm::user]
|
106
|
+
attributes:
|
107
|
+
users:
|
108
|
+
- wigglebottom
|
109
|
+
rvm:
|
110
|
+
user_installs:
|
111
|
+
- user: wigglebottom
|
112
|
+
default_ruby: 1.8.7
|
113
|
+
```
|
114
|
+
|
115
|
+
## Overriding .kitchen.yaml with .kitchen.<driver>.local.yml
|
116
|
+
|
117
|
+
TODO
|
118
|
+
|
119
|
+
## A Note
|
120
|
+
|
121
|
+
This project is currently in rapid development which means frequent releases,
|
122
|
+
potential for massive refactorings (that could be API breaking), and minimal
|
123
|
+
to no documentation. This will change as the project transitions to be used in
|
124
|
+
production environments.
|
125
|
+
|
126
|
+
Despite the warnings above, if you are still interested, please get in touch
|
127
|
+
via freenode/IRC (#chef-hacking),
|
128
|
+
Twitter ([@fnichol](https://twitter.com/fnichol)),
|
129
|
+
or Email ([fnichol@nichol.ca](mailto:fnichol@nichol.ca)).
|
130
|
+
|
131
|
+
For everyone else, watch [this space](https://github.com/opscode/test-kitchen).
|
data/Rakefile
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
Rake::TestTask.new do |t|
|
5
|
+
t.libs.push "lib"
|
6
|
+
t.test_files = FileList['spec/**/*_spec.rb']
|
7
|
+
t.verbose = true
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => [:test]
|
11
|
+
|
12
|
+
unless RUBY_ENGINE == 'jruby'
|
13
|
+
require 'cane/rake_task'
|
14
|
+
require 'tailor/rake_task'
|
15
|
+
require 'cucumber'
|
16
|
+
require 'cucumber/rake/task'
|
17
|
+
|
18
|
+
desc "Run cane to check quality metrics"
|
19
|
+
Cane::RakeTask.new do |cane|
|
20
|
+
cane.abc_exclude = %w(
|
21
|
+
Kitchen::RakeTasks#define
|
22
|
+
Kitchen::ThorTasks#define
|
23
|
+
Kitchen::CLI#pry_prompts
|
24
|
+
Kitchen::Instance#synchronize_or_call
|
25
|
+
)
|
26
|
+
cane.style_exclude = %w(
|
27
|
+
lib/vendor/hash_recursive_merge.rb
|
28
|
+
)
|
29
|
+
cane.doc_exclude = %w(
|
30
|
+
lib/vendor/hash_recursive_merge.rb
|
31
|
+
)
|
32
|
+
cane.style_measure = 160
|
33
|
+
end
|
34
|
+
|
35
|
+
Tailor::RakeTask.new do |task|
|
36
|
+
task.file_set('bin/*', 'binaries')
|
37
|
+
task.file_set('lib/**/*.rb', 'code') do |style|
|
38
|
+
# TODO: Tailor is confused thinking `module Kitchen` is a class. Until
|
39
|
+
# the classes are split in seperate files, let's punt on this
|
40
|
+
style.max_code_lines_in_class 1550, level: :warn
|
41
|
+
# NOTE: Kitchen::InitGenerator.default_yaml is over the default 30 lines
|
42
|
+
# and produces a warning. Since most of it is increasing readability of
|
43
|
+
# the data structure, allowing it here to prevent it from growing
|
44
|
+
style.max_code_lines_in_method 34
|
45
|
+
style.max_line_length 80, level: :warn
|
46
|
+
style.max_line_length 160, level: :error
|
47
|
+
end
|
48
|
+
task.file_set('spec/**/*.rb', 'tests') do |style|
|
49
|
+
# allow vertical alignment of `let(:foo) { block }` blocks
|
50
|
+
style.spaces_before_lbrace 1, level: :off
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
55
|
+
t.cucumber_opts = ['features', '-x', '--format progress']
|
56
|
+
end
|
57
|
+
|
58
|
+
Rake::Task[:default].enhance [:cane, :features, :tailor]
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "Display LOC stats"
|
62
|
+
task :stats do
|
63
|
+
puts "\n## Production Code Stats"
|
64
|
+
sh "countloc -r lib/kitchen lib/kitchen.rb"
|
65
|
+
puts "\n## Test Code Stats"
|
66
|
+
sh "countloc -r spec features"
|
67
|
+
end
|
68
|
+
|
69
|
+
Rake::Task[:default].enhance [:stats]
|
data/bin/kitchen
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# -*- encoding: utf-8 -*-
|
2
3
|
|
3
|
-
|
4
|
-
#
|
5
|
-
|
4
|
+
# Trap interrupts to quit cleanly. See
|
5
|
+
# https://twitter.com/mitchellh/status/283014103189053442
|
6
|
+
Signal.trap("INT") { exit 1 }
|
6
7
|
|
7
|
-
|
8
|
+
$:.unshift File.join(File.dirname(__FILE__), %w{.. lib})
|
9
|
+
require 'rubygems'
|
10
|
+
require 'kitchen/cli'
|
11
|
+
|
12
|
+
Kitchen::CLI.start
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Feature: Ensure that the Command Line Interface works as designed
|
2
|
+
In order to test code via CLI
|
3
|
+
As an Operator
|
4
|
+
I want to run the CLI with different arguments
|
5
|
+
|
6
|
+
Scenario: Running the help command exits cleanly
|
7
|
+
When I successfully run `kitchen help`
|
8
|
+
Then the exit status should be 0
|
9
|
+
And the output should contain "kitchen console"
|
10
|
+
And a file named ".kitchen/logs/kitchen.log" should exist
|
11
|
+
|
12
|
+
Scenario: Show the version number
|
13
|
+
When I successfully run `kitchen version`
|
14
|
+
Then the exit status should be 0
|
15
|
+
|
16
|
+
|
17
|
+
|
@@ -0,0 +1,156 @@
|
|
1
|
+
Feature: Ensure that the Command Line Interface init creates the correct files
|
2
|
+
In order to initialize an un-Kitchenified cookbook
|
3
|
+
As an Operator
|
4
|
+
I want to initialize a cookbook
|
5
|
+
|
6
|
+
|
7
|
+
@ok
|
8
|
+
Scenario: Basic init with no extras succeeds
|
9
|
+
When I run `kitchen init` interactively
|
10
|
+
And I type "n"
|
11
|
+
Then the exit status should be 0
|
12
|
+
And a directory named ".kitchen" should exist
|
13
|
+
And a directory named "test/integration/default" should exist
|
14
|
+
And the file ".gitignore" should contain:
|
15
|
+
"""
|
16
|
+
.kitchen/
|
17
|
+
.kitchen.local.yml
|
18
|
+
"""
|
19
|
+
And the file ".kitchen.yml" should contain:
|
20
|
+
"""
|
21
|
+
---
|
22
|
+
driver_plugin: vagrant
|
23
|
+
platforms:
|
24
|
+
- name: ubuntu-12.04
|
25
|
+
driver_config:
|
26
|
+
box: opscode-ubuntu-12.04
|
27
|
+
box_url: https://opscode-vm.s3.amazonaws.com/vagrant/boxes/opscode-ubuntu-12.04.box
|
28
|
+
run_list:
|
29
|
+
- recipe[apt]
|
30
|
+
- name: ubuntu-10.04
|
31
|
+
driver_config:
|
32
|
+
box: opscode-ubuntu-10.04
|
33
|
+
box_url: https://opscode-vm.s3.amazonaws.com/vagrant/boxes/opscode-ubuntu-10.04.box
|
34
|
+
run_list:
|
35
|
+
- recipe[apt]
|
36
|
+
- name: centos-6.3
|
37
|
+
driver_config:
|
38
|
+
box: opscode-centos-6.3
|
39
|
+
box_url: https://opscode-vm.s3.amazonaws.com/vagrant/boxes/opscode-centos-6.3.box
|
40
|
+
run_list:
|
41
|
+
- recipe[yum::epel]
|
42
|
+
- name: centos-5.8
|
43
|
+
driver_config:
|
44
|
+
box: opscode-centos-5.8
|
45
|
+
box_url: https://opscode-vm.s3.amazonaws.com/vagrant/boxes/opscode-centos-5.8.box
|
46
|
+
run_list:
|
47
|
+
- recipe[yum::epel]
|
48
|
+
suites:
|
49
|
+
- name: default
|
50
|
+
run_list: []
|
51
|
+
attributes: {}
|
52
|
+
"""
|
53
|
+
And a file named "Gemfile" should not exist
|
54
|
+
And a file named "Rakefile" should not exist
|
55
|
+
And a file named "Thorfile" should not exist
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
@ok
|
60
|
+
Scenario: Running with a Rakefile file appends Kitchen tasks
|
61
|
+
Given an empty file named "Rakefile"
|
62
|
+
When I run `kitchen init` interactively
|
63
|
+
And I type "n"
|
64
|
+
Then the exit status should be 0
|
65
|
+
And the file "Rakefile" should contain exactly:
|
66
|
+
"""
|
67
|
+
|
68
|
+
begin
|
69
|
+
require 'kitchen/rake_tasks'
|
70
|
+
Kitchen::RakeTasks.new
|
71
|
+
rescue LoadError
|
72
|
+
puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV['CI']
|
73
|
+
end
|
74
|
+
|
75
|
+
"""
|
76
|
+
|
77
|
+
|
78
|
+
@ok
|
79
|
+
Scenario: Running with a Thorfile file appends Kitchen tasks
|
80
|
+
Given an empty file named "Thorfile"
|
81
|
+
When I run `kitchen init` interactively
|
82
|
+
And I type "n"
|
83
|
+
Then the exit status should be 0
|
84
|
+
And the file "Thorfile" should contain exactly:
|
85
|
+
"""
|
86
|
+
|
87
|
+
begin
|
88
|
+
require 'kitchen/thor_tasks'
|
89
|
+
Kitchen::ThorTasks.new
|
90
|
+
rescue LoadError
|
91
|
+
puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV['CI']
|
92
|
+
end
|
93
|
+
|
94
|
+
"""
|
95
|
+
|
96
|
+
|
97
|
+
@ok
|
98
|
+
Scenario: Listing the drivers provides correct output, does not write Gemfile
|
99
|
+
When I run `kitchen init` interactively
|
100
|
+
And I type "y"
|
101
|
+
And I type "list"
|
102
|
+
And I type "skip"
|
103
|
+
Then the exit status should be 0
|
104
|
+
And a file named ".kitchen.yml" should exist
|
105
|
+
And a directory named ".kitchen" should exist
|
106
|
+
And a file named "Gemfile" should not exist
|
107
|
+
|
108
|
+
|
109
|
+
@ok
|
110
|
+
Scenario: Running the init command without a Gemfile provides warning and fails
|
111
|
+
When I run `kitchen init` interactively
|
112
|
+
And I type "y"
|
113
|
+
And I type "kitchen-vagrant"
|
114
|
+
And the output should contain "You do not have an existing Gemfile"
|
115
|
+
Then the exit status should be 1
|
116
|
+
|
117
|
+
|
118
|
+
@ok
|
119
|
+
Scenario: Running the init command succeeds
|
120
|
+
Given an empty file named "Gemfile"
|
121
|
+
When I run `kitchen init` interactively
|
122
|
+
And I type "y"
|
123
|
+
And I type "kitchen-vagrant"
|
124
|
+
Then the exit status should be 0
|
125
|
+
And the output should contain "You must run `bundle install' to fetch any new gems."
|
126
|
+
And a file named ".kitchen.yml" should exist
|
127
|
+
And a file named ".gitignore" should exist
|
128
|
+
And the file "Gemfile" should contain "gem 'kitchen-vagrant', :group => :integration"
|
129
|
+
|
130
|
+
|
131
|
+
@ok
|
132
|
+
Scenario: Running init with a correct metadata.rb works
|
133
|
+
Given a file named "metadata.rb" with:
|
134
|
+
"""
|
135
|
+
name "ntp"
|
136
|
+
license "Apache 2.0"
|
137
|
+
description "Installs and configures ntp as a client or server"
|
138
|
+
version "0.1.0"
|
139
|
+
recipe "ntp", "Installs and configures ntp either as a server or client"
|
140
|
+
|
141
|
+
%w{ ubuntu debian redhat centos fedora scientific amazon oracle freebsd }.each do |os|
|
142
|
+
supports os
|
143
|
+
end
|
144
|
+
"""
|
145
|
+
When I run `kitchen init` interactively
|
146
|
+
And I type "n"
|
147
|
+
Then the exit status should be 0
|
148
|
+
And the file ".kitchen.yml" should contain:
|
149
|
+
"""
|
150
|
+
suites:
|
151
|
+
- name: default
|
152
|
+
run_list:
|
153
|
+
- recipe[ntp]
|
154
|
+
attributes: {}
|
155
|
+
"""
|
156
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Set up the environment for testing
|
2
|
+
require 'aruba/cucumber'
|
3
|
+
require 'kitchen'
|
4
|
+
|
5
|
+
Before do
|
6
|
+
@aruba_timeout_seconds = 5
|
7
|
+
end
|
8
|
+
|
9
|
+
After do |s|
|
10
|
+
# Tell Cucumber to quit after this scenario is done - if it failed.
|
11
|
+
# This is useful to inspect the 'tmp/aruba' directory before any other
|
12
|
+
# steps are executed and clear it out.
|
13
|
+
Cucumber.wants_to_quit = true if s.failed?
|
14
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012, Fletcher Nichol
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require 'base64'
|
20
|
+
require 'digest'
|
21
|
+
require 'net/https'
|
22
|
+
|
23
|
+
module Kitchen
|
24
|
+
|
25
|
+
# Command string generator to interface with Kitchen Busser (kb). The
|
26
|
+
# commands that are generated are safe to pass to an SSH command or as an
|
27
|
+
# unix command argument (escaped in single quotes).
|
28
|
+
#
|
29
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
30
|
+
class Busser
|
31
|
+
|
32
|
+
# Constructs a new busser command generator, given a suite name.
|
33
|
+
#
|
34
|
+
# @param [String] suite_name name of suite on which to operate
|
35
|
+
# (**Required**)
|
36
|
+
# @param [Hash] opts optional configuration
|
37
|
+
# @option opts [TrueClass, FalseClass] :use_sudo whether or not to invoke
|
38
|
+
# sudo before commands requiring root access (default: `true`)
|
39
|
+
def initialize(suite_name, opts = { :use_sudo => true })
|
40
|
+
validate_options(suite_name)
|
41
|
+
|
42
|
+
@suite_name = suite_name
|
43
|
+
@use_sudo = opts[:use_sudo]
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns a command string which installs the Kitchen Busser (kb), installs
|
47
|
+
# all required kb plugins for the suite.
|
48
|
+
#
|
49
|
+
# If no work needs to be performed, for example if there are no tests for
|
50
|
+
# the given suite, then `nil` will be returned.
|
51
|
+
#
|
52
|
+
# @return [String] a command string to setup the test suite, or nil if no
|
53
|
+
# work needs to be performed
|
54
|
+
def setup_cmd
|
55
|
+
@setup_cmd ||= if local_suite_files.empty?
|
56
|
+
nil
|
57
|
+
else
|
58
|
+
<<-INSTALL_CMD.gsub(/^ {10}/, '')
|
59
|
+
#{sudo}#{ruby_bin} -e "$(cat <<"EOF"
|
60
|
+
#{install_script}
|
61
|
+
EOF
|
62
|
+
)"
|
63
|
+
#{sudo}#{kb_bin} install #{plugins.join(' ')}
|
64
|
+
INSTALL_CMD
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns a command string which transfers all suite test files to the
|
69
|
+
# instance.
|
70
|
+
#
|
71
|
+
# If no work needs to be performed, for example if there are no tests for
|
72
|
+
# the given suite, then `nil` will be returned.
|
73
|
+
#
|
74
|
+
# @return [String] a command string to transfer all suite test files, or
|
75
|
+
# nil if no work needs to be performed.
|
76
|
+
def sync_cmd
|
77
|
+
@sync_cmd ||= if local_suite_files.empty?
|
78
|
+
nil
|
79
|
+
else
|
80
|
+
<<-INSTALL_CMD.gsub(/^ {10}/, '')
|
81
|
+
#{sudo}#{kb_bin} cleanup-suites
|
82
|
+
#{local_suite_files.map { |f| stream_file(f, remote_file(f)) }.join}
|
83
|
+
INSTALL_CMD
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns a command string which runs all kb suite tests for the suite.
|
88
|
+
#
|
89
|
+
# If no work needs to be performed, for example if there are no tests for
|
90
|
+
# the given suite, then `nil` will be returned.
|
91
|
+
#
|
92
|
+
# @return [String] a command string to run the test suites, or nil if no
|
93
|
+
# work needs to be performed
|
94
|
+
def run_cmd
|
95
|
+
@run_cmd ||= local_suite_files.empty? ? nil : "#{sudo}#{kb_bin} test"
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
INSTALL_URL = "https://raw.github.com/opscode/kb/go".freeze
|
101
|
+
DEFAULT_RUBY_BINPATH = "/opt/chef/embedded/bin".freeze
|
102
|
+
DEFAULT_KB_ROOT = "/opt/kb".freeze
|
103
|
+
DEFAULT_TEST_ROOT = File.join(Dir.pwd, "test/integration").freeze
|
104
|
+
|
105
|
+
def validate_options(suite_name)
|
106
|
+
raise ClientError, "Busser#new requires a suite_name" if suite_name.nil?
|
107
|
+
end
|
108
|
+
|
109
|
+
def install_script
|
110
|
+
@install_script ||= begin
|
111
|
+
uri = URI.parse(INSTALL_URL)
|
112
|
+
http = Net::HTTP.new(uri.host, 443)
|
113
|
+
http.use_ssl = true
|
114
|
+
response = http.request(Net::HTTP::Get.new(uri.path))
|
115
|
+
response.body
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def plugins
|
120
|
+
Dir.glob(File.join(test_root, @suite_name, "*")).select { |d|
|
121
|
+
File.directory?(d) && File.basename(d) != "data_bags"
|
122
|
+
}.map { |d| File.basename(d) }.sort.uniq
|
123
|
+
end
|
124
|
+
|
125
|
+
def local_suite_files
|
126
|
+
Dir.glob(File.join(test_root, @suite_name, "*/**/*")).reject do |f|
|
127
|
+
f["data_bags"] || File.directory?(f)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def remote_file(file)
|
132
|
+
local_prefix = File.join(test_root, @suite_name)
|
133
|
+
"$(#{kb_bin} suitepath)/".concat(file.sub(%r{^#{local_prefix}/}, ''))
|
134
|
+
end
|
135
|
+
|
136
|
+
def stream_file(local_path, remote_path)
|
137
|
+
local_file = IO.read(local_path)
|
138
|
+
md5 = Digest::MD5.hexdigest(local_file)
|
139
|
+
perms = sprintf("%o", File.stat(local_path).mode)[3, 3]
|
140
|
+
kb_stream_file = "#{kb_bin} stream-file #{remote_path} #{md5} #{perms}"
|
141
|
+
|
142
|
+
<<-STREAMFILE.gsub(/^ {8}/, '')
|
143
|
+
echo "Uploading #{remote_path} (mode=#{perms})"
|
144
|
+
cat <<"__EOFSTREAM__" | #{sudo}#{kb_stream_file}
|
145
|
+
#{Base64.encode64(local_file)}
|
146
|
+
__EOFSTREAM__
|
147
|
+
STREAMFILE
|
148
|
+
end
|
149
|
+
|
150
|
+
def sudo
|
151
|
+
@use_sudo ? "sudo " : ""
|
152
|
+
end
|
153
|
+
|
154
|
+
def ruby_bin
|
155
|
+
File.join(DEFAULT_RUBY_BINPATH, "ruby")
|
156
|
+
end
|
157
|
+
|
158
|
+
def kb_bin
|
159
|
+
File.join(DEFAULT_KB_ROOT, "bin/kb")
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_root
|
163
|
+
DEFAULT_TEST_ROOT
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|