test-kitchen 1.1.1 → 1.2.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.
- checksums.yaml +4 -4
- data/.cane +5 -0
- data/.travis.yml +8 -3
- data/CHANGELOG.md +66 -0
- data/Guardfile +3 -1
- data/README.md +3 -1
- data/Rakefile +1 -16
- data/features/kitchen_command.feature +1 -0
- data/features/kitchen_driver_create_command.feature +1 -0
- data/features/kitchen_driver_discover_command.feature +1 -0
- data/features/kitchen_help_command.feature +16 -0
- data/features/kitchen_init_command.feature +2 -0
- data/features/kitchen_list_command.feature +42 -0
- data/features/support/env.rb +25 -0
- data/lib/kitchen.rb +0 -1
- data/lib/kitchen/busser.rb +2 -2
- data/lib/kitchen/cli.rb +80 -233
- data/lib/kitchen/command.rb +117 -0
- data/lib/kitchen/command/action.rb +44 -0
- data/lib/kitchen/command/console.rb +51 -0
- data/lib/kitchen/command/diagnose.rb +51 -0
- data/lib/kitchen/command/driver_discover.rb +72 -0
- data/lib/kitchen/command/list.rb +86 -0
- data/lib/kitchen/command/login.rb +42 -0
- data/lib/kitchen/command/sink.rb +53 -0
- data/lib/kitchen/command/test.rb +50 -0
- data/lib/kitchen/driver/ssh_base.rb +2 -1
- data/lib/kitchen/loader/yaml.rb +67 -29
- data/lib/kitchen/provisioner/base.rb +67 -4
- data/lib/kitchen/provisioner/chef_base.rb +50 -65
- data/lib/kitchen/provisioner/chef_solo.rb +3 -2
- data/lib/kitchen/provisioner/chef_zero.rb +11 -9
- data/lib/kitchen/provisioner/shell.rb +88 -0
- data/lib/kitchen/state_file.rb +7 -2
- data/lib/kitchen/util.rb +1 -1
- data/lib/kitchen/version.rb +1 -1
- data/spec/kitchen/loader/yaml_spec.rb +327 -13
- data/spec/spec_helper.rb +2 -7
- data/support/chef-client-zero.rb +1 -0
- data/templates/driver/README.md.erb +1 -1
- data/test-kitchen.gemspec +2 -2
- metadata +59 -46
@@ -0,0 +1,117 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2013, 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 'thread'
|
20
|
+
|
21
|
+
module Kitchen
|
22
|
+
|
23
|
+
module Command
|
24
|
+
|
25
|
+
# Base class for CLI commands.
|
26
|
+
#
|
27
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
28
|
+
class Base
|
29
|
+
|
30
|
+
include Logging
|
31
|
+
|
32
|
+
def initialize(cmd_args, cmd_options, options = {})
|
33
|
+
@args = cmd_args
|
34
|
+
@options = cmd_options
|
35
|
+
@action = options.fetch(:action, nil)
|
36
|
+
@help = options.fetch(:help, lambda { "No help provided" })
|
37
|
+
@config = options.fetch(:config, nil)
|
38
|
+
@loader = options.fetch(:loader, nil)
|
39
|
+
@shell = options.fetch(:shell)
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
attr_reader :args, :options, :help, :config, :shell, :action
|
45
|
+
|
46
|
+
def die(msg)
|
47
|
+
error "\n#{msg}\n\n"
|
48
|
+
help.call
|
49
|
+
exit 1
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_all_instances
|
53
|
+
result = @config.instances
|
54
|
+
|
55
|
+
if result.empty?
|
56
|
+
die "No instances defined"
|
57
|
+
else
|
58
|
+
result
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_filtered_instances(regexp)
|
63
|
+
result = begin
|
64
|
+
@config.instances.get(regexp) ||
|
65
|
+
@config.instances.get_all(/#{regexp}/)
|
66
|
+
rescue RegexpError => e
|
67
|
+
die "Invalid Ruby regular expression, " +
|
68
|
+
"you may need to single quote the argument. " +
|
69
|
+
"Please try again or consult http://rubular.com/ (#{e.message})"
|
70
|
+
end
|
71
|
+
result = Array(result)
|
72
|
+
|
73
|
+
if result.empty?
|
74
|
+
die "No instances for regex `#{regexp}', try running `kitchen list'"
|
75
|
+
else
|
76
|
+
result
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def logger
|
81
|
+
Kitchen.logger
|
82
|
+
end
|
83
|
+
|
84
|
+
def parse_subcommand(arg = nil)
|
85
|
+
arg == "all" ? get_all_instances : get_filtered_instances(arg)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Common module to execute a Kitchen action such as create, converge, etc.
|
90
|
+
#
|
91
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
92
|
+
module RunAction
|
93
|
+
|
94
|
+
def run_action(action, instances, *args)
|
95
|
+
concurrency = 1
|
96
|
+
if options[:concurrency]
|
97
|
+
concurrency = options[:concurrency] || instances.size
|
98
|
+
concurrency = instances.size if concurrency > instances.size
|
99
|
+
end
|
100
|
+
|
101
|
+
queue = Queue.new
|
102
|
+
instances.each {|i| queue << i }
|
103
|
+
concurrency.times { queue << nil }
|
104
|
+
|
105
|
+
threads = []
|
106
|
+
concurrency.times do
|
107
|
+
threads << Thread.new do
|
108
|
+
while instance = queue.pop
|
109
|
+
instance.public_send(action, *args)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
threads.map { |i| i.join }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2013, 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 'kitchen/command'
|
20
|
+
|
21
|
+
require 'benchmark'
|
22
|
+
|
23
|
+
module Kitchen
|
24
|
+
|
25
|
+
module Command
|
26
|
+
|
27
|
+
# Command to run a single action one or more instances.
|
28
|
+
#
|
29
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
30
|
+
class Action < Kitchen::Command::Base
|
31
|
+
|
32
|
+
include RunAction
|
33
|
+
|
34
|
+
def call
|
35
|
+
banner "Starting Kitchen (v#{Kitchen::VERSION})"
|
36
|
+
elapsed = Benchmark.measure do
|
37
|
+
results = parse_subcommand(args.first)
|
38
|
+
run_action(action, results)
|
39
|
+
end
|
40
|
+
banner "Kitchen is finished. #{Util.duration(elapsed.real)}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2013, 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 'kitchen/command'
|
20
|
+
|
21
|
+
module Kitchen
|
22
|
+
|
23
|
+
module Command
|
24
|
+
|
25
|
+
# Command to launch a Pry-based Kitchen console..
|
26
|
+
#
|
27
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
28
|
+
class Console < Kitchen::Command::Base
|
29
|
+
|
30
|
+
def call
|
31
|
+
require 'pry'
|
32
|
+
Pry.start(@config, :prompt => [prompt(">"), prompt("*")])
|
33
|
+
rescue LoadError => e
|
34
|
+
warn %{Make sure you have the pry gem installed. You can install it with:}
|
35
|
+
warn %{`gem install pry` or including 'gem "pry"' in your Gemfile.}
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def prompt(char)
|
42
|
+
proc { |target_self, nest_level, pry|
|
43
|
+
["[#{pry.input_array.size}] ",
|
44
|
+
"kc(#{Pry.view_clip(target_self.class)})",
|
45
|
+
"#{":#{nest_level}" unless nest_level.zero?}#{char} "
|
46
|
+
].join
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2013, 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 'kitchen/command'
|
20
|
+
require 'kitchen/diagnostic'
|
21
|
+
|
22
|
+
require 'yaml'
|
23
|
+
|
24
|
+
module Kitchen
|
25
|
+
|
26
|
+
module Command
|
27
|
+
|
28
|
+
# Command to log into to instance.
|
29
|
+
#
|
30
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
31
|
+
class Diagnose < Kitchen::Command::Base
|
32
|
+
|
33
|
+
def call
|
34
|
+
loader = if options[:all] || options[:loader]
|
35
|
+
@loader
|
36
|
+
else
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
instances = if options[:all] || options[:instances]
|
41
|
+
parse_subcommand(args.first)
|
42
|
+
else
|
43
|
+
[]
|
44
|
+
end
|
45
|
+
|
46
|
+
puts Kitchen::Diagnostic.new(
|
47
|
+
:loader => loader, :instances => instances).read.to_yaml
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2013, 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 'kitchen/command'
|
20
|
+
|
21
|
+
require 'rubygems/spec_fetcher'
|
22
|
+
require 'safe_yaml'
|
23
|
+
|
24
|
+
module Kitchen
|
25
|
+
|
26
|
+
module Command
|
27
|
+
|
28
|
+
# Command to discover drivers published on RubyGems.
|
29
|
+
#
|
30
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
31
|
+
class DriverDiscover < Kitchen::Command::Base
|
32
|
+
|
33
|
+
def call
|
34
|
+
specs = fetch_gem_specs.sort { |x, y| x[0] <=> y[0] }
|
35
|
+
specs = specs[0, 49].push(["...", "..."]) if specs.size > 49
|
36
|
+
specs = specs.unshift(["Gem Name", "Latest Stable Release"])
|
37
|
+
print_table(specs, :indent => 4)
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
def fetch_gem_specs
|
43
|
+
SafeYAML::OPTIONS[:suppress_warnings] = true
|
44
|
+
req = Gem::Requirement.default
|
45
|
+
dep = Gem::Deprecate.skip_during do
|
46
|
+
Gem::Dependency.new(/kitchen-/i, req)
|
47
|
+
end
|
48
|
+
fetcher = Gem::SpecFetcher.fetcher
|
49
|
+
|
50
|
+
specs = if fetcher.respond_to?(:find_matching)
|
51
|
+
fetch_gem_specs_pre_rubygems_2(fetcher, dep)
|
52
|
+
else
|
53
|
+
fetch_gem_specs_post_rubygems_2(fetcher, dep)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def fetch_gem_specs_post_rubygems_2(fetcher, dep)
|
58
|
+
specs = fetcher.spec_for_dependency(dep, false)
|
59
|
+
specs.first.map { |t| [t.first.name, t.first.version] }
|
60
|
+
end
|
61
|
+
|
62
|
+
def fetch_gem_specs_pre_rubygems_2(fetcher, dep)
|
63
|
+
specs = fetcher.find_matching(dep, false, false, false)
|
64
|
+
specs.map { |t| t.first }.map { |t| t[0, 2] }
|
65
|
+
end
|
66
|
+
|
67
|
+
def print_table(*args)
|
68
|
+
shell.print_table(*args)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2013, 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 'kitchen/command'
|
20
|
+
|
21
|
+
module Kitchen
|
22
|
+
|
23
|
+
module Command
|
24
|
+
|
25
|
+
# Command to list one or more instances.
|
26
|
+
#
|
27
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
28
|
+
class List < Kitchen::Command::Base
|
29
|
+
|
30
|
+
def call
|
31
|
+
result = parse_subcommand(args.first)
|
32
|
+
if options[:debug]
|
33
|
+
die "The --debug flag on the list subcommand is deprecated, " +
|
34
|
+
"please use `kitchen diagnose'."
|
35
|
+
elsif options[:bare]
|
36
|
+
puts Array(result).map { |i| i.name }.join("\n")
|
37
|
+
else
|
38
|
+
list_table(result)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def color_pad(string)
|
45
|
+
string + set_color("", :white)
|
46
|
+
end
|
47
|
+
|
48
|
+
def display_instance(instance)
|
49
|
+
[
|
50
|
+
color_pad(instance.name),
|
51
|
+
color_pad(instance.driver.name),
|
52
|
+
color_pad(instance.provisioner.name),
|
53
|
+
format_last_action(instance.last_action)
|
54
|
+
]
|
55
|
+
end
|
56
|
+
|
57
|
+
def format_last_action(last_action)
|
58
|
+
case last_action
|
59
|
+
when 'create' then set_color("Created", :cyan)
|
60
|
+
when 'converge' then set_color("Converged", :magenta)
|
61
|
+
when 'setup' then set_color("Set Up", :blue)
|
62
|
+
when 'verify' then set_color("Verified", :yellow)
|
63
|
+
when nil then set_color("<Not Created>", :red)
|
64
|
+
else set_color("<Unknown>", :white)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def list_table(result)
|
69
|
+
table = [
|
70
|
+
[set_color("Instance", :green), set_color("Driver", :green),
|
71
|
+
set_color("Provisioner", :green), set_color("Last Action", :green)]
|
72
|
+
]
|
73
|
+
table += Array(result).map { |i| display_instance(i) }
|
74
|
+
print_table(table)
|
75
|
+
end
|
76
|
+
|
77
|
+
def print_table(*args)
|
78
|
+
shell.print_table(*args)
|
79
|
+
end
|
80
|
+
|
81
|
+
def set_color(*args)
|
82
|
+
shell.set_color(*args)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2013, 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 'kitchen/command'
|
20
|
+
|
21
|
+
module Kitchen
|
22
|
+
|
23
|
+
module Command
|
24
|
+
|
25
|
+
# Command to log into to instance.
|
26
|
+
#
|
27
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
28
|
+
class Login < Kitchen::Command::Base
|
29
|
+
|
30
|
+
def call
|
31
|
+
results = parse_subcommand(args.first)
|
32
|
+
if results.size > 1
|
33
|
+
die "Argument `#{args.first}' returned multiple results:\n" +
|
34
|
+
results.map { |i| " * #{i.name}" }.join("\n")
|
35
|
+
end
|
36
|
+
instance = results.pop
|
37
|
+
|
38
|
+
instance.login
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|