cucumber-chef 2.1.0.rc.2 → 2.1.0.rc.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -23,45 +23,65 @@ module Cucumber::Chef::Helpers::Server
23
23
 
24
24
  ################################################################################
25
25
 
26
- def server_create(name, attributes={})
27
- if ((attributes[:persist] && @servers[name]) || (@servers[name] && @servers[name][:persist]))
28
- attributes = @servers[name]
29
- log("using existing attributes for container $#{name} #{server_tag(name)}$")
26
+ def server_init(name)
27
+ @containers[name] ||= Hash.new
28
+ end
29
+
30
+ ################################################################################
31
+
32
+ def server_delete(name)
33
+ @containers.delete(name)
34
+ end
35
+
36
+ ################################################################################
37
+
38
+ def server_set_attributes(name, attributes={})
39
+ @containers[name].merge!(attributes)
40
+ end
41
+
42
+ ################################################################################
43
+
44
+ def server_create(name)
45
+ server_init(name)
46
+
47
+ # if this is a new or non-persistent container destroy it
48
+ server_destroy(name) if !@containers[name][:persist]
49
+
50
+ attributes = @containers[name]
51
+ @containers[name] = {
52
+ :ip => generate_ip,
53
+ :mac => generate_mac,
54
+ :persist => true,
55
+ :distro => "ubuntu",
56
+ :release => "lucid",
57
+ :arch => detect_arch(attributes[:distro] || "ubuntu")
58
+ }.merge(attributes)
59
+
60
+ if server_running?(name)
61
+ logger.info { "Container '#{name}' is already running." }
30
62
  else
31
- if (container_exists?(name) && (ENV['DESTROY'] == "1"))
32
- server_destroy(name)
33
- end
34
- attributes = { :ip => generate_ip,
35
- :mac => generate_mac,
36
- :persist => true,
37
- :distro => "ubuntu",
38
- :release => "lucid",
39
- :arch => detect_arch(attributes[:distro] || "ubuntu") }.merge(attributes)
40
- end
41
- @servers = (@servers || Hash.new(nil)).merge(name => attributes)
42
- $current_server = @servers[name][:ip]
43
- if !server_running?(name)
44
- log("please wait, creating container $#{name} #{server_tag(name)}$")
63
+ logger.info { "Please wait, creating container {#{name.inspect} => #{server_tag(name)}}." }
45
64
  bm = ::Benchmark.realtime do
46
65
  test_lab_config_dhcpd
47
66
  container_config_network(name)
48
- container_create(name, @servers[name][:distro], @servers[name][:release], @servers[name][:arch])
67
+ container_create(name, @containers[name][:distro], @containers[name][:release], @containers[name][:arch])
49
68
  end
50
- log("container $#{name}$ creation took %0.4f seconds" % bm)
69
+ logger.info { "Container '#{name}' creation took %0.4f seconds." % bm }
51
70
 
52
71
  bm = ::Benchmark.realtime do
53
- ZTK::TCPSocketCheck.new(:host => @servers[name][:ip], :port => 22).wait
72
+ ZTK::TCPSocketCheck.new(:host => @containers[name][:ip], :port => 22).wait
54
73
  end
55
- log("container $#{name}$ SSHD responded after %0.4f seconds" % bm)
56
- else
57
- log("container $#{name}$ is already running")
74
+ logger.info { "Container '#{name}' SSHD responded after %0.4f seconds." % bm }
58
75
  end
76
+
77
+ save_containers
59
78
  end
60
79
 
61
80
  ################################################################################
62
81
 
63
82
  def server_destroy(name)
64
83
  container_destroy(name)
84
+ test_lab_config_dhcpd
65
85
  end
66
86
 
67
87
  ################################################################################
@@ -70,16 +90,10 @@ module Cucumber::Chef::Helpers::Server
70
90
  container_running?(name)
71
91
  end
72
92
 
73
- ################################################################################
74
-
75
- def servers
76
- containers
77
- end
78
-
79
93
  ################################################################################
80
94
 
81
95
  def server_tag(name)
82
- @servers[name].inspect.to_s
96
+ @containers[name].inspect.to_s
83
97
  end
84
98
 
85
99
  ################################################################################
@@ -27,7 +27,9 @@ module Cucumber::Chef::Helpers::TestLab
27
27
  dhcpd_config = File.join("/etc/dhcp/test-lab.conf")
28
28
  File.open(dhcpd_config, 'w') do |f|
29
29
  f.puts(Cucumber::Chef.generate_do_not_edit_warning("DHCPD Configuration"))
30
- @servers.each do |key, value|
30
+ @containers.each do |key, value|
31
+ next if [:mac, :ip].any?{ |z| value[z].nil? }
32
+
31
33
  f.puts
32
34
  f.puts("host #{key} {")
33
35
  f.puts(" hardware ethernet #{value[:mac]};")
@@ -35,8 +37,12 @@ module Cucumber::Chef::Helpers::TestLab
35
37
  f.puts(" ddns-hostname \"#{key}\";")
36
38
  f.puts("}")
37
39
  end
40
+ f.flush
41
+ f.close
38
42
  end
39
- command_run_local("/etc/init.d/isc-dhcp-server restart")
43
+
44
+ command_run_local("service isc-dhcp-server restart")
45
+ command_run_local("service bind9 restart")
40
46
  end
41
47
 
42
48
  ################################################################################
@@ -23,29 +23,8 @@ module Cucumber::Chef::Helpers::Utility
23
23
 
24
24
  ################################################################################
25
25
 
26
- def log(message)
27
- Cucumber::Chef.logger.info { message.gsub("$", "'") }
28
- return if !(ENV['VERBOSE'] == "1")
29
-
30
- pattern = [ "\033[0m\033[36m", "\033[1m" ]
31
-
32
- result = [ " \033[0m\033[34m[\033[1mCC\033[0m\033[34m] \033[36m" ]
33
- result << pattern.first
34
-
35
- sanity = message.split('').count{ |z| (z == "$") }
36
- raise "You have a log message with an odd number of highlight markup characters! '#{message}' -> (sanity=#{sanity.inspect}) " if (sanity.modulo(2) != 0)
37
-
38
- chunks = message.split("$")
39
- chunks.each_with_index do |chunk, index|
40
- result << pattern[index.modulo(pattern.length)]
41
- result << chunk
42
- end
43
- result << "\033[0m"
44
-
45
- STDOUT.puts(result.join)
46
- STDOUT.flush if STDOUT.respond_to?(:flush)
47
-
48
- true
26
+ def logger
27
+ Cucumber::Chef.logger
49
28
  end
50
29
 
51
30
  ################################################################################
@@ -29,7 +29,7 @@ module Cucumber
29
29
  class Provider
30
30
  attr_accessor :stdout, :stderr, :stdin, :logger
31
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)
32
+ PROXY_METHODS = %w(create destroy up halt reload status id state username ip port chef_server_api chef_server_webui alive? dead? exists?)
33
33
 
34
34
  ################################################################################
35
35
 
@@ -37,7 +37,7 @@ module Cucumber
37
37
  @stdout, @stderr, @stdin, @logger = stdout, stderr, stdin, logger
38
38
  @stdout.sync = true if @stdout.respond_to?(:sync=)
39
39
 
40
- @provider = case Cucumber::Chef::Config[:provider]
40
+ @provider = case Cucumber::Chef::Config.provider
41
41
  when :aws then
42
42
  Cucumber::Chef::Provider::AWS.new(@stdout, @stderr, @stdin, @logger)
43
43
  when :vagrant then
@@ -56,23 +56,26 @@ module Cucumber
56
56
  end
57
57
 
58
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])
59
+ if exists?
60
+
61
+ headers = [:provider, :id, :state, :username, :"ip address", :port, :"chef-server api", :"chef-server webui", :"chef-server default user", :"chef-server default password"]
62
+ results = ZTK::Report.new.list([nil], headers) do |noop|
63
+
64
+ OpenStruct.new(
65
+ :provider => @provider.class,
66
+ :id => self.id,
67
+ :state => self.state,
68
+ :username => self.username,
69
+ :"ip address" => self.ip,
70
+ :port => self.port,
71
+ :"chef-server api" => self.chef_server_api,
72
+ :"chef-server webui" => self.chef_server_webui,
73
+ :"chef-server default user" => "admin",
74
+ :"chef-server default password" => Cucumber::Chef::Config.chef[:admin_password]
75
+ )
73
76
  end
74
77
  else
75
- @stdout.puts("There are no cucumber-chef test labs to display information for!")
78
+ raise ProviderError, "No test labs exists!"
76
79
  end
77
80
 
78
81
  rescue Exception => e
@@ -85,8 +88,10 @@ module Cucumber
85
88
 
86
89
  def method_missing(method_name, *method_args)
87
90
  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)
91
+ result = @provider.send(method_name.to_sym, *method_args)
92
+ splat = [method_name, *method_args].flatten.compact
93
+ Cucumber::Chef.logger.debug { "provider: #{splat.inspect} -> #{result.inspect}" }
94
+ result
90
95
  else
91
96
  super(method_name, *method_args)
92
97
  end
@@ -25,11 +25,11 @@ module Cucumber
25
25
  class AWSError < Error; end
26
26
 
27
27
  class AWS
28
- attr_accessor :stdout, :stderr, :stdin, :logger
28
+ attr_accessor :connection, :server, :stdout, :stderr, :stdin, :logger
29
29
 
30
- INVALID_STATES = %w( terminated pending )
31
- RUNNING_STATES = %w( running starting-up )
32
- SHUTDOWN_STATES = %w( shutdown stopping stopped shutting-down )
30
+ INVALID_STATES = %w(terminated pending).map(&:to_sym)
31
+ RUNNING_STATES = %w(running starting-up).map(&:to_sym)
32
+ SHUTDOWN_STATES = %w(shutdown stopping stopped shutting-down).map(&:to_sym)
33
33
  VALID_STATES = RUNNING_STATES+SHUTDOWN_STATES
34
34
 
35
35
  ################################################################################
@@ -40,55 +40,42 @@ module Cucumber
40
40
 
41
41
  @connection = Fog::Compute.new(
42
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]
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
46
  )
47
47
  ensure_security_group
48
+
49
+ @server = filter_servers(@connection.servers, VALID_STATES)
48
50
  end
49
51
 
52
+ ################################################################################
53
+ # CREATE
50
54
  ################################################################################
51
55
 
52
56
  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.")
57
+ if (exists? && alive?)
58
+ @stdout.puts("A test lab already exists using the #{Cucumber::Chef::Config.provider.upcase} credentials you have supplied; attempting to reprovision it.")
55
59
  else
56
60
  server_definition = {
57
61
  :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]
62
+ :groups => Cucumber::Chef::Config.aws[:aws_security_group],
63
+ :flavor_id => Cucumber::Chef::Config.aws[:aws_instance_type],
64
+ :key_name => Cucumber::Chef::Config.aws[:aws_ssh_key_id],
65
+ :availability_zone => Cucumber::Chef::Config.aws[:availability_zone],
66
+ :tags => { "purpose" => "cucumber-chef", "cucumber-chef-mode" => Cucumber::Chef::Config.mode },
67
+ :identity_file => Cucumber::Chef::Config.aws[:identity_file]
64
68
  }
65
- if (@server = @connection.servers.create(server_definition))
66
- @stdout.puts("Provisioning cucumber-chef test lab platform.")
67
69
 
68
- @stdout.print("Waiting for instance...")
69
- Cucumber::Chef.spinner do
70
+ if (@server = @connection.servers.create(server_definition))
71
+ ZTK::Benchmark.bench(:message => "Creating #{Cucumber::Chef::Config.provider.upcase} instance", :mark => "completed in %0.4f seconds.", :stdout => @stdout) do
70
72
  @server.wait_for { ready? }
73
+ tag_server
74
+ ZTK::TCPSocketCheck.new(:host => self.ip, :port => self.port, :wait => 120).wait
71
75
  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
76
  end
82
77
  end
83
78
 
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
79
  self
93
80
 
94
81
  rescue Exception => e
@@ -97,17 +84,15 @@ module Cucumber
97
84
  raise AWSError, e.message
98
85
  end
99
86
 
87
+ ################################################################################
88
+ # DESTROY
100
89
  ################################################################################
101
90
 
102
91
  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
92
+ if exists?
93
+ @server.destroy
109
94
  else
110
- @stdout.puts("There are no cucumber-chef test labs to destroy!")
95
+ raise AWSError, "We could not find a test lab!"
111
96
  end
112
97
 
113
98
  rescue Exception => e
@@ -116,32 +101,39 @@ module Cucumber
116
101
  raise AWSError, e.message
117
102
  end
118
103
 
104
+ ################################################################################
105
+ # UP
119
106
  ################################################################################
120
107
 
121
108
  def up
122
- if (lab_exists? && (@server = labs_shutdown.first))
109
+ if (exists? && dead?)
123
110
  if @server.start
111
+ @server.wait_for { ready? }
112
+ ZTK::TCPSocketCheck.new(:host => self.ip, :port => self.port, :wait => 120).wait
113
+ else
114
+ raise AWSError, "Failed to boot the test lab!"
115
+ end
116
+ else
117
+ raise AWSError, "We could not find a powered off test lab."
118
+ end
124
119
 
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")
120
+ rescue Exception => e
121
+ Cucumber::Chef.logger.fatal { e.message }
122
+ Cucumber::Chef.logger.fatal { e.backtrace.join("\n") }
123
+ raise AWSError, e.message
124
+ end
136
125
 
137
- @stdout.puts("Successfully started up cucumber-chef test lab!")
126
+ ################################################################################
127
+ # HALT
128
+ ################################################################################
138
129
 
139
- info
140
- else
141
- @stdout.puts("Failed to start up cucumber-chef test lab!")
130
+ def halt
131
+ if (exists? && alive?)
132
+ if !@server.stop
133
+ raise AWSError, "Failed to halt the test lab!"
142
134
  end
143
135
  else
144
- @stdout.puts("There are no available cucumber-chef test labs to start up!")
136
+ raise AWSError, "We could not find a running test lab."
145
137
  end
146
138
 
147
139
  rescue Exception => e
@@ -150,17 +142,17 @@ module Cucumber
150
142
  raise AWSError, e.message
151
143
  end
152
144
 
145
+ ################################################################################
146
+ # RELOAD
153
147
  ################################################################################
154
148
 
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!")
149
+ def reload
150
+ if (exists? && alive?)
151
+ if !@server.restart
152
+ raise AWSError, "Failed to reload the test lab!"
161
153
  end
162
154
  else
163
- @stdout.puts("There are no available cucumber-chef test labs top shutdown!")
155
+ raise AWSError, "We could not find a running test lab."
164
156
  end
165
157
 
166
158
  rescue Exception => e
@@ -169,91 +161,68 @@ module Cucumber
169
161
  raise AWSError, e.message
170
162
  end
171
163
 
164
+ ################################################################################
165
+
166
+ def exists?
167
+ !!@server
168
+ end
169
+
170
+ def alive?
171
+ (exists? && RUNNING_STATES.include?(self.state))
172
+ end
173
+
174
+ def dead?
175
+ (exists? && SHUTDOWN_STATES.include?(self.state))
176
+ end
177
+
172
178
  ################################################################################
173
179
 
174
180
  def id
175
- labs_running.first.id
181
+ @server.id
176
182
  end
177
183
 
178
184
  def state
179
- labs_running.first.state
185
+ @server.state.to_sym
180
186
  end
181
187
 
182
188
  def username
183
- labs_running.first.username
189
+ @server.username
184
190
  end
185
191
 
186
192
  def ip
187
- labs_running.first.public_ip_address
193
+ @server.public_ip_address
188
194
  end
189
195
 
190
196
  def port
191
197
  22
192
198
  end
193
199
 
194
- ################################################################################
195
-
196
- def lab_exists?
197
- (labs.size > 0)
198
- end
199
200
 
200
201
  ################################################################################
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
-
202
+ private
216
203
  ################################################################################
217
204
 
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
- ################################################################################
205
+ def filter_servers(servers, states=VALID_STATES)
206
+ Cucumber::Chef.logger.debug("states") { states.collect{ |s| s.inspect }.join(", ") }
207
+ results = servers.select do |server|
208
+ Cucumber::Chef.logger.debug("candidate") { "id=#{server.id.inspect}, state=#{server.state.inspect}, tags=#{server.tags.inspect}" }
233
209
 
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 } )
210
+ ( server.tags['cucumber-chef-mode'] == Cucumber::Chef::Config.mode.to_s &&
211
+ server.tags['cucumber-chef-user'] == Cucumber::Chef::Config.user.to_s &&
212
+ states.any?{ |state| state.to_s == server.state } )
241
213
  end
242
214
  results.each do |server|
243
- Cucumber::Chef.logger.debug("results") { "ID=#{server.id}, state='#{server.state}'" }
215
+ Cucumber::Chef.logger.debug("results") { "id=#{server.id.inspect}, state=#{server.state.inspect}" }
244
216
  end
245
- results
217
+ results.first
246
218
  end
247
219
 
248
-
249
- ################################################################################
250
- private
251
220
  ################################################################################
252
221
 
253
222
  def tag_server
254
223
  {
255
- "cucumber-chef-mode" => Cucumber::Chef::Config[:mode],
256
- "cucumber-chef-user" => Cucumber::Chef::Config[:user],
224
+ "cucumber-chef-mode" => Cucumber::Chef::Config.mode,
225
+ "cucumber-chef-user" => Cucumber::Chef::Config.user,
257
226
  "purpose" => "cucumber-chef"
258
227
  }.each do |k, v|
259
228
  tag = @connection.tags.new
@@ -266,7 +235,7 @@ module Cucumber
266
235
  ################################################################################
267
236
 
268
237
  def ensure_security_group
269
- security_group_name = Cucumber::Chef::Config[:aws][:aws_security_group]
238
+ security_group_name = Cucumber::Chef::Config.aws[:aws_security_group]
270
239
  if (security_group = @connection.security_groups.get(security_group_name))
271
240
  port_ranges = security_group.ip_permissions.collect{ |entry| entry["fromPort"]..entry["toPort"] }
272
241
  security_group.authorize_port_range(22..22) if port_ranges.none?{ |port_range| port_range === 22 }