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

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.
@@ -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 }