test-kitchen 0.6.0 → 0.7.0.beta.1
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/config/Cheffile +0 -7
- data/lib/test-kitchen/cli/destroy.rb +0 -6
- data/lib/test-kitchen/cli.rb +15 -1
- data/lib/test-kitchen/dsl.rb +5 -1
- data/lib/test-kitchen/environment.rb +2 -0
- data/lib/test-kitchen/platform.rb +16 -0
- data/lib/test-kitchen/project/base.rb +1 -1
- data/lib/test-kitchen/runner/base.rb +2 -0
- data/lib/test-kitchen/runner/openstack/dsl.rb +39 -0
- data/lib/test-kitchen/runner/openstack/environment.rb +141 -0
- data/lib/test-kitchen/runner/openstack.rb +147 -0
- data/lib/test-kitchen/runner.rb +1 -0
- data/lib/test-kitchen/scaffold.rb +1 -1
- data/lib/test-kitchen/version.rb +1 -1
- metadata +28 -9
data/config/Cheffile
CHANGED
@@ -21,13 +21,6 @@ require 'test-kitchen'
|
|
21
21
|
site 'http://community.opscode.com/api/v1'
|
22
22
|
|
23
23
|
# base test-kitchen cookbooks
|
24
|
-
cookbook 'apt', '1.4.6'
|
25
|
-
cookbook 'yum', '0.8.0'
|
26
|
-
cookbook 'build-essential', '1.1.0'
|
27
|
-
cookbook 'git', '1.0.0'
|
28
|
-
cookbook 'rvm',
|
29
|
-
:git => 'https://github.com/fnichol/chef-rvm.git',
|
30
|
-
:ref => 'c27a8942ed311ccce2c63c2e863201b049c70a0d'
|
31
24
|
cookbook 'test-kitchen',
|
32
25
|
:path => TestKitchen.source_root.join('cookbooks', 'test-kitchen').to_s
|
33
26
|
|
@@ -27,12 +27,6 @@ module TestKitchen
|
|
27
27
|
banner "kitchen destroy (options)"
|
28
28
|
|
29
29
|
def run
|
30
|
-
options = {
|
31
|
-
:platform => config[:platform],
|
32
|
-
:configuration => config[:configuration]
|
33
|
-
}
|
34
|
-
|
35
|
-
runner = TestKitchen::Runner.targets['vagrant'].new(env, options)
|
36
30
|
runner.destroy
|
37
31
|
end
|
38
32
|
|
data/lib/test-kitchen/cli.rb
CHANGED
@@ -54,6 +54,14 @@ module TestKitchen
|
|
54
54
|
:show_options => true,
|
55
55
|
:exit => 0
|
56
56
|
|
57
|
+
option :version,
|
58
|
+
:short => "-v",
|
59
|
+
:long => "--version",
|
60
|
+
:description => "Show Test Kitchen version",
|
61
|
+
:boolean => true,
|
62
|
+
:proc => lambda {|v| puts "test-kitchen: #{::TestKitchen::VERSION}"},
|
63
|
+
:exit => 0
|
64
|
+
|
57
65
|
attr_accessor :runner
|
58
66
|
attr_accessor :env
|
59
67
|
attr_accessor :ui
|
@@ -91,7 +99,7 @@ module TestKitchen
|
|
91
99
|
def runner
|
92
100
|
@runner ||= begin
|
93
101
|
# CLI option takes precedence, then project
|
94
|
-
runner_name = config[:runner] || env.project.runner ||
|
102
|
+
runner_name = config[:runner] || env.project.runner || env.default_runner
|
95
103
|
runner_class = TestKitchen::Runner.targets[runner_name]
|
96
104
|
runner = runner_class.new(env, config)
|
97
105
|
end
|
@@ -257,6 +265,12 @@ module TestKitchen
|
|
257
265
|
|
258
266
|
def print_help_and_exit(exitcode=1, fatal_message=nil)
|
259
267
|
$stderr.puts(fatal_message) if fatal_message
|
268
|
+
|
269
|
+
begin
|
270
|
+
self.parse_options
|
271
|
+
rescue OptionParser::InvalidOption => e
|
272
|
+
puts "#{e}\n"
|
273
|
+
end
|
260
274
|
puts self.opt_parser
|
261
275
|
puts
|
262
276
|
TestKitchen::CLI::Kitchen.list_commands
|
data/lib/test-kitchen/dsl.rb
CHANGED
@@ -15,10 +15,10 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
|
-
|
19
18
|
require 'hashr'
|
20
19
|
require 'test-kitchen/project'
|
21
20
|
require 'test-kitchen/platform'
|
21
|
+
require 'test-kitchen/runner/openstack/dsl'
|
22
22
|
|
23
23
|
module TestKitchen
|
24
24
|
module DSL
|
@@ -31,6 +31,10 @@ module TestKitchen
|
|
31
31
|
def platform(name, &block)
|
32
32
|
env.platforms[name.to_s] = Platform.new(name, &block)
|
33
33
|
end
|
34
|
+
|
35
|
+
def default_runner(name)
|
36
|
+
env.default_runner = name
|
37
|
+
end
|
34
38
|
end
|
35
39
|
module CookbookDSL
|
36
40
|
def cookbook(name, &block)
|
@@ -32,6 +32,7 @@ module TestKitchen
|
|
32
32
|
attr_reader :ui
|
33
33
|
attr_reader :kitchenfile_name
|
34
34
|
attr_accessor :project
|
35
|
+
attr_accessor :default_runner
|
35
36
|
|
36
37
|
KITCHEN_SUBDIRS = [".", "kitchen", "test/kitchen"]
|
37
38
|
|
@@ -47,6 +48,7 @@ module TestKitchen
|
|
47
48
|
@project = Project::Cookbook.new(File.basename(Dir.pwd))
|
48
49
|
end
|
49
50
|
|
51
|
+
@default_runner = "vagrant"
|
50
52
|
@tmp_path = root_path.join('.kitchen')
|
51
53
|
@cache_path = tmp_path.join('.cache')
|
52
54
|
@ui = options[:ui]
|
@@ -41,6 +41,8 @@ module TestKitchen
|
|
41
41
|
include Chef::Mixin::ParamsValidate
|
42
42
|
|
43
43
|
attr_reader :name
|
44
|
+
|
45
|
+
# Virtual Box Specific Attributes
|
44
46
|
attr_writer :box, :box_url
|
45
47
|
|
46
48
|
def initialize(name, &block)
|
@@ -49,6 +51,20 @@ module TestKitchen
|
|
49
51
|
instance_eval(&block) if block_given?
|
50
52
|
end
|
51
53
|
|
54
|
+
OPENSTACK_OPTIONS = {
|
55
|
+
:image_id => nil, :flavor_id => nil, :install_chef => false,
|
56
|
+
:install_chef_cmd => "curl -L http://www.opscode.com/chef/install.sh | sudo bash",
|
57
|
+
:keyname => nil, :instance_name => nil, :ssh_user => "root", :ssh_key => nil}
|
58
|
+
|
59
|
+
OPENSTACK_OPTIONS.each do |option, default|
|
60
|
+
attr_writer option
|
61
|
+
define_method(option) do |*args|
|
62
|
+
arg = args.first
|
63
|
+
set_or_return(option, arg, default.nil? ? {} : {:default => default})
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
52
68
|
def box(arg=nil)
|
53
69
|
set_or_return(:box, arg, {})
|
54
70
|
end
|
@@ -143,6 +143,8 @@ module TestKitchen
|
|
143
143
|
desired_platform = env.all_platforms[options[:platform]]
|
144
144
|
if desired_platform.box_url
|
145
145
|
TestKitchen::Runner.targets['vagrant'].new(env, options)
|
146
|
+
elsif desired_platform.image_id
|
147
|
+
TestKitchen::Runner.targets['openstack'].new(env, options)
|
146
148
|
else
|
147
149
|
raise ArgumentError,
|
148
150
|
"No runner available for platform: #{desired_platform.name}"
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'test-kitchen/runner/openstack/environment'
|
2
|
+
|
3
|
+
module TestKitchen
|
4
|
+
class Openstack
|
5
|
+
include Chef::Mixin::ParamsValidate
|
6
|
+
|
7
|
+
attr_writer :username, :password, :tenant, :auth_url
|
8
|
+
|
9
|
+
def initialize(&block)
|
10
|
+
instance_eval(&block) if block_given?
|
11
|
+
end
|
12
|
+
|
13
|
+
def username(arg=nil)
|
14
|
+
set_or_return(:username, arg, {})
|
15
|
+
end
|
16
|
+
|
17
|
+
def password(arg=nil)
|
18
|
+
set_or_return(:password, arg, {})
|
19
|
+
end
|
20
|
+
|
21
|
+
def tenant(arg=nil)
|
22
|
+
set_or_return(:tenant, arg, {})
|
23
|
+
end
|
24
|
+
|
25
|
+
def auth_url(arg=nil)
|
26
|
+
set_or_return(:auth_url, arg, {})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module TestKitchen
|
32
|
+
module DSL
|
33
|
+
module BasicDSL
|
34
|
+
def openstack(&block)
|
35
|
+
TestKitchen::Environment::Openstack.config = TestKitchen::Openstack.new(&block)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'test-kitchen/environment'
|
2
|
+
require 'json'
|
3
|
+
require 'fog'
|
4
|
+
|
5
|
+
module TestKitchen
|
6
|
+
class Environment
|
7
|
+
class Openstack < TestKitchen::Environment
|
8
|
+
attr_reader :username, :password, :tenant, :auth_url
|
9
|
+
attr_reader :servers
|
10
|
+
|
11
|
+
def initialize(conf={})
|
12
|
+
super
|
13
|
+
@username = conf[:username] || config.username
|
14
|
+
@password = conf[:password] || config.password
|
15
|
+
@tenant = conf[:tenant] || config.tenant
|
16
|
+
@auth_url = conf[:auth_url] || config.auth_url
|
17
|
+
@servers = {}
|
18
|
+
load
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_server(platform_name, server_def)
|
22
|
+
@servers[platform_name] ||=
|
23
|
+
begin
|
24
|
+
server = connection.servers.create({ :name => server_def[:instance_name],
|
25
|
+
:image_ref => server_def[:image_id],
|
26
|
+
:flavor_ref => server_def[:flavor_id],
|
27
|
+
:key_name => server_def[:keyname]})
|
28
|
+
server.wait_for { ready? }
|
29
|
+
sleep(2) until tcp_test_ssh(server.public_ip_address['addr'])
|
30
|
+
save
|
31
|
+
server
|
32
|
+
end
|
33
|
+
|
34
|
+
# These won't persist on the fog objectso we have to set them every
|
35
|
+
# time. :(
|
36
|
+
@servers[platform_name].username = server_def[:ssh_user]
|
37
|
+
if server_def[:ssh_key]
|
38
|
+
@servers[platform_name].private_key_path = File.expand_path(server_def[:ssh_key])
|
39
|
+
end
|
40
|
+
@servers[platform_name]
|
41
|
+
end
|
42
|
+
|
43
|
+
def tcp_test_ssh(hostname)
|
44
|
+
tcp_socket = TCPSocket.new(hostname, '22')
|
45
|
+
IO.select([tcp_socket], nil, nil, 5)
|
46
|
+
rescue SocketError, Errno::ETIMEDOUT, Errno::EPERM,
|
47
|
+
Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH
|
48
|
+
false
|
49
|
+
ensure
|
50
|
+
tcp_socket && tcp_socket.close
|
51
|
+
end
|
52
|
+
|
53
|
+
def connection
|
54
|
+
@connection ||= Fog::Compute.new(:provider => 'OpenStack',
|
55
|
+
:openstack_username => username,
|
56
|
+
:openstack_api_key => password,
|
57
|
+
:openstack_auth_url => auth_url,
|
58
|
+
:openstack_tenant => tenant)
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
# The following functions all take a name of
|
63
|
+
# of a VM in our enironment
|
64
|
+
|
65
|
+
def status(name)
|
66
|
+
if @servers.has_key?(name)
|
67
|
+
@servers[name].state.to_s.downcase
|
68
|
+
else
|
69
|
+
"not created"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def destroy(name)
|
74
|
+
@servers[name].destroy if @servers.has_key?(name)
|
75
|
+
@servers.delete(name)
|
76
|
+
save
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
# Ideally we could use the #ssh and #scp functions on Fog's server '
|
81
|
+
# object. But these seem to be broken in the case of Openstack
|
82
|
+
|
83
|
+
def ssh_options(name)
|
84
|
+
if key = @servers[name].private_key_path
|
85
|
+
{:keys => [key]}
|
86
|
+
else
|
87
|
+
{}
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def ssh(name)
|
92
|
+
server = @servers[name]
|
93
|
+
Fog::SSH.new(server.public_ip_address['addr'], server.username, ssh_options(name))
|
94
|
+
end
|
95
|
+
|
96
|
+
def scp(name)
|
97
|
+
server = @servers[name]
|
98
|
+
Fog::SCP.new(server.public_ip_address['addr'], server.username, ssh_options(name))
|
99
|
+
end
|
100
|
+
|
101
|
+
# GROSS: Global config as a class variable
|
102
|
+
def config
|
103
|
+
@@config
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.config
|
107
|
+
@@config
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.config=(config)
|
111
|
+
@@config = config
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
# Store state in .openstack_state file,
|
117
|
+
# allowing us to re-use already created VMs
|
118
|
+
|
119
|
+
def state_file
|
120
|
+
File.join(root_path, ".openstack_state")
|
121
|
+
end
|
122
|
+
|
123
|
+
def load
|
124
|
+
if File.exists?(state_file)
|
125
|
+
state = JSON.parse(File.read(state_file))
|
126
|
+
state.each do |platform, id|
|
127
|
+
@servers[platform] = connection.servers.get(id)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def save
|
133
|
+
state = {}
|
134
|
+
@servers.each {|k,s| state[k] = s.id}
|
135
|
+
File.open(state_file, 'w') do |f|
|
136
|
+
f.write(state.to_json)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Steven Danna (<steve@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 'fog'
|
20
|
+
require 'test-kitchen/runner/openstack/environment'
|
21
|
+
|
22
|
+
module TestKitchen
|
23
|
+
module Runner
|
24
|
+
class Openstack < Base
|
25
|
+
|
26
|
+
|
27
|
+
# @vm: The TestKitchen::Platform::Version object
|
28
|
+
#
|
29
|
+
# @platform: From the parent constructor, contains the full name
|
30
|
+
# of the relevant platform if we were created by #for_platform
|
31
|
+
|
32
|
+
attr_accessor :vm
|
33
|
+
|
34
|
+
def initialize(env, options={})
|
35
|
+
super
|
36
|
+
|
37
|
+
if @platform
|
38
|
+
@vm = env.all_platforms[@platform]
|
39
|
+
end
|
40
|
+
|
41
|
+
@os_env = TestKitchen::Environment::Openstack.new()
|
42
|
+
end
|
43
|
+
|
44
|
+
def create
|
45
|
+
env.ui.msg "[#{platform}] Provisioning guest on Openstack", :green
|
46
|
+
@os_env.create_server(@platform,
|
47
|
+
{ :instance_name => (vm.instance_name || "cookbook-tester-#{platform}"),
|
48
|
+
:image_id => vm.image_id,
|
49
|
+
:flavor_id => vm.flavor_id,
|
50
|
+
:keyname => vm.keyname,
|
51
|
+
:ssh_key => vm.ssh_key,
|
52
|
+
:ssh_user => vm.ssh_user})
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
def converge
|
57
|
+
install_chef if vm.install_chef
|
58
|
+
move_repo
|
59
|
+
move_cookbooks
|
60
|
+
run_chef_solo
|
61
|
+
end
|
62
|
+
|
63
|
+
# status and destroy are expected to operate on all
|
64
|
+
# vm's in an environment
|
65
|
+
def status
|
66
|
+
env.all_platforms.each do |name, ver|
|
67
|
+
env.ui.msg "#{name}\t#{@os_env.status(name)}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def destroy
|
72
|
+
env.all_platforms.each do |name, platform|
|
73
|
+
env.ui.msg "[#{name}] Terminating openstack server", :yellow
|
74
|
+
@os_env.destroy name
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def execute_remote_command(platform_name, command, message=nil)
|
79
|
+
env.ui.msg("[#{platform_name}] #{message}", :green) if message
|
80
|
+
results = @os_env.ssh(platform_name).run(command) do |data|
|
81
|
+
stdout, stderr = data.map {|s| s.rstrip}
|
82
|
+
stdout.lines.each do |line|
|
83
|
+
env.ui.msg "[#{platform_name}] #{line}", :green
|
84
|
+
end
|
85
|
+
stderr.lines.each do |line|
|
86
|
+
env.ui.msg "[#{platform_name}] #{line}", :red
|
87
|
+
end
|
88
|
+
end
|
89
|
+
if results.first.status != 0
|
90
|
+
msg = message || "Remote command"
|
91
|
+
env.ui.msg "[#{platform_name}] #{msg} failed!", :red
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def install_chef(name=platform)
|
98
|
+
execute_remote_command(name, vm.install_chef_cmd, "Installing Chef")
|
99
|
+
end
|
100
|
+
|
101
|
+
def run_chef_solo(name=platform)
|
102
|
+
execute_remote_command(name, "echo '#{json_for_node}' > node.json",
|
103
|
+
"Creating node configuration JSON")
|
104
|
+
execute_remote_command(name, "echo 'cookbook_path [ \"#{remote_cookbook_dir}\" ]' > solo.rb",
|
105
|
+
"Creating chef-solo configuration")
|
106
|
+
execute_remote_command(name, "sudo chef-solo -j node.json -c solo.rb",
|
107
|
+
"Running chef-solo on host")
|
108
|
+
end
|
109
|
+
|
110
|
+
def move_cookbooks(name=platform)
|
111
|
+
env.ui.msg("[#{name}] Moving cookbooks via SCP", :green)
|
112
|
+
@os_env.scp(name).upload(File.join(env.tmp_path, "cookbooks"),
|
113
|
+
remote_cookbook_dir, :recursive => true)
|
114
|
+
end
|
115
|
+
|
116
|
+
def move_repo(name=platform)
|
117
|
+
env.ui.msg("[#{name}] Moving repo via SCP", :green)
|
118
|
+
execute_remote_command(name, "sudo mkdir -p #{remote_root_dir}")
|
119
|
+
execute_remote_command(name, "sudo chown #{vm.ssh_user} #{remote_root_dir}")
|
120
|
+
@os_env.scp(name).upload(File.join(env.tmp_path, "cookbook_under_test"),
|
121
|
+
configuration.guest_source_root,
|
122
|
+
{:recursive => true})
|
123
|
+
end
|
124
|
+
|
125
|
+
def json_for_node
|
126
|
+
{
|
127
|
+
'test-kitchen' => {
|
128
|
+
'project' => configuration.to_hash.merge('source_root' => configuration.guest_source_root,
|
129
|
+
'test_root' => configuration.guest_test_root)},
|
130
|
+
'run_list' => run_list
|
131
|
+
}.to_json
|
132
|
+
end
|
133
|
+
|
134
|
+
def run_list
|
135
|
+
configuration.run_list + [test_recipe_name]
|
136
|
+
end
|
137
|
+
|
138
|
+
def remote_root_dir
|
139
|
+
File.dirname(configuration.guest_source_root)
|
140
|
+
end
|
141
|
+
|
142
|
+
def remote_cookbook_dir
|
143
|
+
File.join(remote_root_dir, 'cookbooks')
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
data/lib/test-kitchen/runner.rb
CHANGED
data/lib/test-kitchen/version.rb
CHANGED
metadata
CHANGED
@@ -1,32 +1,48 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: test-kitchen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.7.0.beta.1
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Seth Chisamore
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-11-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: fog
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: foodcritic
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
17
33
|
none: false
|
18
34
|
requirements:
|
19
|
-
- -
|
35
|
+
- - ! '>='
|
20
36
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
37
|
+
version: 1.4.0
|
22
38
|
type: :runtime
|
23
39
|
prerelease: false
|
24
40
|
version_requirements: !ruby/object:Gem::Requirement
|
25
41
|
none: false
|
26
42
|
requirements:
|
27
|
-
- -
|
43
|
+
- - ! '>='
|
28
44
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
45
|
+
version: 1.4.0
|
30
46
|
- !ruby/object:Gem::Dependency
|
31
47
|
name: hashr
|
32
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -161,6 +177,9 @@ files:
|
|
161
177
|
- lib/test-kitchen/project/supported_platforms.rb
|
162
178
|
- lib/test-kitchen/project.rb
|
163
179
|
- lib/test-kitchen/runner/base.rb
|
180
|
+
- lib/test-kitchen/runner/openstack/dsl.rb
|
181
|
+
- lib/test-kitchen/runner/openstack/environment.rb
|
182
|
+
- lib/test-kitchen/runner/openstack.rb
|
164
183
|
- lib/test-kitchen/runner/vagrant.rb
|
165
184
|
- lib/test-kitchen/runner.rb
|
166
185
|
- lib/test-kitchen/scaffold.rb
|
@@ -183,9 +202,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
183
202
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
184
203
|
none: false
|
185
204
|
requirements:
|
186
|
-
- - ! '
|
205
|
+
- - ! '>'
|
187
206
|
- !ruby/object:Gem::Version
|
188
|
-
version:
|
207
|
+
version: 1.3.1
|
189
208
|
requirements: []
|
190
209
|
rubyforge_project:
|
191
210
|
rubygems_version: 1.8.23
|