cucumber-chef 2.1.0.rc.1 → 2.1.0.rc.2
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/cc-knife +1 -1
- data/bin/cc-push +9 -14
- data/bin/cc-server +2 -3
- data/bin/cucumber-chef +111 -47
- data/chef_repo/cookbooks/cucumber-chef/recipes/test_lab.rb +2 -1
- data/cucumber-chef.gemspec +12 -4
- data/lib/cucumber/chef/bootstrap.rb +4 -3
- data/lib/cucumber/chef/config.rb +32 -17
- data/lib/cucumber/chef/helpers/chef_client.rb +6 -9
- data/lib/cucumber/chef/helpers/command.rb +1 -1
- data/lib/cucumber/chef/helpers/container.rb +5 -12
- data/lib/cucumber/chef/provider.rb +102 -0
- data/lib/cucumber/chef/providers/aws.rb +294 -0
- data/lib/cucumber/chef/providers/vagrant.rb +121 -0
- data/lib/cucumber/chef/provisioner.rb +32 -29
- data/lib/cucumber/chef/server.rb +133 -0
- data/lib/cucumber/chef/steps/ssh_steps.rb +23 -8
- data/lib/cucumber/chef/templates/bootstrap/ubuntu-precise-test-lab.erb +1 -1
- data/lib/cucumber/chef/templates/cucumber/cc-hooks.rb +8 -68
- data/lib/cucumber/chef/test_lab.rb +20 -309
- data/lib/cucumber/chef/utility.rb +109 -41
- data/lib/cucumber/chef/version.rb +1 -1
- data/lib/cucumber/chef.rb +5 -0
- metadata +42 -22
@@ -0,0 +1,102 @@
|
|
1
|
+
################################################################################
|
2
|
+
#
|
3
|
+
# Author: Zachary Patten <zachary@jovelabs.com>
|
4
|
+
# Copyright: Copyright (c) 2011-2013 Atalanta Systems Ltd
|
5
|
+
# License: Apache License, Version 2.0
|
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
|
+
################################################################################
|
20
|
+
|
21
|
+
require 'cucumber/chef/providers/aws'
|
22
|
+
require 'cucumber/chef/providers/vagrant'
|
23
|
+
|
24
|
+
module Cucumber
|
25
|
+
module Chef
|
26
|
+
|
27
|
+
class ProviderError < Error; end
|
28
|
+
|
29
|
+
class Provider
|
30
|
+
attr_accessor :stdout, :stderr, :stdin, :logger
|
31
|
+
|
32
|
+
PROXY_METHODS = %w(create destroy up down status lab_exists? labs labs_running labs_shutdown id state username ip port chef_server_webui)
|
33
|
+
|
34
|
+
################################################################################
|
35
|
+
|
36
|
+
def initialize(stdout=STDOUT, stderr=STDERR, stdin=STDIN, logger=$logger)
|
37
|
+
@stdout, @stderr, @stdin, @logger = stdout, stderr, stdin, logger
|
38
|
+
@stdout.sync = true if @stdout.respond_to?(:sync=)
|
39
|
+
|
40
|
+
@provider = case Cucumber::Chef::Config[:provider]
|
41
|
+
when :aws then
|
42
|
+
Cucumber::Chef::Provider::AWS.new(@stdout, @stderr, @stdin, @logger)
|
43
|
+
when :vagrant then
|
44
|
+
Cucumber::Chef::Provider::Vagrant.new(@stdout, @stderr, @stdin, @logger)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
################################################################################
|
49
|
+
|
50
|
+
def chef_server_webui
|
51
|
+
"http://#{ip}:4040/"
|
52
|
+
end
|
53
|
+
|
54
|
+
def chef_server_api
|
55
|
+
"http://#{ip}:4000/"
|
56
|
+
end
|
57
|
+
|
58
|
+
def status
|
59
|
+
if lab_exists?
|
60
|
+
details = {
|
61
|
+
"Provider" => @provider.class,
|
62
|
+
"ID" => self.id,
|
63
|
+
"State" => self.state,
|
64
|
+
"Username" => self.username,
|
65
|
+
"IP Address" => self.ip,
|
66
|
+
"Port" => self.port,
|
67
|
+
"Chef-Server API" => self.chef_server_api,
|
68
|
+
"Chef-Server WebUI" => self.chef_server_webui
|
69
|
+
}
|
70
|
+
max_key_length = details.collect{ |k,v| k.to_s.length }.max
|
71
|
+
details.each do |key,value|
|
72
|
+
@stdout.puts("%#{max_key_length}s: %s" % [key,value.inspect])
|
73
|
+
end
|
74
|
+
else
|
75
|
+
@stdout.puts("There are no cucumber-chef test labs to display information for!")
|
76
|
+
end
|
77
|
+
|
78
|
+
rescue Exception => e
|
79
|
+
Cucumber::Chef.logger.fatal { e.message }
|
80
|
+
Cucumber::Chef.logger.fatal { e.backtrace.join("\n") }
|
81
|
+
raise ProviderError, e.message
|
82
|
+
end
|
83
|
+
|
84
|
+
################################################################################
|
85
|
+
|
86
|
+
def method_missing(method_name, *method_args)
|
87
|
+
if Cucumber::Chef::Provider::PROXY_METHODS.include?(method_name.to_s)
|
88
|
+
Cucumber::Chef.logger.debug { "provider: #{method_name} #{method_args.inspect}" }
|
89
|
+
@provider.send(method_name.to_sym, *method_args)
|
90
|
+
else
|
91
|
+
super(method_name, *method_args)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
################################################################################
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
################################################################################
|
@@ -0,0 +1,294 @@
|
|
1
|
+
################################################################################
|
2
|
+
#
|
3
|
+
# Author: Zachary Patten <zachary@jovelabs.com>
|
4
|
+
# Copyright: Copyright (c) 2011-2013 Atalanta Systems Ltd
|
5
|
+
# License: Apache License, Version 2.0
|
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
|
+
################################################################################
|
20
|
+
|
21
|
+
module Cucumber
|
22
|
+
module Chef
|
23
|
+
class Provider
|
24
|
+
|
25
|
+
class AWSError < Error; end
|
26
|
+
|
27
|
+
class AWS
|
28
|
+
attr_accessor :stdout, :stderr, :stdin, :logger
|
29
|
+
|
30
|
+
INVALID_STATES = %w( terminated pending )
|
31
|
+
RUNNING_STATES = %w( running starting-up )
|
32
|
+
SHUTDOWN_STATES = %w( shutdown stopping stopped shutting-down )
|
33
|
+
VALID_STATES = RUNNING_STATES+SHUTDOWN_STATES
|
34
|
+
|
35
|
+
################################################################################
|
36
|
+
|
37
|
+
def initialize(stdout=STDOUT, stderr=STDERR, stdin=STDIN, logger=$logger)
|
38
|
+
@stdout, @stderr, @stdin, @logger = stdout, stderr, stdin, logger
|
39
|
+
@stdout.sync = true if @stdout.respond_to?(:sync=)
|
40
|
+
|
41
|
+
@connection = Fog::Compute.new(
|
42
|
+
:provider => 'AWS',
|
43
|
+
:aws_access_key_id => Cucumber::Chef::Config[:aws][:aws_access_key_id],
|
44
|
+
:aws_secret_access_key => Cucumber::Chef::Config[:aws][:aws_secret_access_key],
|
45
|
+
:region => Cucumber::Chef::Config[:aws][:region]
|
46
|
+
)
|
47
|
+
ensure_security_group
|
48
|
+
end
|
49
|
+
|
50
|
+
################################################################################
|
51
|
+
|
52
|
+
def create
|
53
|
+
if (lab_exists? && (@server = labs_running.first))
|
54
|
+
@stdout.puts("A test lab already exists using the AWS credentials you have supplied; attempting to reprovision it.")
|
55
|
+
else
|
56
|
+
server_definition = {
|
57
|
+
:image_id => Cucumber::Chef::Config.aws_image_id,
|
58
|
+
:groups => Cucumber::Chef::Config[:aws][:aws_security_group],
|
59
|
+
:flavor_id => Cucumber::Chef::Config[:aws][:aws_instance_type],
|
60
|
+
:key_name => Cucumber::Chef::Config[:aws][:aws_ssh_key_id],
|
61
|
+
:availability_zone => Cucumber::Chef::Config[:aws][:availability_zone],
|
62
|
+
:tags => { "purpose" => "cucumber-chef", "cucumber-chef-mode" => Cucumber::Chef::Config[:mode] },
|
63
|
+
:identity_file => Cucumber::Chef::Config[:aws][:identity_file]
|
64
|
+
}
|
65
|
+
if (@server = @connection.servers.create(server_definition))
|
66
|
+
@stdout.puts("Provisioning cucumber-chef test lab platform.")
|
67
|
+
|
68
|
+
@stdout.print("Waiting for instance...")
|
69
|
+
Cucumber::Chef.spinner do
|
70
|
+
@server.wait_for { ready? }
|
71
|
+
end
|
72
|
+
@stdout.puts("done.\n")
|
73
|
+
|
74
|
+
tag_server
|
75
|
+
|
76
|
+
@stdout.print("Waiting for 20 seconds...")
|
77
|
+
Cucumber::Chef.spinner do
|
78
|
+
sleep(20)
|
79
|
+
end
|
80
|
+
@stdout.print("done.\n")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
if @server
|
85
|
+
@stdout.print("Waiting for SSHD...")
|
86
|
+
Cucumber::Chef.spinner do
|
87
|
+
ZTK::TCPSocketCheck.new(:host => @server.public_ip_address, :port => 22, :wait => 120).wait
|
88
|
+
end
|
89
|
+
@stdout.puts("done.\n")
|
90
|
+
end
|
91
|
+
|
92
|
+
self
|
93
|
+
|
94
|
+
rescue Exception => e
|
95
|
+
Cucumber::Chef.logger.fatal { e.message }
|
96
|
+
Cucumber::Chef.logger.fatal { "Backtrace:\n#{e.backtrace.join("\n")}" }
|
97
|
+
raise AWSError, e.message
|
98
|
+
end
|
99
|
+
|
100
|
+
################################################################################
|
101
|
+
|
102
|
+
def destroy
|
103
|
+
if ((l = labs).count > 0)
|
104
|
+
@stdout.puts("Destroying Servers:")
|
105
|
+
l.each do |server|
|
106
|
+
@stdout.puts(" * #{server.public_ip_address}")
|
107
|
+
server.destroy
|
108
|
+
end
|
109
|
+
else
|
110
|
+
@stdout.puts("There are no cucumber-chef test labs to destroy!")
|
111
|
+
end
|
112
|
+
|
113
|
+
rescue Exception => e
|
114
|
+
Cucumber::Chef.logger.fatal { e.message }
|
115
|
+
Cucumber::Chef.logger.fatal { e.backtrace.join("\n") }
|
116
|
+
raise AWSError, e.message
|
117
|
+
end
|
118
|
+
|
119
|
+
################################################################################
|
120
|
+
|
121
|
+
def up
|
122
|
+
if (lab_exists? && (@server = labs_shutdown.first))
|
123
|
+
if @server.start
|
124
|
+
|
125
|
+
@stdout.print("Waiting for instance...")
|
126
|
+
Cucumber::Chef.spinner do
|
127
|
+
@server.wait_for { ready? }
|
128
|
+
end
|
129
|
+
@stdout.puts("done.\n")
|
130
|
+
|
131
|
+
@stdout.print("Waiting for SSHD...")
|
132
|
+
Cucumber::Chef.spinner do
|
133
|
+
ZTK::TCPSocketCheck.new(:host => @server.public_ip_address, :port => 22, :wait => 120).wait
|
134
|
+
end
|
135
|
+
@stdout.puts("done.\n")
|
136
|
+
|
137
|
+
@stdout.puts("Successfully started up cucumber-chef test lab!")
|
138
|
+
|
139
|
+
info
|
140
|
+
else
|
141
|
+
@stdout.puts("Failed to start up cucumber-chef test lab!")
|
142
|
+
end
|
143
|
+
else
|
144
|
+
@stdout.puts("There are no available cucumber-chef test labs to start up!")
|
145
|
+
end
|
146
|
+
|
147
|
+
rescue Exception => e
|
148
|
+
Cucumber::Chef.logger.fatal { e.message }
|
149
|
+
Cucumber::Chef.logger.fatal { e.backtrace.join("\n") }
|
150
|
+
raise AWSError, e.message
|
151
|
+
end
|
152
|
+
|
153
|
+
################################################################################
|
154
|
+
|
155
|
+
def down
|
156
|
+
if (lab_exists? && (@server = labs_running.first))
|
157
|
+
if @server.stop
|
158
|
+
@stdout.puts("Successfully shutdown cucumber-chef test lab!")
|
159
|
+
else
|
160
|
+
@stdout.puts("Failed to shutdown cucumber-chef test lab!")
|
161
|
+
end
|
162
|
+
else
|
163
|
+
@stdout.puts("There are no available cucumber-chef test labs top shutdown!")
|
164
|
+
end
|
165
|
+
|
166
|
+
rescue Exception => e
|
167
|
+
Cucumber::Chef.logger.fatal { e.message }
|
168
|
+
Cucumber::Chef.logger.fatal { e.backtrace.join("\n") }
|
169
|
+
raise AWSError, e.message
|
170
|
+
end
|
171
|
+
|
172
|
+
################################################################################
|
173
|
+
|
174
|
+
def id
|
175
|
+
labs_running.first.id
|
176
|
+
end
|
177
|
+
|
178
|
+
def state
|
179
|
+
labs_running.first.state
|
180
|
+
end
|
181
|
+
|
182
|
+
def username
|
183
|
+
labs_running.first.username
|
184
|
+
end
|
185
|
+
|
186
|
+
def ip
|
187
|
+
labs_running.first.public_ip_address
|
188
|
+
end
|
189
|
+
|
190
|
+
def port
|
191
|
+
22
|
192
|
+
end
|
193
|
+
|
194
|
+
################################################################################
|
195
|
+
|
196
|
+
def lab_exists?
|
197
|
+
(labs.size > 0)
|
198
|
+
end
|
199
|
+
|
200
|
+
################################################################################
|
201
|
+
|
202
|
+
def labs
|
203
|
+
@servers ||= @connection.servers
|
204
|
+
results = @servers.select do |server|
|
205
|
+
Cucumber::Chef.logger.debug("candidate") { "ID=#{server.id}, state='#{server.state}'" }
|
206
|
+
( server.tags['cucumber-chef-mode'] == Cucumber::Chef::Config[:mode].to_s &&
|
207
|
+
server.tags['cucumber-chef-user'] == Cucumber::Chef::Config[:user].to_s &&
|
208
|
+
VALID_STATES.any?{ |state| state == server.state } )
|
209
|
+
end
|
210
|
+
results.each do |server|
|
211
|
+
Cucumber::Chef.logger.debug("results") { "ID=#{server.id}, state='#{server.state}'" }
|
212
|
+
end
|
213
|
+
results
|
214
|
+
end
|
215
|
+
|
216
|
+
################################################################################
|
217
|
+
|
218
|
+
def labs_running
|
219
|
+
@servers ||= @connection.servers
|
220
|
+
results = @servers.select do |server|
|
221
|
+
Cucumber::Chef.logger.debug("candidate") { "ID=#{server.id}, state='#{server.state}'" }
|
222
|
+
( server.tags['cucumber-chef-mode'] == Cucumber::Chef::Config[:mode].to_s &&
|
223
|
+
server.tags['cucumber-chef-user'] == Cucumber::Chef::Config[:user].to_s &&
|
224
|
+
RUNNING_STATES.any?{ |state| state == server.state } )
|
225
|
+
end
|
226
|
+
results.each do |server|
|
227
|
+
Cucumber::Chef.logger.debug("results") { "ID=#{server.id}, state='#{server.state}'" }
|
228
|
+
end
|
229
|
+
results
|
230
|
+
end
|
231
|
+
|
232
|
+
################################################################################
|
233
|
+
|
234
|
+
def labs_shutdown
|
235
|
+
@servers ||= @connection.servers
|
236
|
+
results = @servers.select do |server|
|
237
|
+
Cucumber::Chef.logger.debug("candidate") { "ID=#{server.id}, state='#{server.state}'" }
|
238
|
+
( server.tags['cucumber-chef-mode'] == Cucumber::Chef::Config[:mode].to_s &&
|
239
|
+
server.tags['cucumber-chef-user'] == Cucumber::Chef::Config[:user].to_s &&
|
240
|
+
SHUTDOWN_STATES.any?{ |state| state == server.state } )
|
241
|
+
end
|
242
|
+
results.each do |server|
|
243
|
+
Cucumber::Chef.logger.debug("results") { "ID=#{server.id}, state='#{server.state}'" }
|
244
|
+
end
|
245
|
+
results
|
246
|
+
end
|
247
|
+
|
248
|
+
|
249
|
+
################################################################################
|
250
|
+
private
|
251
|
+
################################################################################
|
252
|
+
|
253
|
+
def tag_server
|
254
|
+
{
|
255
|
+
"cucumber-chef-mode" => Cucumber::Chef::Config[:mode],
|
256
|
+
"cucumber-chef-user" => Cucumber::Chef::Config[:user],
|
257
|
+
"purpose" => "cucumber-chef"
|
258
|
+
}.each do |k, v|
|
259
|
+
tag = @connection.tags.new
|
260
|
+
tag.resource_id = @server.id
|
261
|
+
tag.key, tag.value = k, v
|
262
|
+
tag.save
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
################################################################################
|
267
|
+
|
268
|
+
def ensure_security_group
|
269
|
+
security_group_name = Cucumber::Chef::Config[:aws][:aws_security_group]
|
270
|
+
if (security_group = @connection.security_groups.get(security_group_name))
|
271
|
+
port_ranges = security_group.ip_permissions.collect{ |entry| entry["fromPort"]..entry["toPort"] }
|
272
|
+
security_group.authorize_port_range(22..22) if port_ranges.none?{ |port_range| port_range === 22 }
|
273
|
+
security_group.authorize_port_range(4000..4000) if port_ranges.none?{ |port_range| port_range === 4000 }
|
274
|
+
security_group.authorize_port_range(4040..4040) if port_ranges.none?{ |port_range| port_range === 4040 }
|
275
|
+
security_group.authorize_port_range(8787..8787) if port_ranges.none?{ |port_range| port_range === 8787 }
|
276
|
+
elsif (security_group = @connection.security_groups.new(:name => security_group_name, :description => "cucumber-chef test lab")).save
|
277
|
+
security_group.authorize_port_range(22..22)
|
278
|
+
security_group.authorize_port_range(4000..4000)
|
279
|
+
security_group.authorize_port_range(4040..4040)
|
280
|
+
security_group.authorize_port_range(8787..8787)
|
281
|
+
else
|
282
|
+
raise AWSError, "Could not find an existing or create a new AWS security group."
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
################################################################################
|
287
|
+
|
288
|
+
end
|
289
|
+
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
################################################################################
|
@@ -0,0 +1,121 @@
|
|
1
|
+
################################################################################
|
2
|
+
#
|
3
|
+
# Author: Zachary Patten <zachary@jovelabs.com>
|
4
|
+
# Copyright: Copyright (c) 2011-2013 Atalanta Systems Ltd
|
5
|
+
# License: Apache License, Version 2.0
|
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
|
+
################################################################################
|
20
|
+
|
21
|
+
module Cucumber
|
22
|
+
module Chef
|
23
|
+
class Provider
|
24
|
+
|
25
|
+
class VagrantError < Error; end
|
26
|
+
|
27
|
+
class Vagrant
|
28
|
+
attr_accessor :env, :vm, :stdout, :stderr, :stdin, :logger
|
29
|
+
|
30
|
+
################################################################################
|
31
|
+
|
32
|
+
def initialize(stdout=STDOUT, stderr=STDERR, stdin=STDIN, logger=$logger)
|
33
|
+
@stdout, @stderr, @stdin, @logger = stdout, stderr, stdin, logger
|
34
|
+
@stdout.sync = true if @stdout.respond_to?(:sync=)
|
35
|
+
|
36
|
+
# @env = ::Vagrant::Environment.new
|
37
|
+
@env = ::Vagrant::Environment.new(:ui_class => ::Vagrant::UI::Colored)
|
38
|
+
@vm = @env.primary_vm
|
39
|
+
end
|
40
|
+
|
41
|
+
################################################################################
|
42
|
+
|
43
|
+
def create
|
44
|
+
@stdout.puts("Provisioning cucumber-chef test lab platform.")
|
45
|
+
|
46
|
+
@stdout.print("Waiting for instance...")
|
47
|
+
Cucumber::Chef.spinner do
|
48
|
+
@env.cli("up")
|
49
|
+
end
|
50
|
+
@stdout.puts("done.\n")
|
51
|
+
|
52
|
+
@stdout.print("Waiting for SSHD...")
|
53
|
+
Cucumber::Chef.spinner do
|
54
|
+
ZTK::TCPSocketCheck.new(:host => self.ip, :port => 22, :wait => 120).wait
|
55
|
+
end
|
56
|
+
@stdout.puts("done.\n")
|
57
|
+
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def destroy
|
62
|
+
@env.cli("destroy", "--force")
|
63
|
+
end
|
64
|
+
|
65
|
+
def up
|
66
|
+
@env.cli("up")
|
67
|
+
end
|
68
|
+
|
69
|
+
def down
|
70
|
+
@env.cli("halt")
|
71
|
+
end
|
72
|
+
|
73
|
+
################################################################################
|
74
|
+
|
75
|
+
def id
|
76
|
+
@vm.name
|
77
|
+
end
|
78
|
+
|
79
|
+
def state
|
80
|
+
@vm.state
|
81
|
+
end
|
82
|
+
|
83
|
+
def username
|
84
|
+
@vm.config.ssh.username
|
85
|
+
end
|
86
|
+
|
87
|
+
def ip
|
88
|
+
@vm.config.ssh.host
|
89
|
+
end
|
90
|
+
|
91
|
+
def port
|
92
|
+
@vm.config.vm.forwarded_ports.select{ |fwd_port| (fwd_port[:name] == "ssh") }.first[:hostport].to_i
|
93
|
+
end
|
94
|
+
|
95
|
+
################################################################################
|
96
|
+
|
97
|
+
def lab_exists?
|
98
|
+
(@env.vms.count > 0)
|
99
|
+
end
|
100
|
+
|
101
|
+
def labs
|
102
|
+
[@env.primary_vm]
|
103
|
+
end
|
104
|
+
|
105
|
+
def labs_running
|
106
|
+
[@env.primary_vm]
|
107
|
+
end
|
108
|
+
|
109
|
+
def labs_shutdown
|
110
|
+
Array.new # @env.vms
|
111
|
+
end
|
112
|
+
|
113
|
+
################################################################################
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
################################################################################
|
@@ -32,26 +32,27 @@ module Cucumber
|
|
32
32
|
|
33
33
|
################################################################################
|
34
34
|
|
35
|
-
def initialize(
|
36
|
-
@
|
35
|
+
def initialize(test_lab, stdout=STDOUT, stderr=STDERR, stdin=STDIN)
|
36
|
+
@test_lab = test_lab
|
37
37
|
@stdout, @stderr, @stdin = stdout, stderr, stdin
|
38
38
|
@stdout.sync = true if @stdout.respond_to?(:sync=)
|
39
39
|
|
40
40
|
@ssh = ZTK::SSH.new(:stdout => @stdout, :stderr => @stderr, :stdin => @stdin)
|
41
|
-
@ssh.config.host_name = @
|
42
|
-
@ssh.config.
|
43
|
-
@ssh.config.
|
41
|
+
@ssh.config.host_name = @test_lab.ip
|
42
|
+
@ssh.config.port = @test_lab.port
|
43
|
+
@ssh.config.user = Cucumber::Chef.lab_user
|
44
|
+
@ssh.config.keys = Cucumber::Chef::Config[Cucumber::Chef::Config[:provider]][:identity_file]
|
44
45
|
|
45
46
|
# @command = Cucumber::Chef::Command.new(@stdout, @stderr, @stdin)
|
46
47
|
|
47
|
-
@cookbooks_path = File.
|
48
|
-
@roles_path = File.
|
48
|
+
@cookbooks_path = File.join(Cucumber::Chef.root_dir, "chef_repo", "cookbooks")
|
49
|
+
@roles_path = File.join(Cucumber::Chef.root_dir, "chef_repo", "roles")
|
49
50
|
end
|
50
51
|
|
51
52
|
################################################################################
|
52
53
|
|
53
54
|
def build
|
54
|
-
template_file = File.
|
55
|
+
template_file = File.join(Cucumber::Chef.root_dir, "lib", "cucumber", "chef", "templates", "bootstrap", "ubuntu-precise-test-lab.erb")
|
55
56
|
|
56
57
|
bootstrap(template_file)
|
57
58
|
wait_for_chef_server
|
@@ -79,21 +80,24 @@ module Cucumber
|
|
79
80
|
def bootstrap(template_file)
|
80
81
|
raise ProvisionerError, "You must have the environment variable 'USER' set." if !Cucumber::Chef::Config[:user]
|
81
82
|
|
82
|
-
@stdout.print("Bootstrapping
|
83
|
+
@stdout.print("Bootstrapping #{Cucumber::Chef::Config[:provider].upcase} instance...")
|
83
84
|
Cucumber::Chef.spinner do
|
84
85
|
attributes = {
|
85
86
|
"run_list" => "role[test_lab]",
|
86
87
|
"cucumber_chef" => {
|
87
88
|
"version" => Cucumber::Chef::VERSION,
|
88
89
|
"prerelease" => Cucumber::Chef::Config[:prerelease]
|
89
|
-
}
|
90
|
+
},
|
91
|
+
"lab_user" => Cucumber::Chef.lab_user,
|
92
|
+
"lxc_user" => Cucumber::Chef.lxc_user
|
90
93
|
}
|
91
94
|
|
92
95
|
bootstrap = Cucumber::Chef::Bootstrap.new(@stdout, @stderr, @stdin)
|
93
|
-
bootstrap.config[:host] = @
|
94
|
-
bootstrap.config[:
|
96
|
+
bootstrap.config[:host] = @test_lab.ip
|
97
|
+
bootstrap.config[:port] = @test_lab.port
|
98
|
+
bootstrap.config[:ssh_user] = Cucumber::Chef.lab_user
|
95
99
|
bootstrap.config[:use_sudo] = true
|
96
|
-
bootstrap.config[:identity_file] = Cucumber::Chef
|
100
|
+
bootstrap.config[:identity_file] = Cucumber::Chef.bootstrap_identity
|
97
101
|
bootstrap.config[:template_file] = template_file
|
98
102
|
bootstrap.config[:context][:hostname] = HOSTNAME
|
99
103
|
bootstrap.config[:context][:chef_server] = HOSTNAME
|
@@ -111,8 +115,8 @@ module Cucumber
|
|
111
115
|
def download_chef_credentials
|
112
116
|
@stdout.print("Downloading chef-server credentials...")
|
113
117
|
Cucumber::Chef.spinner do
|
114
|
-
local_path = Cucumber::Chef.
|
115
|
-
remote_path = File.join(
|
118
|
+
local_path = File.join(Cucumber::Chef.home_dir, Cucumber::Chef::Config[:provider].to_s)
|
119
|
+
remote_path = File.join(Cucumber::Chef.lab_user_home_dir, ".chef")
|
116
120
|
|
117
121
|
files = [ "#{Cucumber::Chef::Config[:user]}.pem", "validation.pem" ]
|
118
122
|
files.each do |file|
|
@@ -127,10 +131,10 @@ module Cucumber
|
|
127
131
|
def download_proxy_ssh_credentials
|
128
132
|
@stdout.print("Downloading container SSH credentials...")
|
129
133
|
Cucumber::Chef.spinner do
|
130
|
-
local_path = Cucumber::Chef.
|
131
|
-
remote_path = File.join(
|
134
|
+
local_path = File.join(Cucumber::Chef.home_dir, Cucumber::Chef::Config[:provider].to_s)
|
135
|
+
remote_path = File.join(Cucumber::Chef.lab_user_home_dir, ".ssh")
|
132
136
|
|
133
|
-
files = { "id_rsa" => "id_rsa-#{
|
137
|
+
files = { "id_rsa" => "id_rsa-#{@ssh.config.user}" }
|
134
138
|
files.each do |remote_file, local_file|
|
135
139
|
local = File.join(local_path, local_file)
|
136
140
|
File.exists?(local) and File.delete(local)
|
@@ -146,16 +150,15 @@ module Cucumber
|
|
146
150
|
def render_knife_rb
|
147
151
|
@stdout.print("Building 'cc-knife' configuration...")
|
148
152
|
Cucumber::Chef.spinner do
|
149
|
-
template_file = File.
|
150
|
-
knife_rb = File.expand_path(File.join(Cucumber::Chef.locate(:directory, ".cucumber-chef"), "knife.rb"))
|
153
|
+
template_file = File.join(Cucumber::Chef.root_dir, "lib", "cucumber", "chef", "templates", "cucumber-chef", "knife-rb.erb")
|
151
154
|
|
152
155
|
context = {
|
153
|
-
:chef_server => @
|
156
|
+
:chef_server => @test_lab.ip,
|
154
157
|
:librarian_chef => Cucumber::Chef::Config[:librarian_chef],
|
155
158
|
:user => Cucumber::Chef::Config[:user]
|
156
159
|
}
|
157
160
|
|
158
|
-
File.open(knife_rb, 'w') do |f|
|
161
|
+
File.open(Cucumber::Chef.knife_rb, 'w') do |f|
|
159
162
|
f.puts(ZTK::Template.render(template_file, context))
|
160
163
|
end
|
161
164
|
end
|
@@ -169,7 +172,7 @@ module Cucumber
|
|
169
172
|
@stdout.print("Uploading cucumber-chef cookbooks...")
|
170
173
|
|
171
174
|
Cucumber::Chef.spinner do
|
172
|
-
Cucumber::Chef.
|
175
|
+
Cucumber::Chef.load_chef_config
|
173
176
|
cookbook_repo = ::Chef::CookbookLoader.new(@cookbooks_path)
|
174
177
|
cookbook_repo.each do |name, cookbook|
|
175
178
|
Cucumber::Chef.logger.debug { "::Chef::CookbookUploader(#{name}) ATTEMPT" }
|
@@ -190,7 +193,7 @@ module Cucumber
|
|
190
193
|
@stdout.print("Uploading cucumber-chef test lab role...")
|
191
194
|
|
192
195
|
Cucumber::Chef.spinner do
|
193
|
-
Cucumber::Chef.
|
196
|
+
Cucumber::Chef.load_chef_config
|
194
197
|
::Chef::Config[:role_path] = @roles_path
|
195
198
|
[ "test_lab" ].each do |name|
|
196
199
|
role = ::Chef::Role.from_disk(name)
|
@@ -210,7 +213,7 @@ module Cucumber
|
|
210
213
|
@stdout.print("Tagging cucumber-chef test lab node...")
|
211
214
|
|
212
215
|
Cucumber::Chef.spinner do
|
213
|
-
Cucumber::Chef.
|
216
|
+
Cucumber::Chef.load_chef_config
|
214
217
|
node = ::Chef::Node.load(HOSTNAME)
|
215
218
|
[ Cucumber::Chef::Config[:mode].to_s, Cucumber::Chef::Config[:user].to_s ].each do |tag|
|
216
219
|
node.tags << tag
|
@@ -230,7 +233,7 @@ module Cucumber
|
|
230
233
|
@stdout.print("Setting up cucumber-chef test lab run list...")
|
231
234
|
|
232
235
|
Cucumber::Chef.spinner do
|
233
|
-
Cucumber::Chef.
|
236
|
+
Cucumber::Chef.load_chef_config
|
234
237
|
node = ::Chef::Node.load(HOSTNAME)
|
235
238
|
[ "role[test_lab]" ].each do |entry|
|
236
239
|
node.run_list << entry
|
@@ -260,13 +263,13 @@ module Cucumber
|
|
260
263
|
def wait_for_chef_server
|
261
264
|
@stdout.print("Waiting for Chef-Server...")
|
262
265
|
Cucumber::Chef.spinner do
|
263
|
-
ZTK::TCPSocketCheck.new(:host => @
|
266
|
+
ZTK::TCPSocketCheck.new(:host => @test_lab.ip, :port => 4000, :data => "GET", :wait => 120).wait
|
264
267
|
end
|
265
268
|
@stdout.puts("done.\n")
|
266
269
|
|
267
270
|
@stdout.print("Waiting for Chef-WebUI...")
|
268
271
|
Cucumber::Chef.spinner do
|
269
|
-
ZTK::TCPSocketCheck.new(:host => @
|
272
|
+
ZTK::TCPSocketCheck.new(:host => @test_lab.ip, :port => 4040, :data => "GET", :wait => 120).wait
|
270
273
|
end
|
271
274
|
@stdout.puts("done.\n")
|
272
275
|
end
|
@@ -284,7 +287,7 @@ module Cucumber
|
|
284
287
|
|
285
288
|
@stdout.print("Waiting for SSHD...")
|
286
289
|
Cucumber::Chef.spinner do
|
287
|
-
ZTK::TCPSocketCheck.new(:host => @
|
290
|
+
ZTK::TCPSocketCheck.new(:host => @test_lab.ip, :port => 22, :wait => 120).wait
|
288
291
|
end
|
289
292
|
@stdout.puts("done.\n")
|
290
293
|
|