cucumber-chef 2.0.7 → 2.1.0.rc.0

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.
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");