test-kitchen 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/kitchen +7 -0
- data/config/Cheffile +55 -0
- data/config/Kitchenfile +39 -0
- data/config/Vagrantfile +109 -0
- data/cookbooks/test-kitchen/attributes/default.rb +25 -0
- data/cookbooks/test-kitchen/libraries/helpers.rb +25 -0
- data/cookbooks/test-kitchen/metadata.rb +27 -0
- data/cookbooks/test-kitchen/recipes/chef.rb +19 -0
- data/cookbooks/test-kitchen/recipes/compat.rb +39 -0
- data/cookbooks/test-kitchen/recipes/default.rb +51 -0
- data/cookbooks/test-kitchen/recipes/erlang.rb +19 -0
- data/cookbooks/test-kitchen/recipes/ruby.rb +40 -0
- data/lib/test-kitchen.rb +34 -0
- data/lib/test-kitchen/cli.rb +267 -0
- data/lib/test-kitchen/cli/destroy.rb +42 -0
- data/lib/test-kitchen/cli/init.rb +37 -0
- data/lib/test-kitchen/cli/platform_list.rb +37 -0
- data/lib/test-kitchen/cli/project_info.rb +44 -0
- data/lib/test-kitchen/cli/ssh.rb +36 -0
- data/lib/test-kitchen/cli/status.rb +36 -0
- data/lib/test-kitchen/cli/test.rb +60 -0
- data/lib/test-kitchen/dsl.rb +59 -0
- data/lib/test-kitchen/environment.rb +164 -0
- data/lib/test-kitchen/platform.rb +63 -0
- data/lib/test-kitchen/project.rb +23 -0
- data/lib/test-kitchen/project/base.rb +159 -0
- data/lib/test-kitchen/project/cookbook.rb +87 -0
- data/lib/test-kitchen/project/cookbook_copy.rb +58 -0
- data/lib/test-kitchen/project/ruby.rb +37 -0
- data/lib/test-kitchen/project/supported_platforms.rb +75 -0
- data/lib/test-kitchen/runner.rb +20 -0
- data/lib/test-kitchen/runner/base.rb +144 -0
- data/lib/test-kitchen/runner/vagrant.rb +92 -0
- data/lib/test-kitchen/scaffold.rb +73 -0
- data/lib/test-kitchen/ui.rb +73 -0
- data/lib/test-kitchen/version.rb +21 -0
- metadata +196 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2012 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/mixin/params_validate'
|
20
|
+
|
21
|
+
module TestKitchen
|
22
|
+
module Project
|
23
|
+
class Base
|
24
|
+
include Chef::Mixin::ParamsValidate
|
25
|
+
|
26
|
+
PROJECT_ROOT_INDICATORS = ["Gemfile", "metadata.rb"]
|
27
|
+
|
28
|
+
attr_reader :name, :guest_source_root, :guest_test_root, :exclusions
|
29
|
+
attr_writer :language, :runtimes, :install, :script, :configurations, :root_path, :memory
|
30
|
+
attr_accessor :vm
|
31
|
+
|
32
|
+
def initialize(name, parent=nil, &block)
|
33
|
+
raise ArgumentError, "Project name must be specified" if name.nil? || name.empty?
|
34
|
+
@name = name
|
35
|
+
@parent = parent
|
36
|
+
@configurations = {}
|
37
|
+
@exclusions = []
|
38
|
+
@guest_source_root = '/test-kitchen/source'
|
39
|
+
@guest_test_root = '/test-kitchen/test'
|
40
|
+
instance_eval(&block) if block_given?
|
41
|
+
end
|
42
|
+
|
43
|
+
def each_build(platforms, active_config=nil)
|
44
|
+
raise ArgumentError if platforms.nil? || ! block_given?
|
45
|
+
c = Array(active_config ?
|
46
|
+
configurations[active_config] : configurations.values)
|
47
|
+
platforms.to_a.product(c).each do |platform,configuration|
|
48
|
+
yield [platform, configuration] unless exclusions.any? do |e|
|
49
|
+
e[:platform] == platform.split('-').first &&
|
50
|
+
((! e[:configuration]) || e[:configuration] == configuration.name)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def configuration(name, &block)
|
56
|
+
@configurations[name] = self.class.new(name, self, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
def configurations
|
60
|
+
@configurations.empty? ? {:default => self} : @configurations
|
61
|
+
end
|
62
|
+
|
63
|
+
def tests_tag
|
64
|
+
@parent.nil? ? 'default' : name
|
65
|
+
end
|
66
|
+
|
67
|
+
def exclude(exclusion)
|
68
|
+
@exclusions << exclusion
|
69
|
+
end
|
70
|
+
|
71
|
+
def run_list
|
72
|
+
['test-kitchen::default'] + run_list_extras
|
73
|
+
end
|
74
|
+
|
75
|
+
def run_list_extras(arg=nil)
|
76
|
+
set_or_return(:run_list_extras, arg, :default => [])
|
77
|
+
end
|
78
|
+
|
79
|
+
def runner(arg=nil)
|
80
|
+
set_or_return(:runner, arg, :default => 'vagrant')
|
81
|
+
end
|
82
|
+
|
83
|
+
def language(arg=nil)
|
84
|
+
set_or_return(:language, arg, :default => 'ruby')
|
85
|
+
end
|
86
|
+
|
87
|
+
def runtimes(arg=nil)
|
88
|
+
set_or_return(:runtimes, arg, :default =>
|
89
|
+
if language == 'ruby' || language == 'chef'
|
90
|
+
['1.9.2']
|
91
|
+
else
|
92
|
+
[]
|
93
|
+
end)
|
94
|
+
end
|
95
|
+
|
96
|
+
def install(arg=nil)
|
97
|
+
set_or_return(:install, arg,
|
98
|
+
:default => language == 'ruby' ? 'bundle install' : '')
|
99
|
+
end
|
100
|
+
|
101
|
+
def script(arg=nil)
|
102
|
+
set_or_return(:script, arg, :default => 'rspec spec')
|
103
|
+
end
|
104
|
+
|
105
|
+
def memory(arg=nil)
|
106
|
+
set_or_return(:memory, arg, {})
|
107
|
+
end
|
108
|
+
|
109
|
+
def specs(arg=nil)
|
110
|
+
set_or_return(:specs, arg, {:default => true})
|
111
|
+
end
|
112
|
+
|
113
|
+
def features(arg=nil)
|
114
|
+
set_or_return(:features, arg, {:default => true})
|
115
|
+
end
|
116
|
+
|
117
|
+
def root_path
|
118
|
+
return @root_path if defined?(@root_path)
|
119
|
+
|
120
|
+
root_finder = lambda do |path|
|
121
|
+
found = PROJECT_ROOT_INDICATORS.find do |rootfile|
|
122
|
+
File.exist?(File.join(path.to_s, rootfile))
|
123
|
+
end
|
124
|
+
|
125
|
+
return path if found
|
126
|
+
return nil if path.root? || !File.exist?(path)
|
127
|
+
root_finder.call(path.parent)
|
128
|
+
end
|
129
|
+
|
130
|
+
@root_path = root_finder.call(Pathname.new(Dir.pwd))
|
131
|
+
end
|
132
|
+
|
133
|
+
def update_code_command
|
134
|
+
"rsync -aHv --update --progress --checksum #{guest_source_root}/ #{guest_test_root}"
|
135
|
+
end
|
136
|
+
|
137
|
+
def preflight_command
|
138
|
+
nil
|
139
|
+
end
|
140
|
+
|
141
|
+
def install_command(runtime=nil)
|
142
|
+
raise NotImplementedError
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_command(runtime=nil)
|
146
|
+
raise NotImplementedError
|
147
|
+
end
|
148
|
+
|
149
|
+
def to_hash
|
150
|
+
self.runtimes # hack
|
151
|
+
hash = {}
|
152
|
+
self.instance_variables.each do |var|
|
153
|
+
hash[var[1..-1].to_sym] = self.instance_variable_get(var)
|
154
|
+
end
|
155
|
+
hash
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2012 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module TestKitchen
|
20
|
+
module Project
|
21
|
+
class Cookbook < Ruby
|
22
|
+
|
23
|
+
include CookbookCopy
|
24
|
+
include SupportedPlatforms
|
25
|
+
|
26
|
+
attr_writer :lint
|
27
|
+
attr_writer :supported_platforms
|
28
|
+
|
29
|
+
def lint(arg=nil)
|
30
|
+
set_or_return(:lint, arg, {:default => true})
|
31
|
+
end
|
32
|
+
|
33
|
+
def run_list
|
34
|
+
super + ['recipe[minitest-handler]']
|
35
|
+
end
|
36
|
+
|
37
|
+
def preflight_command(cmd = nil)
|
38
|
+
return nil unless lint
|
39
|
+
parent_dir = File.join(root_path, '..')
|
40
|
+
set_or_return(:preflight_command, cmd, :default =>
|
41
|
+
"knife cookbook test -o #{parent_dir} #{name}" +
|
42
|
+
" && foodcritic -f ~FC007 -f correctness #{root_path}")
|
43
|
+
end
|
44
|
+
|
45
|
+
def script(arg=nil)
|
46
|
+
set_or_return(:script, arg, :default =>
|
47
|
+
%Q{if [ -d "features" ]; then bundle exec cucumber -t @#{tests_tag} features; fi})
|
48
|
+
end
|
49
|
+
|
50
|
+
def install_command(runtime=nil)
|
51
|
+
super(runtime, File.join(guest_test_root, 'test'))
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_command(runtime=nil)
|
55
|
+
super(runtime, File.join(guest_test_root, 'test'))
|
56
|
+
end
|
57
|
+
|
58
|
+
def supported_platforms
|
59
|
+
@supported_platforms ||= extract_supported_platforms(
|
60
|
+
File.read(File.join(root_path, 'metadata.rb')))
|
61
|
+
end
|
62
|
+
|
63
|
+
def non_buildable_platforms(platform_names)
|
64
|
+
supported_platforms.sort - platform_names.map do |platform|
|
65
|
+
platform.split('-').first
|
66
|
+
end.sort.uniq
|
67
|
+
end
|
68
|
+
|
69
|
+
def each_build(platforms, active_config=nil, &block)
|
70
|
+
if supported_platforms.empty?
|
71
|
+
super(platforms, active_config, &block)
|
72
|
+
else
|
73
|
+
super(platforms.select do |platform|
|
74
|
+
supported_platforms.any? do |supported|
|
75
|
+
platform.start_with?("#{supported}-")
|
76
|
+
end
|
77
|
+
end, active_config, &block)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def cookbook_path(root_path, tmp_path)
|
82
|
+
@cookbook_path ||= copy_cookbook_under_test(root_path, tmp_path)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Andrew Crump (<andrew@kotirisoftware.com>)
|
3
|
+
# Copyright:: Copyright (c) 2012 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module TestKitchen
|
20
|
+
module Project
|
21
|
+
module CookbookCopy
|
22
|
+
|
23
|
+
# This is a workaround to allow the top-level containing cookbook
|
24
|
+
# to be copied to the kitchen tmp subdirectory.
|
25
|
+
def copy_cookbook_under_test(root_path, tmp_path)
|
26
|
+
cookbook_path = root_path.parent.parent
|
27
|
+
source_paths = source_paths_excluding_test_dir(cookbook_path)
|
28
|
+
dest_path = File.join(tmp_path, 'cookbook_under_test')
|
29
|
+
copy_paths(source_paths, dest_path,
|
30
|
+
destination_paths(cookbook_path, source_paths, dest_path))
|
31
|
+
dest_path
|
32
|
+
end
|
33
|
+
|
34
|
+
def source_paths_excluding_test_dir(cookbook_path)
|
35
|
+
paths_from = Find.find(cookbook_path).reject do |path|
|
36
|
+
Find.prune if ['.git', 'test'].map do |dir|
|
37
|
+
File.join(cookbook_path, dir)
|
38
|
+
end.include?(path)
|
39
|
+
end.drop(1)
|
40
|
+
end
|
41
|
+
|
42
|
+
def destination_paths(cookbook_path, paths_from, dest_path)
|
43
|
+
paths_from.map do |file|
|
44
|
+
File.join(dest_path,
|
45
|
+
file.to_s.sub(%r{^#{Regexp.escape(cookbook_path.to_s)}/}, ''))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def copy_paths(source_paths, dest_path, dest_paths)
|
50
|
+
FileUtils.mkdir_p(dest_path)
|
51
|
+
source_paths.each_with_index do |from_path, index|
|
52
|
+
FileUtils.cp_r(from_path, dest_paths[index])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2012 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module TestKitchen
|
20
|
+
module Project
|
21
|
+
class Ruby < Base
|
22
|
+
|
23
|
+
def install_command(runtime=nil, test_path=guest_test_root)
|
24
|
+
cmd = "cd #{test_path}"
|
25
|
+
cmd << " && rvm use #{runtime}" if runtime
|
26
|
+
cmd << " && gem install bundler"
|
27
|
+
cmd << " && #{install}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_command(runtime=nil, test_path=guest_test_root)
|
31
|
+
cmd = "cd #{test_path}"
|
32
|
+
cmd << " && rvm use #{runtime}" if runtime
|
33
|
+
cmd << " && #{script}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Andrew Crump (<andrew@kotirisoftware.com>)
|
3
|
+
# Copyright:: Copyright (c) 2012 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module TestKitchen
|
20
|
+
module Project
|
21
|
+
module SupportedPlatforms
|
22
|
+
|
23
|
+
def extract_supported_platforms(metadata)
|
24
|
+
raise ArgumentError, "Metadata must be provided" unless metadata
|
25
|
+
ast = parse_ruby(metadata)
|
26
|
+
supports = find_nodes(ast, [:command]).reject do |command|
|
27
|
+
find_nodes(command, [:@ident, 'supports']).empty?
|
28
|
+
end
|
29
|
+
string_literals(supports) + word_list(ast, supports)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def parse_ruby(ruby_str)
|
35
|
+
Ripper::SexpBuilder.new(ruby_str).parse
|
36
|
+
end
|
37
|
+
|
38
|
+
def word_list(ast, nodes)
|
39
|
+
nodes.map do |node|
|
40
|
+
var_name = find_nodes(find_nodes(node, [:var_ref]), [:@ident]).flatten
|
41
|
+
if var_name.length > 1
|
42
|
+
add_block = find_nodes(ast, [:method_add_block]).reject do |n|
|
43
|
+
find_nodes(n, [:@ident, "supports"]).empty?
|
44
|
+
end
|
45
|
+
unless find_nodes(find_nodes(add_block, [:do_block]),
|
46
|
+
[:@ident, var_name[1]]).flatten.empty?
|
47
|
+
|
48
|
+
find_nodes(find_nodes(add_block,
|
49
|
+
[:qwords_add]), [:@tstring_content]).uniq.map do |str|
|
50
|
+
str[1] if str.length > 1
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end.flatten.compact
|
56
|
+
end
|
57
|
+
|
58
|
+
def string_literals(nodes)
|
59
|
+
nodes.map do |node|
|
60
|
+
tstring = find_nodes(node, [:@tstring_content]).find{|n| ! n.empty?}
|
61
|
+
tstring && tstring.length > 1 ? tstring[1] : nil
|
62
|
+
end.compact.flatten
|
63
|
+
end
|
64
|
+
|
65
|
+
def find_nodes(ast, node, result=[])
|
66
|
+
if ast.respond_to?(:each)
|
67
|
+
result << ast if ast.size > 1 and ast[0..(node.size - 1)] == node
|
68
|
+
ast.each { |child| find_nodes(child, node, result) }
|
69
|
+
end
|
70
|
+
result
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2012 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'test-kitchen/runner/base'
|
20
|
+
require 'test-kitchen/runner/vagrant'
|
@@ -0,0 +1,144 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2012 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'librarian/chef/cli'
|
20
|
+
|
21
|
+
module TestKitchen
|
22
|
+
module Runner
|
23
|
+
class TestFailureError < StandardError; end
|
24
|
+
class Base
|
25
|
+
|
26
|
+
attr_accessor :platform
|
27
|
+
attr_accessor :configuration
|
28
|
+
attr_accessor :env
|
29
|
+
|
30
|
+
def initialize(env, options={})
|
31
|
+
raise ArgumentError, "Environment cannot be nil" if env.nil?
|
32
|
+
@env = env
|
33
|
+
@platform = options[:platform]
|
34
|
+
@configuration = options[:configuration]
|
35
|
+
end
|
36
|
+
|
37
|
+
def provision
|
38
|
+
assemble_cookbooks!
|
39
|
+
end
|
40
|
+
|
41
|
+
def run_list
|
42
|
+
['test-kitchen::default']
|
43
|
+
end
|
44
|
+
|
45
|
+
def preflight_check
|
46
|
+
if env.project.preflight_command
|
47
|
+
system(env.project.preflight_command)
|
48
|
+
unless $?.success?
|
49
|
+
env.ui.info('Your cookbook had lint failures.', :red)
|
50
|
+
exit $?.exitstatus
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test
|
56
|
+
runtimes = configuration.runtimes
|
57
|
+
runtimes.each do |runtime|
|
58
|
+
message = "Synchronizing latest code from source root => test root."
|
59
|
+
execute_remote_command(platform, configuration.update_code_command, message)
|
60
|
+
|
61
|
+
message = "Updating dependencies for [#{configuration.name}]"
|
62
|
+
message << " under [#{runtime}]" if runtime
|
63
|
+
execute_remote_command(platform, configuration.install_command(runtime), message)
|
64
|
+
|
65
|
+
message = "Running tests for [#{configuration.name}]"
|
66
|
+
message << " under [#{runtime}]" if runtime
|
67
|
+
exit_code = execute_remote_command(platform, configuration.test_command(runtime), message)
|
68
|
+
raise TestFailureError unless exit_code == 0
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def status
|
73
|
+
raise NotImplementedError
|
74
|
+
end
|
75
|
+
|
76
|
+
def destroy
|
77
|
+
raise NotImplementedError
|
78
|
+
end
|
79
|
+
|
80
|
+
def ssh
|
81
|
+
raise NotImplementedError
|
82
|
+
end
|
83
|
+
|
84
|
+
def execute_remote_command(platform, command, mesage=nil)
|
85
|
+
raise NotImplementedError
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.inherited(subclass)
|
89
|
+
key = subclass.to_s.split('::').last.downcase
|
90
|
+
Runner.targets[key] = subclass
|
91
|
+
end
|
92
|
+
|
93
|
+
protected
|
94
|
+
|
95
|
+
def assemble_cookbooks!
|
96
|
+
# dump out a meta Cheffile
|
97
|
+
env.create_tmp_file('Cheffile',
|
98
|
+
IO.read(TestKitchen.source_root.join('config', 'Cheffile')))
|
99
|
+
|
100
|
+
env.ui.info("Assembling required cookbooks at [#{env.tmp_path.join('cookbooks')}].", :yellow)
|
101
|
+
|
102
|
+
# The following is a programatic version of `librarian-chef install`
|
103
|
+
Librarian::Action::Clean.new(librarian_env).run
|
104
|
+
Librarian::Action::Resolve.new(librarian_env).run
|
105
|
+
Librarian::Action::Install.new(librarian_env).run
|
106
|
+
end
|
107
|
+
|
108
|
+
def librarian_env
|
109
|
+
@librarian_env ||= Librarian::Chef::Environment.new(:project_path => env.tmp_path)
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_recipe_name
|
113
|
+
["#{env.project.name}_test", env.project.name].map do |cookbook_name|
|
114
|
+
if cookbook_exists?(cookbook_name)
|
115
|
+
cookbook_name + '::' + (if ! configuration || env.project.name == configuration.name
|
116
|
+
'default'
|
117
|
+
else
|
118
|
+
configuration.name
|
119
|
+
end)
|
120
|
+
end
|
121
|
+
end.compact.first
|
122
|
+
end
|
123
|
+
|
124
|
+
def cookbook_exists?(name)
|
125
|
+
env.cookbook_paths.any?{|path| Dir.exists?(File.join(path, name)) }
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.targets
|
131
|
+
@@targets ||= {}
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.for_platform(env, options)
|
135
|
+
desired_platform = env.all_platforms[options[:platform]]
|
136
|
+
if desired_platform.box_url
|
137
|
+
TestKitchen::Runner.targets['vagrant'].new(env, options)
|
138
|
+
else
|
139
|
+
raise ArgumentError,
|
140
|
+
"No runner available for platform: #{desired_platform.name}"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|