cucumber-chef 2.0.7 → 2.1.0.rc.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/README.md +1 -1
  2. data/Rakefile +1 -1
  3. data/bin/cc-knife +2 -5
  4. data/bin/cc-push +50 -26
  5. data/bin/cc-server +9 -10
  6. data/bin/cucumber-chef +65 -71
  7. data/chef_repo/cookbooks/cucumber-chef/attributes/default.rb +1 -1
  8. data/chef_repo/cookbooks/cucumber-chef/recipes/default.rb +1 -1
  9. data/chef_repo/cookbooks/cucumber-chef/recipes/lxc.rb +34 -36
  10. data/chef_repo/cookbooks/cucumber-chef/recipes/test_lab.rb +64 -47
  11. data/chef_repo/cookbooks/cucumber-chef/templates/default/solrconfig.erb +650 -0
  12. data/cucumber-chef.gemspec +5 -5
  13. data/lib/cucumber/chef/bootstrap.rb +10 -10
  14. data/lib/cucumber/chef/config.rb +15 -15
  15. data/lib/cucumber/chef/helpers/chef_client.rb +88 -14
  16. data/lib/cucumber/chef/helpers/chef_server.rb +39 -16
  17. data/lib/cucumber/chef/helpers/command.rb +28 -12
  18. data/lib/cucumber/chef/helpers/container.rb +29 -26
  19. data/lib/cucumber/chef/helpers/minitest.rb +1 -1
  20. data/lib/cucumber/chef/helpers/server.rb +37 -18
  21. data/lib/cucumber/chef/helpers/test_lab.rb +1 -1
  22. data/lib/cucumber/chef/helpers/utility.rb +23 -3
  23. data/lib/cucumber/chef/helpers.rb +10 -8
  24. data/lib/cucumber/chef/provisioner.rb +22 -21
  25. data/lib/cucumber/chef/steps/chef_steps.rb +1 -1
  26. data/lib/cucumber/chef/steps/minitest_steps.rb +3 -3
  27. data/lib/cucumber/chef/steps/provision_steps.rb +7 -6
  28. data/lib/cucumber/chef/steps/ssh_steps.rb +31 -2
  29. data/lib/cucumber/chef/steps.rb +1 -1
  30. data/lib/cucumber/chef/templates/cucumber/cc-hooks.rb +111 -0
  31. data/lib/cucumber/chef/templates/cucumber/env.rb +0 -87
  32. data/lib/cucumber/chef/templates/cucumber/readme-environments.erb +1 -0
  33. data/lib/cucumber/chef/templates/cucumber/readme-roles.erb +1 -1
  34. data/lib/cucumber/chef/templates/cucumber-chef/config-rb.erb +5 -0
  35. data/lib/cucumber/chef/test_lab.rb +70 -23
  36. data/lib/cucumber/chef/utility.rb +121 -31
  37. data/lib/cucumber/chef/version.rb +2 -2
  38. data/lib/cucumber/chef.rb +1 -1
  39. data/lib/cucumber-chef.rb +1 -1
  40. data/spec/cucumber/chef/config_spec.rb +1 -1
  41. data/spec/cucumber/chef/provisioner_spec.rb +1 -1
  42. data/spec/cucumber/chef/test_lab_spec.rb +1 -1
  43. data/spec/spec_helper.rb +1 -1
  44. metadata +8 -5
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stephen Nelson-Smith <stephen@atalanta-systems.com>
4
4
  # Author: Zachary Patten <zachary@jovelabs.com>
5
- # Copyright: Copyright (c) 2011-2012 Atalanta Systems Ltd
5
+ # Copyright: Copyright (c) 2011-2013 Atalanta Systems Ltd
6
6
  # License: Apache License, Version 2.0
7
7
  #
8
8
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -41,33 +41,33 @@ module Cucumber
41
41
  ################################################################################
42
42
 
43
43
  def run
44
- $logger.debug { "config(#{@config.inspect})" }
44
+ Cucumber::Chef.logger.debug { "config(#{@config.inspect})" }
45
45
 
46
46
  if !@config[:template_file]
47
47
  message = "You must supply a 'template_file' option."
48
- $logger.fatal { message }
48
+ Cucumber::Chef.logger.fatal { message }
49
49
  raise BootstrapError, message
50
50
  end
51
51
 
52
52
  if !@config[:host]
53
53
  message = "You must supply a 'host' option."
54
- $logger.fatal { message }
54
+ Cucumber::Chef.logger.fatal { message }
55
55
  raise BootstrapError, message
56
56
  end
57
57
 
58
58
  if !@config[:ssh_user]
59
59
  message = "You must supply a 'ssh_user' option."
60
- $logger.fatal { message }
60
+ Cucumber::Chef.logger.fatal { message }
61
61
  raise BootstrapError, message
62
62
  end
63
63
 
64
64
  if (!@config[:ssh_password] && !@config[:identity_file])
65
65
  message = "You must supply a 'ssh_password' or 'identity_file' option."
66
- $logger.fatal { message }
66
+ Cucumber::Chef.logger.fatal { message }
67
67
  raise BootstrapError, message
68
68
  end
69
69
 
70
- $logger.debug { "prepare(#{@config[:host]})" }
70
+ Cucumber::Chef.logger.debug { "prepare(#{@config[:host]})" }
71
71
 
72
72
  @ssh.config.host_name = @config[:host]
73
73
  @ssh.config.user = @config[:ssh_user]
@@ -75,13 +75,13 @@ module Cucumber
75
75
  @ssh.config.keys = @config[:identity_file]
76
76
  @ssh.config.timeout = 5
77
77
 
78
- $logger.debug { "template_file(#{@config[:template_file]})" }
78
+ Cucumber::Chef.logger.debug { "template_file(#{@config[:template_file]})" }
79
79
  command = ZTK::Template.render(@config[:template_file], @config[:context])
80
80
  command = "sudo #{command}" if @config[:use_sudo]
81
81
 
82
- $logger.debug { "begin(#{@config[:host]})" }
82
+ Cucumber::Chef.logger.debug { "begin(#{@config[:host]})" }
83
83
  @ssh.exec(command, :silence => true)
84
- $logger.debug { "end(#{@config[:host]})" }
84
+ Cucumber::Chef.logger.debug { "end(#{@config[:host]})" }
85
85
  end
86
86
 
87
87
  ################################################################################
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stephen Nelson-Smith <stephen@atalanta-systems.com>
4
4
  # Author: Zachary Patten <zachary@jovelabs.com>
5
- # Copyright: Copyright (c) 2011-2012 Atalanta Systems Ltd
5
+ # Copyright: Copyright (c) 2011-2013 Atalanta Systems Ltd
6
6
  # License: Apache License, Version 2.0
7
7
  #
8
8
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -51,14 +51,14 @@ module Cucumber
51
51
 
52
52
  def self.load
53
53
  config_rb = Cucumber::Chef.locate(:file, ".cucumber-chef", "config.rb")
54
- $logger.info { "Attempting to load cucumber-chef configuration from '%s'." % config_rb }
54
+ Cucumber::Chef.logger.debug { "Attempting to load cucumber-chef configuration from '%s'." % config_rb }
55
55
  self.from_file(config_rb)
56
56
  self.verify
57
- $logger.info { "Successfully loaded cucumber-chef configuration from '%s'." % config_rb }
57
+ Cucumber::Chef.logger.debug { "Successfully loaded cucumber-chef configuration from '%s'." % config_rb }
58
58
 
59
59
  log_dump = self.duplicate(self.configuration)
60
60
  log_dump[:aws].merge!(:aws_access_key_id => "[REDACTED]", :aws_secret_access_key => "[REDACTED]")
61
- $logger.debug { log_dump.inspect }
61
+ Cucumber::Chef.logger.debug { log_dump.inspect }
62
62
 
63
63
  self
64
64
  rescue Errno::ENOENT, UtilityError
@@ -77,25 +77,25 @@ module Cucumber
77
77
  self.verify_keys
78
78
  self.verify_provider_keys
79
79
  eval("self.verify_provider_#{self[:provider].to_s.downcase}")
80
- $logger.debug { "Configuration verified successfully" }
80
+ Cucumber::Chef.logger.debug { "Configuration verified successfully" }
81
81
  end
82
82
 
83
83
  ################################################################################
84
84
 
85
85
  def self.verify_keys
86
- $logger.debug { "Checking for missing configuration keys" }
86
+ Cucumber::Chef.logger.debug { "Checking for missing configuration keys" }
87
87
  missing_keys = KEYS.select{ |key| !self[key.to_sym] }
88
88
  if missing_keys.count > 0
89
89
  message = "Configuration incomplete, missing configuration keys: #{missing_keys.join(", ")}"
90
- $logger.fatal { message }
90
+ Cucumber::Chef.logger.fatal { message }
91
91
  raise ConfigError, message
92
92
  end
93
93
 
94
- $logger.debug { "Checking for invalid configuration keys" }
94
+ Cucumber::Chef.logger.debug { "Checking for invalid configuration keys" }
95
95
  invalid_keys = KEYS.select{ |key| !eval("#{key.to_s.upcase}S").include?(self[key]) }
96
96
  if invalid_keys.count > 0
97
97
  message = "Configuration incomplete, invalid configuration keys: #{invalid_keys.join(", ")}"
98
- $logger.fatal { message }
98
+ Cucumber::Chef.logger.fatal { message }
99
99
  raise ConfigError, message
100
100
  end
101
101
  end
@@ -103,11 +103,11 @@ module Cucumber
103
103
  ################################################################################
104
104
 
105
105
  def self.verify_provider_keys
106
- $logger.debug { "Checking for missing provider keys" }
106
+ Cucumber::Chef.logger.debug { "Checking for missing provider keys" }
107
107
  missing_keys = eval("PROVIDER_#{self[:provider].to_s.upcase}_KEYS").select{ |key| !self[self[:provider]].key?(key) }
108
108
  if missing_keys.count > 0
109
109
  message = "Configuration incomplete, missing provider configuration keys: #{missing_keys.join(", ")}"
110
- $logger.fatal { message }
110
+ Cucumber::Chef.logger.fatal { message }
111
111
  raise ConfigError, message
112
112
  end
113
113
  end
@@ -122,14 +122,14 @@ module Cucumber
122
122
  compute.describe_availability_zones
123
123
  end
124
124
  rescue Fog::Service::Error => err
125
- message = "Invalid AWS credentials. Please check your configuration."
126
- $logger.fatal { message }
125
+ message = "Invalid AWS credentials. Please check your configuration. #{err.inspect}"
126
+ Cucumber::Chef.logger.fatal { message }
127
127
  raise ConfigError, message
128
128
  end
129
129
 
130
130
  def self.verify_provider_vagrant
131
131
  message = "Not yet implemented."
132
- $logger.fatal { message }
132
+ Cucumber::Chef.logger.fatal { message }
133
133
  raise ConfigError, message
134
134
  end
135
135
 
@@ -147,7 +147,7 @@ module Cucumber
147
147
  return ami.name if ami
148
148
  end
149
149
  message = "Could not find a valid AMI image ID. Please check your configuration."
150
- $logger.fatal { message }
150
+ Cucumber::Chef.logger.fatal { message }
151
151
  raise ConfigError, message
152
152
  end
153
153
 
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stephen Nelson-Smith <stephen@atalanta-systems.com>
4
4
  # Author: Zachary Patten <zachary@jovelabs.com>
5
- # Copyright: Copyright (c) 2011-2012 Atalanta Systems Ltd
5
+ # Copyright: Copyright (c) 2011-2013 Atalanta Systems Ltd
6
6
  # License: Apache License, Version 2.0
7
7
  #
8
8
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,26 +26,45 @@ module Cucumber::Chef::Helpers::ChefClient
26
26
  # call this in a Before hook
27
27
  def chef_set_client_config(config={})
28
28
  @chef_client_config = (@chef_client_config || {
29
- :log_level => :debug,
29
+ :log_level => :info,
30
30
  :log_location => "/var/log/chef/client.log",
31
31
  :chef_server_url => "https://api.opscode.com/organizations/#{config[:orgname]}",
32
- :validation_client_name => "#{config[:orgname]}-validator"
32
+ :validation_client_name => "#{config[:orgname]}-validator",
33
+ :ssl_verify_mode => :verify_none,
34
+ :environment => nil # use default; i.e. set no value
33
35
  }).merge(config)
36
+ log("setting chef client config $#{@chef_client_config.inspect}$")
37
+
38
+ true
34
39
  end
35
40
 
36
41
  ################################################################################
37
42
 
38
43
  # call this before chef_run_client
39
44
  def chef_set_client_attributes(name, attributes={})
40
- @chef_client_attributes = (@chef_client_attributes || {}).merge(attributes) { |k,o,n| (k = (o + n)) }
45
+ @servers[name] ||= Hash.new
46
+ @servers[name][:chef_client] = (@servers[name][:chef_client] || {}).merge(attributes) { |k,o,n| (k = (o + n).uniq) }
47
+ log("setting chef client attributes to $#{@servers[name][:chef_client].inspect}$ for container $#{name}$")
48
+
49
+ true
41
50
  end
42
51
 
43
52
  ################################################################################
44
53
 
45
54
  def chef_run_client(name,*args)
46
55
  chef_config_client(name)
47
- output = command_run_remote(name, ["/usr/bin/chef-client -j /etc/chef/attributes.json -N #{name}", args].join(" "))
48
- log("chef-client", "ran on node '#{name}'")
56
+ artifacts =
57
+ log("removing artifacts #{Cucumber::Chef::Config[:artifacts].values.collect{|z| "$#{z}$" }.join(' ')}")
58
+ (command_run_remote(name, "/bin/rm -fv #{Cucumber::Chef::Config[:artifacts].values.join(' ')}") rescue nil)
59
+
60
+ log("running chef client on container $#{name}$")
61
+
62
+ output = nil
63
+ bm = ::Benchmark.realtime do
64
+ output = command_run_remote(name, ["/usr/bin/chef-client --json-attributes /etc/chef/attributes.json --node-name #{name}", args].flatten.join(" "))
65
+ end
66
+ log("chef client run on container $#{name}$ took %0.4f seconds" % bm)
67
+
49
68
  output
50
69
  end
51
70
 
@@ -56,16 +75,15 @@ module Cucumber::Chef::Helpers::ChefClient
56
75
  client_rb = File.join("/", container_root(name), "etc/chef/client.rb")
57
76
  FileUtils.mkdir_p(File.dirname(client_rb))
58
77
 
78
+ max_key_size = @chef_client_config.keys.collect{ |z| z.to_s.size }.max
79
+
59
80
  File.open(client_rb, 'w') do |f|
60
81
  f.puts(Cucumber::Chef.generate_do_not_edit_warning("Chef Client Configuration"))
61
82
  f.puts
62
- f.puts("log_level :#{@chef_client_config[:log_level]}")
63
- f.puts("log_location \"#{@chef_client_config[:log_location]}\"")
64
- f.puts("chef_server_url \"#{@chef_client_config[:chef_server_url]}\"")
65
- f.puts("ssl_verify_mode :verify_none")
66
- f.puts("validation_client_name \"#{@chef_client_config[:validation_client_name]}\"")
67
- f.puts("node_name \"#{name}\"")
68
- f.puts("environment \"#{@chef_client_config[:environment]}\"") if @chef_client_config[:environment]
83
+ @chef_client_config.merge(:node_name => name).each do |(key,value)|
84
+ next if value.nil?
85
+ f.puts("%-#{max_key_size}s %s" % [key, value.inspect])
86
+ end
69
87
  f.puts
70
88
  f.puts("Mixlib::Log::Formatter.show_time = true")
71
89
  end
@@ -73,7 +91,7 @@ module Cucumber::Chef::Helpers::ChefClient
73
91
  attributes_json = File.join("/", container_root(name), "etc", "chef", "attributes.json")
74
92
  FileUtils.mkdir_p(File.dirname(attributes_json))
75
93
  File.open(attributes_json, 'w') do |f|
76
- f.puts((@chef_client_attributes || {}).to_json)
94
+ f.puts((@servers[name][:chef_client] || {}).to_json)
77
95
  end
78
96
 
79
97
  # make sure our log location is there
@@ -81,6 +99,62 @@ module Cucumber::Chef::Helpers::ChefClient
81
99
  FileUtils.mkdir_p(File.dirname(log_location))
82
100
 
83
101
  command_run_local("cp /etc/chef/validation.pem #{container_root(name)}/etc/chef/ 2>&1")
102
+
103
+ true
104
+ end
105
+
106
+ ################################################################################
107
+
108
+ def chef_client_artifacts(name)
109
+ # this is messy and needs to be refactored into a more configurable
110
+ # solution; but for now this should do the trick
111
+
112
+ ssh_private_key_file = Cucumber::Chef.locate(:file, ".cucumber-chef", "id_rsa-#{Cucumber::Chef::Config[:lab_user]}")
113
+ File.chmod(0400, ssh_private_key_file)
114
+
115
+ ssh = ZTK::SSH.new
116
+
117
+ ssh.config.proxy_host_name = $test_lab.labs_running.first.public_ip_address
118
+ ssh.config.proxy_user = Cucumber::Chef::Config[:lab_user]
119
+ ssh.config.proxy_keys = ssh_private_key_file
120
+
121
+ ssh.config.host_name = name
122
+ ssh.config.user = Cucumber::Chef::Config[:lxc_user]
123
+ ssh.config.keys = ssh_private_key_file
124
+
125
+ feature_file = $scenario.file_colon_line.split(":").first
126
+ feature_line = $scenario.file_colon_line.split(":").last
127
+ scenario_tag = $scenario.name.gsub(" ", "_")
128
+
129
+ feature_name = File.basename(feature_file, ".feature")
130
+ feature_dir = feature_file.split("/")[-2]
131
+
132
+ Cucumber::Chef::Config[:artifacts].each do |label, remote_path|
133
+ result = ssh.exec("/bin/bash -c '[[ -f #{remote_path} ]] ; echo $?'", :silence => true)
134
+ if (result.output =~ /0/)
135
+ log("retrieving artifact $#{remote_path}$ from container $#{name}$")
136
+
137
+ local_path = File.join(Cucumber::Chef.locate(:directory, ".cucumber-chef"), "artifacts", feature_dir, "#{feature_name}.txt")
138
+ tmp_path = File.join("/tmp", label)
139
+
140
+ FileUtils.mkdir_p(File.dirname(local_path))
141
+ ssh.download(remote_path, tmp_path)
142
+ data = IO.read(tmp_path).chomp
143
+
144
+ message = "#{$scenario.name} (#{File.basename(feature_file)}:#{feature_line}:#{label})"
145
+ header = ("-" * message.length)
146
+
147
+ f = File.open(local_path, "a")
148
+ f.write("#{header}\n")
149
+ f.write("#{message}\n")
150
+ f.write("#{header}\n")
151
+ f.write("#{data}\n")
152
+
153
+ File.chmod(0644, local_path)
154
+ end
155
+ end
156
+
157
+ true
84
158
  end
85
159
 
86
160
  ################################################################################
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stephen Nelson-Smith <stephen@atalanta-systems.com>
4
4
  # Author: Zachary Patten <zachary@jovelabs.com>
5
- # Copyright: Copyright (c) 2011-2012 Atalanta Systems Ltd
5
+ # Copyright: Copyright (c) 2011-2013 Atalanta Systems Ltd
6
6
  # License: Apache License, Version 2.0
7
7
  #
8
8
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,14 +25,14 @@ module Cucumber::Chef::Helpers::ChefServer
25
25
 
26
26
  def chef_server_node_destroy(name)
27
27
  (::Chef::Node.load(name).destroy rescue nil)
28
- log("chef-server", "destroyed node '#{name}'")
28
+ log("destroyed chef node $#{name}$")
29
29
  end
30
30
 
31
31
  ################################################################################
32
32
 
33
33
  def chef_server_client_destroy(name)
34
34
  (::Chef::ApiClient.load(name).destroy rescue nil)
35
- log("chef-server", "destroyed client '#{name}'")
35
+ log("destroyed chef client $#{name}$")
36
36
  end
37
37
 
38
38
  ################################################################################
@@ -45,20 +45,37 @@ module Cucumber::Chef::Helpers::ChefServer
45
45
  cookbook_repo.each do |name, cbook|
46
46
  next if name != cookbook
47
47
  ::Chef::CookbookUploader.new(cbook, cookbook_path, :force => true).upload_cookbooks
48
- log("chef-server", "uploaded cookbook '#{cookbook}' from path '#{cookbook_path}'")
48
+ log("uploaded chef cookbook $#{cookbook}$ from $#{cookbook_path}$")
49
49
  end
50
50
  end
51
51
 
52
52
  ################################################################################
53
53
 
54
54
  def load_role(role, role_path)
55
- if !File.exists?(File.expand_path(role_path))
56
- raise "Role path does not exist!"
55
+ expanded_role_path = File.expand_path(role_path)
56
+ if !File.exists?(expanded_role_path)
57
+ raise "Role path, '#{expanded_role_path}', does not exist!"
57
58
  end
58
- ::Chef::Config[:role_path] = role_path
59
+ ::Chef::Config[:role_path] = expanded_role_path
59
60
  role = ::Chef::Role.from_disk(role)
60
61
  role.save
61
- log("chef-server", "updated role '#{role}' from file '#{role_path}'")
62
+ log("updated chef role $#{role}$ from $#{role_path}$")
63
+ end
64
+
65
+ ################################################################################
66
+
67
+ def get_databag(databag)
68
+ @rest ||= ::Chef::REST.new(Chef::Config[:chef_server_url])
69
+ @rest.get_rest("data/#{databag}")
70
+ rescue Net::HTTPServerException => e
71
+ raise unless e.to_s =~ /^404/
72
+ end
73
+
74
+ def destroy_databag(databag)
75
+ @rest ||= ::Chef::REST.new(Chef::Config[:chef_server_url])
76
+ @rest.delete_rest("data/#{databag}")
77
+ rescue Net::HTTPServerException => e
78
+ raise unless e.to_s =~ /^404/
62
79
  end
63
80
 
64
81
  ################################################################################
@@ -77,24 +94,30 @@ module Cucumber::Chef::Helpers::ChefServer
77
94
  def load_databag(databag, databag_path)
78
95
  create_databag(databag)
79
96
  items = Dir.glob(File.expand_path(File.join(databag_path, "*.{json,rb}")))
97
+ if (items.size == 0)
98
+ raise "Could not find any of the data bags you defined!"
99
+ end
80
100
  items.each do |item|
81
101
  next if File.directory?(item)
82
102
 
103
+ item_name = %w( json rb ).collect{ |ext| (item =~ /#{ext}/ ? File.basename(item, ".#{ext}") : nil) }.compact.first
83
104
  item_path = File.basename(item)
84
105
  databag_item_path = File.expand_path(File.join(databag_path, item_path))
85
106
 
86
107
  data_bag_item = ::Chef::DataBagItem.new
87
108
  data_bag_item.data_bag(databag)
88
- data_bag_item.raw_data = load_databag_item(databag_item_path)
109
+ raw_data = load_databag_item(databag_item_path)
110
+ data_bag_item.raw_data = raw_data.dup
89
111
  data_bag_item.save
90
- log("chef-server", "updated data bag item '#{databag}/#{item_path}' from file '#{databag_path}'")
91
- end
92
112
 
93
- # TODO fix ghetto sleep
94
- # databags don't always update right away; ghetto fix with a sleep
95
- # for now. likely needs to loop reading the databag back until it updates
96
- # then return
97
- sleep(3)
113
+ loop do
114
+ chef_data = ::Chef::DataBagItem.load(databag, item_name).raw_data
115
+ break if chef_data == raw_data
116
+ log("waiting on chef data bag to update")
117
+ sleep(1)
118
+ end
119
+ log("updated chef data bag item $#{databag}/#{item_path}$ from $#{databag_path}$")
120
+ end
98
121
  end
99
122
 
100
123
  ################################################################################
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stephen Nelson-Smith <stephen@atalanta-systems.com>
4
4
  # Author: Zachary Patten <zachary@jovelabs.com>
5
- # Copyright: Copyright (c) 2011-2012 Atalanta Systems Ltd
5
+ # Copyright: Copyright (c) 2011-2013 Atalanta Systems Ltd
6
6
  # License: Apache License, Version 2.0
7
7
  #
8
8
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,29 +24,45 @@ module Cucumber::Chef::Helpers::Command
24
24
  ################################################################################
25
25
 
26
26
  def command_run_remote(name, command, expected_exit_code=0)
27
- output = %x(ssh #{name} '#{command}' 2>&1)
28
- raise "command_run_remote(#{command}) failed (#{$?})" if ($? != expected_exit_code)
27
+ command = %Q(ssh #{name} #{command} 2>&1)
28
+ logger.info { "command_run_remote(#{command})" }
29
+ output = %x(#{command})
30
+ if !expected_exit_code.nil? && ($? != expected_exit_code)
31
+ message = "command_run_remote(#{command}) failed (code=#{$?},output='#{output.chomp}')"
32
+ logger.fatal { message }
33
+ logger.fatal { "output(#{output.chomp})" }
34
+ raise message
35
+ end
29
36
  output
30
- # rescue RuntimeError => e
31
- # if $? == 65280
32
- # puts "Exit Code #{$?}: Retrying..."
33
- # retry
34
- # end
35
37
  end
36
38
 
37
39
  ################################################################################
38
40
 
39
41
  def command_run_chroot(name, command, expected_exit_code=0)
40
- output = %x(chroot #{container_root(name)} /bin/bash -c '#{command}' 2>&1)
41
- raise "command_run_chroot(#{command}) failed (#{$?})" if ($? != expected_exit_code)
42
+ command = %Q(chroot #{container_root(name)} /bin/bash -c '#{command.gsub("'", '"')}' 2>&1)
43
+ logger.info { "command_run_chroot(#{command})" }
44
+ output = %x(#{command})
45
+ if !expected_exit_code.nil? && ($? != expected_exit_code)
46
+ message = "command_run_chroot(#{command}) failed (#{$?})"
47
+ logger.fatal { message }
48
+ logger.fatal { "output(#{output.chomp})" }
49
+ raise message
50
+ end
42
51
  output
43
52
  end
44
53
 
45
54
  ################################################################################
46
55
 
47
56
  def command_run_local(command, expected_exit_code=0)
48
- output = %x(#{command} 2>&1)
49
- raise "command_run_local(#{command}) failed (#{$?})" if ($? != expected_exit_code)
57
+ command = %Q(/bin/bash -c '#{command.gsub("'", '"')}' 2>&1)
58
+ logger.info { "command_run_local(#{command})" }
59
+ output = %x(#{command})
60
+ if !expected_exit_code.nil? && ($? != expected_exit_code)
61
+ message = "command_run_local(#{command}) failed (#{$?})"
62
+ logger.fatal { message }
63
+ logger.fatal { "output(#{output.chomp})" }
64
+ raise message
65
+ end
50
66
  output
51
67
  end
52
68
 
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stephen Nelson-Smith <stephen@atalanta-systems.com>
4
4
  # Author: Zachary Patten <zachary@jovelabs.com>
5
- # Copyright: Copyright (c) 2011-2012 Atalanta Systems Ltd
5
+ # Copyright: Copyright (c) 2011-2013 Atalanta Systems Ltd
6
6
  # License: Apache License, Version 2.0
7
7
  #
8
8
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,71 +25,74 @@ module Cucumber::Chef::Helpers::Container
25
25
 
26
26
  def container_create(name, distro, release, arch)
27
27
  unless container_exists?(name)
28
- chef_server_node_destroy(name)
29
- chef_server_client_destroy(name)
30
-
31
28
  cache_rootfs = container_cache_root(name, distro, release, arch)
32
- log(name, "has triggered first time lxc distro cache build; this will take a while") if !File.exists?(cache_rootfs)
29
+ if !File.exists?(cache_rootfs)
30
+ log("$#{name}$ has triggered building the lxc file cache for $#{distro}$")
31
+ log("this one time process per distro can take up to 10 minutes or longer depending on the test lab hardware")
32
+ end
33
33
 
34
34
  command_run_local(container_create_command(name, distro, release, arch))
35
35
 
36
36
  # install omnibus into the distro/release file cache if it's not already there
37
- omnibus_chef_client = File.join("/", "opt", "opscode", "bin", "chef-client")
38
- if !File.exists?(File.join(cache_rootfs, omnibus_chef_client))
37
+ omnibus_chef_client = File.join("/", "opt", "chef", "bin", "chef-client")
38
+ omnibus_cache = File.join(cache_rootfs, omnibus_chef_client)
39
+ logger.info { "looking for omnibus cache in #{omnibus_cache}" }
40
+ if !File.exists?(omnibus_cache)
39
41
  case distro.downcase
40
42
  when "ubuntu" then
41
- %x( chroot #{cache_rootfs} /bin/bash -c 'apt-get -y --force-yes install wget' 2>&1 )
43
+ command_run_local("chroot #{cache_rootfs} /bin/bash -c 'apt-get -y --force-yes install wget'")
42
44
  when "fedora" then
43
- %x( yum --nogpgcheck --installroot=#{cache_rootfs} -y install wget openssh-server )
45
+ command_run_local("yum --nogpgcheck --installroot=#{cache_rootfs} -y install wget openssh-server")
44
46
  end
45
- %x( chroot #{cache_rootfs} /bin/bash -c 'wget http://www.opscode.com/chef/install.sh -O - | bash' 2>&1 )
47
+ command_run_local("chroot #{cache_rootfs} /bin/bash -c 'wget http://www.opscode.com/chef/install.sh -O - | bash'")
46
48
  if distro.downcase == "fedora"
47
- %x( chroot #{cache_rootfs} /bin/bash -c 'rpm -Uvh --nodeps /tmp/*rpm' 2>&1 )
49
+ command_run_local("chroot #{cache_rootfs} /bin/bash -c 'rpm -Uvh --nodeps /tmp/*rpm'")
48
50
  end
49
- command_run_local("lxc-destroy -n #{name} 2>&1")
51
+ command_run_local("lxc-destroy -n #{name}")
50
52
  command_run_local(container_create_command(name, distro, release, arch))
51
53
  end
52
54
 
53
55
  command_run_local("mkdir -p #{container_root(name)}/root/.ssh")
54
56
  command_run_local("chmod 0755 #{container_root(name)}/root/.ssh")
55
57
  command_run_local("cat /root/.ssh/id_rsa.pub | tee -a #{container_root(name)}/root/.ssh/authorized_keys")
56
- command_run_local("cat /home/ubuntu/.ssh/id_rsa.pub | tee -a #{container_root(name)}/root/.ssh/authorized_keys")
58
+ command_run_local("cat /home/#{Cucumber::Chef::Config[:lab_user]}/.ssh/id_rsa.pub | tee -a #{container_root(name)}/root/.ssh/authorized_keys")
57
59
 
58
- command_run_local("mkdir -p #{container_root(name)}/home/ubuntu/.ssh")
59
- command_run_local("chmod 0755 #{container_root(name)}/home/ubuntu/.ssh")
60
- command_run_local("cat /root/.ssh/id_rsa.pub | tee -a #{container_root(name)}/home/ubuntu/.ssh/authorized_keys")
61
- command_run_local("cat /home/ubuntu/.ssh/id_rsa.pub | tee -a #{container_root(name)}/home/ubuntu/.ssh/authorized_keys")
62
- command_run_local("chown -R ubuntu:ubuntu #{container_root(name)}/home/ubuntu/.ssh")
60
+ command_run_local("mkdir -p #{container_root(name)}/home/#{Cucumber::Chef::Config[:lab_user]}/.ssh")
61
+ command_run_local("chmod 0755 #{container_root(name)}/home/#{Cucumber::Chef::Config[:lab_user]}/.ssh")
62
+ command_run_local("cat /root/.ssh/id_rsa.pub | tee -a #{container_root(name)}/home/#{Cucumber::Chef::Config[:lab_user]}/.ssh/authorized_keys")
63
+ command_run_local("cat /home/#{Cucumber::Chef::Config[:lab_user]}/.ssh/id_rsa.pub | tee -a #{container_root(name)}/home/#{Cucumber::Chef::Config[:lab_user]}/.ssh/authorized_keys")
64
+ command_run_local("chown -R #{Cucumber::Chef::Config[:lab_user]}:#{Cucumber::Chef::Config[:lab_user]} #{container_root(name)}/home/#{Cucumber::Chef::Config[:lab_user]}/.ssh")
63
65
 
64
66
  command_run_local("rm #{container_root(name)}/etc/motd")
65
67
  command_run_local("cp /etc/motd #{container_root(name)}/etc/motd")
66
- command_run_local("echo \" You are now logged in to the LXC '#{name}'\\n\" >> #{container_root(name)}/etc/motd")
67
- command_run_local("sed -i \"s/localhost #{name}/#{name}.test-lab #{name} localhost/\" #{container_root(name)}/etc/hosts")
68
- command_run_local("echo \"#{name}.test-lab\" | tee #{container_root(name)}/etc/hostname")
68
+ command_run_local("echo ' You are now logged in to the #{name} container!\n' >> #{container_root(name)}/etc/motd")
69
+ command_run_local("sed -i 's/localhost #{name}/#{name}.test-lab #{name} localhost/' #{container_root(name)}/etc/hosts")
70
+ command_run_local("echo '#{name}.test-lab' | tee #{container_root(name)}/etc/hostname")
69
71
  end
70
72
  container_start(name)
71
73
  end
72
74
 
73
75
  def container_destroy(name)
74
76
  if container_exists?(name)
75
- container_stop(name)
76
- command_run_local("lxc-destroy -n #{name} 2>&1")
77
77
  chef_server_node_destroy(name)
78
78
  chef_server_client_destroy(name)
79
+ container_stop(name)
80
+ command_run_local("lxc-destroy -n #{name}")
81
+ log("destroyed container $#{name}$")
79
82
  end
80
83
  end
81
84
 
82
85
  ################################################################################
83
86
 
84
87
  def container_start(name)
85
- status = command_run_local("lxc-info -n #{name} 2>&1")
88
+ status = command_run_local("lxc-info -n #{name}")
86
89
  if status.include?("STOPPED")
87
90
  command_run_local("lxc-start -d -n #{name}")
88
91
  end
89
92
  end
90
93
 
91
94
  def container_stop(name)
92
- status = command_run_local("lxc-info -n #{name} 2>&1")
95
+ status = command_run_local("lxc-info -n #{name}")
93
96
  if status.include?("RUNNING")
94
97
  command_run_local("lxc-stop -n #{name}")
95
98
  end
@@ -98,7 +101,7 @@ module Cucumber::Chef::Helpers::Container
98
101
  ################################################################################
99
102
 
100
103
  def container_running?(name)
101
- status = command_run_local("lxc-info -n #{name} 2>&1")
104
+ status = command_run_local("lxc-info -n #{name}")
102
105
  status.include?("RUNNING")
103
106
  end
104
107
 
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stephen Nelson-Smith <stephen@atalanta-systems.com>
4
4
  # Author: Zachary Patten <zachary@jovelabs.com>
5
- # Copyright: Copyright (c) 2011-2012 Atalanta Systems Ltd
5
+ # Copyright: Copyright (c) 2011-2013 Atalanta Systems Ltd
6
6
  # License: Apache License, Version 2.0
7
7
  #
8
8
  # Licensed under the Apache License, Version 2.0 (the "License");