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.
- data/README.md +1 -1
- data/Rakefile +1 -1
- data/bin/cc-knife +2 -5
- data/bin/cc-push +50 -26
- data/bin/cc-server +9 -10
- data/bin/cucumber-chef +65 -71
- data/chef_repo/cookbooks/cucumber-chef/attributes/default.rb +1 -1
- data/chef_repo/cookbooks/cucumber-chef/recipes/default.rb +1 -1
- data/chef_repo/cookbooks/cucumber-chef/recipes/lxc.rb +34 -36
- data/chef_repo/cookbooks/cucumber-chef/recipes/test_lab.rb +64 -47
- data/chef_repo/cookbooks/cucumber-chef/templates/default/solrconfig.erb +650 -0
- data/cucumber-chef.gemspec +5 -5
- data/lib/cucumber/chef/bootstrap.rb +10 -10
- data/lib/cucumber/chef/config.rb +15 -15
- data/lib/cucumber/chef/helpers/chef_client.rb +88 -14
- data/lib/cucumber/chef/helpers/chef_server.rb +39 -16
- data/lib/cucumber/chef/helpers/command.rb +28 -12
- data/lib/cucumber/chef/helpers/container.rb +29 -26
- data/lib/cucumber/chef/helpers/minitest.rb +1 -1
- data/lib/cucumber/chef/helpers/server.rb +37 -18
- data/lib/cucumber/chef/helpers/test_lab.rb +1 -1
- data/lib/cucumber/chef/helpers/utility.rb +23 -3
- data/lib/cucumber/chef/helpers.rb +10 -8
- data/lib/cucumber/chef/provisioner.rb +22 -21
- data/lib/cucumber/chef/steps/chef_steps.rb +1 -1
- data/lib/cucumber/chef/steps/minitest_steps.rb +3 -3
- data/lib/cucumber/chef/steps/provision_steps.rb +7 -6
- data/lib/cucumber/chef/steps/ssh_steps.rb +31 -2
- data/lib/cucumber/chef/steps.rb +1 -1
- data/lib/cucumber/chef/templates/cucumber/cc-hooks.rb +111 -0
- data/lib/cucumber/chef/templates/cucumber/env.rb +0 -87
- data/lib/cucumber/chef/templates/cucumber/readme-environments.erb +1 -0
- data/lib/cucumber/chef/templates/cucumber/readme-roles.erb +1 -1
- data/lib/cucumber/chef/templates/cucumber-chef/config-rb.erb +5 -0
- data/lib/cucumber/chef/test_lab.rb +70 -23
- data/lib/cucumber/chef/utility.rb +121 -31
- data/lib/cucumber/chef/version.rb +2 -2
- data/lib/cucumber/chef.rb +1 -1
- data/lib/cucumber-chef.rb +1 -1
- data/spec/cucumber/chef/config_spec.rb +1 -1
- data/spec/cucumber/chef/provisioner_spec.rb +1 -1
- data/spec/cucumber/chef/test_lab_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- 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-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
66
|
+
Cucumber::Chef.logger.fatal { message }
|
67
67
|
raise BootstrapError, message
|
68
68
|
end
|
69
69
|
|
70
|
-
|
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
|
-
|
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
|
-
|
82
|
+
Cucumber::Chef.logger.debug { "begin(#{@config[:host]})" }
|
83
83
|
@ssh.exec(command, :silence => true)
|
84
|
-
|
84
|
+
Cucumber::Chef.logger.debug { "end(#{@config[:host]})" }
|
85
85
|
end
|
86
86
|
|
87
87
|
################################################################################
|
data/lib/cucumber/chef/config.rb
CHANGED
@@ -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-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
80
|
+
Cucumber::Chef.logger.debug { "Configuration verified successfully" }
|
81
81
|
end
|
82
82
|
|
83
83
|
################################################################################
|
84
84
|
|
85
85
|
def self.verify_keys
|
86
|
-
|
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
|
-
|
90
|
+
Cucumber::Chef.logger.fatal { message }
|
91
91
|
raise ConfigError, message
|
92
92
|
end
|
93
93
|
|
94
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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-
|
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 => :
|
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
|
-
@
|
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
|
-
|
48
|
-
log("
|
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
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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((@
|
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-
|
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
|
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
|
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
|
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
|
-
|
56
|
-
|
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] =
|
59
|
+
::Chef::Config[:role_path] = expanded_role_path
|
59
60
|
role = ::Chef::Role.from_disk(role)
|
60
61
|
role.save
|
61
|
-
log("chef
|
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
|
-
|
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
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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-
|
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
|
-
|
28
|
-
|
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
|
-
|
41
|
-
|
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
|
-
|
49
|
-
|
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-
|
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
|
-
|
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", "
|
38
|
-
|
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
|
-
|
43
|
+
command_run_local("chroot #{cache_rootfs} /bin/bash -c 'apt-get -y --force-yes install wget'")
|
42
44
|
when "fedora" then
|
43
|
-
|
45
|
+
command_run_local("yum --nogpgcheck --installroot=#{cache_rootfs} -y install wget openssh-server")
|
44
46
|
end
|
45
|
-
|
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
|
-
|
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}
|
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
|
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
|
59
|
-
command_run_local("chmod 0755 #{container_root(name)}/home
|
60
|
-
command_run_local("cat /root/.ssh/id_rsa.pub | tee -a #{container_root(name)}/home
|
61
|
-
command_run_local("cat /home
|
62
|
-
command_run_local("chown -R
|
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
|
67
|
-
command_run_local("sed -i
|
68
|
-
command_run_local("echo
|
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}
|
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}
|
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}
|
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-
|
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");
|