cucumber-chef 0.4.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.
- data/.document +5 -0
- data/.gitignore +45 -0
- data/Gemfile +21 -0
- data/LICENSE +201 -0
- data/README.md +83 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/bin/cucumber-chef +162 -0
- data/cookbooks/cucumber-chef/README.rdoc +8 -0
- data/cookbooks/cucumber-chef/files/default/add-git-identity +2 -0
- data/cookbooks/cucumber-chef/files/default/controller-first-boot +1 -0
- data/cookbooks/cucumber-chef/files/default/cucumber-net +5 -0
- data/cookbooks/cucumber-chef/files/default/cucumber-private-key +27 -0
- data/cookbooks/cucumber-chef/files/default/cucumber-run_list +1 -0
- data/cookbooks/cucumber-chef/files/default/git-private-key +27 -0
- data/cookbooks/cucumber-chef/files/default/install-chef +1 -0
- data/cookbooks/cucumber-chef/files/default/lxc-controller-network-config +5 -0
- data/cookbooks/cucumber-chef/files/default/lxc-lucid-chef +377 -0
- data/cookbooks/cucumber-chef/files/default/permissive-ssh-config +3 -0
- data/cookbooks/cucumber-chef/metadata.rb +6 -0
- data/cookbooks/cucumber-chef/recipes/controller.rb +50 -0
- data/cookbooks/cucumber-chef/recipes/lxc.rb +35 -0
- data/cookbooks/cucumber-chef/recipes/test_lab.rb +23 -0
- data/cookbooks/cucumber-chef/recipes/testrunner.rb +46 -0
- data/cookbooks/cucumber-chef/roles/controller.rb +7 -0
- data/cookbooks/cucumber-chef/roles/test_lab_test.rb +9 -0
- data/cookbooks/cucumber-chef/templates/default/controller-client.erb +5 -0
- data/cookbooks/cucumber-chef/templates/default/lxc-lucid-chef +385 -0
- data/cucumber-chef.gemspec +118 -0
- data/features/installing.feature +10 -0
- data/features/steps/installing_steps.rb +34 -0
- data/features/steps/setup_steps.rb +32 -0
- data/features/steps/upload_steps.rb +11 -0
- data/features/steps/usage_steps.rb +62 -0
- data/features/support/env.rb +25 -0
- data/features/support/filetools.rb +9 -0
- data/features/support/silent_system.rb +4 -0
- data/features/usage.feature +26 -0
- data/lib/cucumber-chef.rb +1 -0
- data/lib/cucumber/chef.rb +195 -0
- data/lib/cucumber/chef/handy.rb +87 -0
- data/lib/cucumber/chef/templates/controller.erb +35 -0
- data/lib/cucumber/chef/templates/env.rb +16 -0
- data/lib/cucumber/chef/templates/example_feature.erb +11 -0
- data/lib/cucumber/chef/templates/example_step.erb +19 -0
- data/lib/cucumber/chef/templates/readme.erb +28 -0
- data/lib/cucumber/chef/templates/ubuntu10.04-gems.erb +43 -0
- data/lib/cucumber/chef/version.rb +5 -0
- data/lib/cucumber/ec2_server_create.rb +99 -0
- data/spec/unit/cucumber_chef_spec.rb +270 -0
- metadata +213 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Chef
|
3
|
+
module Handy
|
4
|
+
def create_server(server, ip)
|
5
|
+
create_network_config(server, ip)
|
6
|
+
create_container(server)
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_network_config(name, ip)
|
10
|
+
network_config = File.join("/etc/lxc", name)
|
11
|
+
File.open(network_config, 'w') do |f|
|
12
|
+
f.puts "lxc.network.type = veth"
|
13
|
+
f.puts "lxc.network.flags = up"
|
14
|
+
f.puts "lxc.network.link = br0"
|
15
|
+
f.puts "lxc.network.name = eth0"
|
16
|
+
f.puts "lxc.network.ipv4 = #{ip}/24"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_container(name)
|
21
|
+
unless File.exists?("/var/lib/lxc/#{name}")
|
22
|
+
%x[lxc-create -n #{name} -f /etc/lxc/#{name} -t lucid-chef > /dev/null 2>&1 ]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_run_list(name, run_list)
|
27
|
+
rl = Hash.new
|
28
|
+
a = Array.new
|
29
|
+
a << run_list
|
30
|
+
rl['run_list'] = a
|
31
|
+
first_boot = File.join('/var/lib/lxc', name, 'rootfs/etc/chef/first-boot.json')
|
32
|
+
File.open(first_boot, 'w') do |f|
|
33
|
+
f.puts rl.to_json
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def run_chef_first_time(name)
|
38
|
+
%x[chroot /var/lib/lxc/#{name}/rootfs /bin/bash -c 'chef-client -j /etc/chef/first-boot.json > /dev/null 2>&1']
|
39
|
+
end
|
40
|
+
|
41
|
+
def run_chef(name)
|
42
|
+
container_path = "/var/lib/lxc/#{name}/rootfs"
|
43
|
+
%x[chroot #{container_path} /bin/bash -c 'chef-client > /dev/null 2>&1']
|
44
|
+
end
|
45
|
+
|
46
|
+
def upload_databag_item(databag, item)
|
47
|
+
databag_item = ::Chef::DataBagItem.new
|
48
|
+
databag_item.data_bag(databag)
|
49
|
+
databag_item.raw_data = item
|
50
|
+
databag_item.save
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_client_rb(orgname)
|
54
|
+
client_rb = File.join('/var/lib/lxc', name, 'rootfs/etc/chef/client.rb')
|
55
|
+
File.open(client_rb, 'w') do |f|
|
56
|
+
f.puts "log_level :info"
|
57
|
+
f.puts "log_location STDOUT"
|
58
|
+
f.puts "chef_server_url 'https://api.opscode.com/organizations/#{orgname}'"
|
59
|
+
f.puts "validation_client_name '#{orgname}-validator'"
|
60
|
+
f.puts "node_name 'cucumber-chef-#{name}'"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def start_container(name)
|
65
|
+
status = %x[lxc-info -n #{name} 2>&1]
|
66
|
+
if status.include?("STOPPED")
|
67
|
+
%x[lxc-start -d -n #{name}]
|
68
|
+
sleep 5
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def stop_container(name)
|
73
|
+
status = %x[lxc-info -n #{name} 2>&1]
|
74
|
+
if status.include?("RUNNING")
|
75
|
+
%x[lxc-destroy -d -n #{name}]
|
76
|
+
sleep 5
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def run_remote_command(remote_server, command)
|
81
|
+
%x[ssh workstation.testlab 'ssh #{remote_server} #{command}']
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
bash -c '
|
2
|
+
(
|
3
|
+
cat <<EOP
|
4
|
+
lxc.network.type = veth
|
5
|
+
lxc.network.flags = up
|
6
|
+
lxc.network.link = br0
|
7
|
+
lxc.network.name = eth0
|
8
|
+
lxc.network.ipv4 = 192.168.10.10/24
|
9
|
+
EOP
|
10
|
+
) > /etc/lxc/controller
|
11
|
+
|
12
|
+
lxc-create -n controller -f /etc/lxc/controller -t lucid-chef
|
13
|
+
|
14
|
+
(
|
15
|
+
cat <<EOP
|
16
|
+
|
17
|
+
log_level :info
|
18
|
+
log_location STDOUT
|
19
|
+
chef_server_url "<%= @config[:chef_server_url] %>"
|
20
|
+
validation_client_name "<%= @config[:validation_client_name] %>"
|
21
|
+
<% if @config[:chef_node_name] == nil %>
|
22
|
+
# Using default node name"
|
23
|
+
<% else %>
|
24
|
+
node_name "<%= @config[:chef_node_name] %>"
|
25
|
+
<% end %>
|
26
|
+
EOP
|
27
|
+
) > /var/lib/lxc/controller/rootfs/etc/chef/client.rb
|
28
|
+
|
29
|
+
cat <<EOP
|
30
|
+
{ "run_list": [ "recipe[cucumber-chef::controller]" ] }
|
31
|
+
EOP
|
32
|
+
) > /var/lib/lxc/controller/rootfs/etc/chef/first-boot.json
|
33
|
+
|
34
|
+
chroot /var/lib/lxc/controller/rootfs /bin/bash -c "chef-client -j /etc/chef/first-boot.json > /dev/null 2>&1"
|
35
|
+
lxc-start -d -n controller && sleep 5 && lxc-start -d -n controller'
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rspec/expectations'
|
4
|
+
require 'chef'
|
5
|
+
require 'cucumber/chef'
|
6
|
+
require 'cucumber/nagios/steps'
|
7
|
+
require 'cucumber/chef/handy'
|
8
|
+
|
9
|
+
class CustomWorld
|
10
|
+
include Cucumber::Chef
|
11
|
+
include Cucumber::Chef::Handy
|
12
|
+
end
|
13
|
+
|
14
|
+
World do
|
15
|
+
CustomWorld.new
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Feature: Example feature for <%= @project %>
|
2
|
+
So that I can be learn how to use cucumber-chef
|
3
|
+
As an infrastructure developer
|
4
|
+
I can run an example feature that doesn't do much
|
5
|
+
|
6
|
+
Scenario: Example scenario for <%= @project %>
|
7
|
+
Given I have a remote server
|
8
|
+
And I apply the <%= @project %> role/recipe
|
9
|
+
And run Chef
|
10
|
+
When I connect to the remote server from the test server
|
11
|
+
Then the <% @project %> server behaves as it should
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Given /^I have a remote server$/ do
|
2
|
+
pending # express the regexp above with the code you wish you had
|
3
|
+
end
|
4
|
+
|
5
|
+
Given /^I apply the <%= @project %> role\/recipe$/ do
|
6
|
+
pending # express the regexp above with the code you wish you had
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^run Chef$/ do
|
10
|
+
pending # express the regexp above with the code you wish you had
|
11
|
+
end
|
12
|
+
|
13
|
+
When /^I connect to the remote server from the test server$/ do
|
14
|
+
pending # express the regexp above with the code you wish you had
|
15
|
+
end
|
16
|
+
|
17
|
+
Then /^the <%= @project %> server behaves as it should$/ do
|
18
|
+
pending # express the regexp above with the code you wish you had
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Welcome to the <%= @project %> suite of cucumber-chef tests
|
2
|
+
|
3
|
+
Your general workflow will be to write cucumber features that describe the intended behaviour of '<%= @project %>'. You will then write failing tests by writing steps to test the b$
|
4
|
+
|
5
|
+
You will then want to create a '<%= @project %>' cookbook, and write recipes that make your tests pass. Upload your cookbook to the Opscode Platform, and then push your cucumber-ch$
|
6
|
+
|
7
|
+
cucumber-chef upload <%= @project %>
|
8
|
+
|
9
|
+
Then run your tests with:
|
10
|
+
|
11
|
+
cucumber-chef test <%= @project %>
|
12
|
+
|
13
|
+
For an example feature, take a look at ./<%= @project %>/features/example.feature
|
14
|
+
|
15
|
+
For an example step definition, look at ./<%= @project %>/features/example.feature
|
16
|
+
|
17
|
+
To get started, you'll need to configure cucumber-chef to use your own Opscode Chef platform credentials, and AWS EC2 keys. You can generate a sample config with:
|
18
|
+
|
19
|
+
cucumber-chef genconfig
|
20
|
+
|
21
|
+
This will drop a .cucumber-chef config file in the home directory of the user with which you ran the cucumber-chef command. You'll need to edit the file in order to carry out setup, upload or test functionality.
|
22
|
+
|
23
|
+
One you've got a configuration in place, run:
|
24
|
+
|
25
|
+
cucumber-chef setup
|
26
|
+
|
27
|
+
This will create what we call a 'test lab' in EC2 in which tests will be run.
|
28
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
bash -c '
|
2
|
+
if [ ! -f /usr/bin/chef-client ]; then
|
3
|
+
apt-get update
|
4
|
+
apt-get install -y ruby ruby1.8-dev build-essential wget libruby-extras libruby1.8-extras
|
5
|
+
cd /tmp
|
6
|
+
wget http://production.cf.rubygems.org/rubygems/rubygems-1.3.7.tgz
|
7
|
+
tar zxf rubygems-1.3.7.tgz
|
8
|
+
cd rubygems-1.3.7
|
9
|
+
ruby setup.rb --no-format-executable
|
10
|
+
fi
|
11
|
+
gem install ohai chef --no-rdoc --no-ri --verbose <%= '--prerelease' if @config[:prerelease] %>
|
12
|
+
|
13
|
+
mkdir -p /etc/chef
|
14
|
+
|
15
|
+
(
|
16
|
+
cat <<'EOP'
|
17
|
+
<%= IO.read(@config[:validation_key]) %>
|
18
|
+
EOP
|
19
|
+
) > /tmp/validation.pem
|
20
|
+
awk NF /tmp/validation.pem > /etc/chef/validation.pem
|
21
|
+
rm /tmp/validation.pem
|
22
|
+
|
23
|
+
(
|
24
|
+
cat <<'EOP'
|
25
|
+
log_level :info
|
26
|
+
log_location STDOUT
|
27
|
+
chef_server_url "<%= @config[:chef_server_url] %>"
|
28
|
+
validation_client_name "<%= @config[:validation_client_name] %>"
|
29
|
+
<% if @config[:chef_node_name] == nil %>
|
30
|
+
# Using default node name"
|
31
|
+
<% else %>
|
32
|
+
node_name "<%= @config[:chef_node_name] %>"
|
33
|
+
<% end %>
|
34
|
+
EOP
|
35
|
+
) > /etc/chef/client.rb
|
36
|
+
|
37
|
+
(
|
38
|
+
cat <<'EOP'
|
39
|
+
<%= { "run_list" => @run_list }.to_json %>
|
40
|
+
EOP
|
41
|
+
) > /etc/chef/first-boot.json
|
42
|
+
|
43
|
+
/usr/bin/chef-client -j /etc/chef/first-boot.json'
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'fog'
|
2
|
+
require 'socket'
|
3
|
+
require 'chef/knife'
|
4
|
+
require 'chef/knife/bootstrap'
|
5
|
+
require 'chef/json_compat'
|
6
|
+
|
7
|
+
class Chef
|
8
|
+
class Knife
|
9
|
+
class Ec2ServerCreate < Knife
|
10
|
+
|
11
|
+
attr_accessor :initial_sleep_delay
|
12
|
+
|
13
|
+
def tcp_test_ssh(hostname)
|
14
|
+
tcp_socket = TCPSocket.new(hostname, 22)
|
15
|
+
readable = IO.select([tcp_socket], nil, nil, 5)
|
16
|
+
if readable
|
17
|
+
Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
|
18
|
+
yield
|
19
|
+
true
|
20
|
+
else
|
21
|
+
false
|
22
|
+
end
|
23
|
+
rescue Errno::ETIMEDOUT
|
24
|
+
false
|
25
|
+
rescue Errno::ECONNREFUSED
|
26
|
+
sleep 2
|
27
|
+
false
|
28
|
+
ensure
|
29
|
+
tcp_socket && tcp_socket.close
|
30
|
+
end
|
31
|
+
|
32
|
+
def run
|
33
|
+
require 'fog'
|
34
|
+
require 'highline'
|
35
|
+
require 'net/ssh/multi'
|
36
|
+
require 'readline'
|
37
|
+
|
38
|
+
$stdout.sync = true
|
39
|
+
|
40
|
+
connection = Fog::Compute.new(
|
41
|
+
:provider => 'AWS',
|
42
|
+
:aws_access_key_id => Chef::Config[:knife][:aws_access_key_id],
|
43
|
+
:aws_secret_access_key => Chef::Config[:knife][:aws_secret_access_key],
|
44
|
+
:region => #REGION
|
45
|
+
)
|
46
|
+
|
47
|
+
# WHAT IS THIS FOR?
|
48
|
+
ami = connection.images.get(locate_config_value(:image))
|
49
|
+
|
50
|
+
server_def = {
|
51
|
+
:image_id => locate_config_value(:image),
|
52
|
+
:groups => config[:security_groups],
|
53
|
+
:flavor_id => locate_config_value(:flavor),
|
54
|
+
:key_name => Chef::Config[:knife][:aws_ssh_key_id],
|
55
|
+
:availability_zone => Chef::Config[:knife][:availability_zone]
|
56
|
+
}
|
57
|
+
|
58
|
+
server = connection.servers.create(server_def)
|
59
|
+
|
60
|
+
puts "Instance ID: #{server.id}"
|
61
|
+
print "\n#{h.color("Waiting for server", :magenta)}"
|
62
|
+
|
63
|
+
# wait for it to be ready to do stuff
|
64
|
+
server.wait_for { print "."; ready? }
|
65
|
+
|
66
|
+
puts("\n")
|
67
|
+
|
68
|
+
puts "Public IP Address #{server.public_ip_address}"
|
69
|
+
|
70
|
+
print "\n#{h.color("Waiting for sshd", :magenta)}"
|
71
|
+
|
72
|
+
print(".") until tcp_test_ssh(server.dns_name) { sleep @initial_sleep_delay ||= 10; puts("done") }
|
73
|
+
|
74
|
+
bootstrap_for_node(server).run
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
def bootstrap_for_node(server)
|
79
|
+
bootstrap = Chef::Knife::Bootstrap.new
|
80
|
+
bootstrap.name_args = [server.dns_name]
|
81
|
+
bootstrap.config[:run_list] = config[:run_list]
|
82
|
+
bootstrap.config[:ssh_user] = config[:ssh_user]
|
83
|
+
bootstrap.config[:identity_file] = config[:identity_file]
|
84
|
+
bootstrap.config[:chef_node_name] = config[:chef_node_name] || server.id
|
85
|
+
bootstrap.config[:prerelease] = config[:prerelease]
|
86
|
+
bootstrap.config[:distro] = locate_config_value(:distro)
|
87
|
+
bootstrap.config[:use_sudo] = true
|
88
|
+
bootstrap.config[:template_file] = locate_config_value(:template_file)
|
89
|
+
bootstrap.config[:environment] = config[:environment]
|
90
|
+
bootstrap
|
91
|
+
end
|
92
|
+
|
93
|
+
def locate_config_value(key)
|
94
|
+
key = key.to_sym
|
95
|
+
Chef::Config[:knife][key] || config[key]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,270 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
require File.join(File.dirname(__FILE__), "../../lib/cucumber-chef")
|
4
|
+
|
5
|
+
def tcp_test_ssh(hostname)
|
6
|
+
tcp_socket = TCPSocket.new(hostname, 22)
|
7
|
+
IO.select([tcp_socket], nil, nil, 5)
|
8
|
+
rescue Errno::ETIMEDOUT
|
9
|
+
false
|
10
|
+
rescue Errno::EPERM
|
11
|
+
false
|
12
|
+
rescue Errno::ECONNREFUSED
|
13
|
+
sleep 2
|
14
|
+
false
|
15
|
+
# This happens on EC2 quite often
|
16
|
+
rescue Errno::EHOSTUNREACH
|
17
|
+
sleep 2
|
18
|
+
false
|
19
|
+
ensure
|
20
|
+
tcp_socket && tcp_socket.close
|
21
|
+
end
|
22
|
+
|
23
|
+
describe Cucumber::Chef::Config do
|
24
|
+
describe "when configuration is missing" do
|
25
|
+
it "should raise if it cannot find a configuration" do
|
26
|
+
begin
|
27
|
+
chef_dir = File.expand_path("~/.chef")
|
28
|
+
config_file = File.join(chef_dir, "knife.rb")
|
29
|
+
FileUtils.mv(config_file, File.join(chef_dir, "knife.rb.bak"))
|
30
|
+
expect { subject.config }.to raise_error(Cucumber::Chef::ConfigError)
|
31
|
+
ensure
|
32
|
+
FileUtils.mv(File.join(chef_dir, "knife.rb.bak"), config_file)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "when configuration is invalid" do
|
38
|
+
config_dir = File.join(File.dirname(__FILE__), "../../.chef")
|
39
|
+
|
40
|
+
before(:all) { FileUtils.mkdir_p(config_dir) }
|
41
|
+
after(:all) { FileUtils.rm_rf(config_dir) }
|
42
|
+
|
43
|
+
it "should complain about missing keys" do
|
44
|
+
config = "node_name ''"
|
45
|
+
File.open(Pathname(config_dir) + "knife.rb", 'w') { |f| f.puts config }
|
46
|
+
values, missing_keys = subject.display
|
47
|
+
missing_keys.should include("node_name")
|
48
|
+
missing_keys.should include("knife[:aws_access_key_id]")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "when configuration is valid" do
|
53
|
+
it "should find the configuration" do
|
54
|
+
values, missing_keys = subject.display
|
55
|
+
missing_keys.should be_empty
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should display the configuration values" do
|
59
|
+
values, missing_keys = subject.display
|
60
|
+
output = values.join("\n")
|
61
|
+
output.should match(/node_name:/)
|
62
|
+
output.should match(/knife\[:aws_secret_access_key\]:/)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe Cucumber::Chef::Provisioner do
|
68
|
+
before(:all) do
|
69
|
+
@config = subject.config
|
70
|
+
@config[:mode] = "test"
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "verify_opscode_platform_credentials" do
|
74
|
+
describe "when configuration is invalid" do
|
75
|
+
config_dir = File.join(File.dirname(__FILE__), "../../.chef")
|
76
|
+
knife_file = File.join(config_dir, "knife.rb")
|
77
|
+
|
78
|
+
before(:all) do
|
79
|
+
FileUtils.mkdir_p(config_dir)
|
80
|
+
end
|
81
|
+
|
82
|
+
after(:all) do
|
83
|
+
FileUtils.rm_rf(config_dir)
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "when node name is missing" do
|
87
|
+
it "should raise" do
|
88
|
+
config = "node_name ''"
|
89
|
+
File.open(knife_file, 'w') { |f| f.puts config }
|
90
|
+
expect {
|
91
|
+
subject.verify_opscode_platform_credentials(subject.config)
|
92
|
+
}.to raise_error(Cucumber::Chef::ProvisionerError)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "when node name is invalid" do
|
97
|
+
it "should raise" do
|
98
|
+
config = "node_name 'REALLYBOGUSORGNAME'"
|
99
|
+
File.open(knife_file, 'w') { |f| f.puts config }
|
100
|
+
expect {
|
101
|
+
subject.verify_opscode_platform_credentials(subject.config)
|
102
|
+
}.to raise_error(Cucumber::Chef::ProvisionerError)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "when configuration is valid" do
|
108
|
+
it "should not raise" do
|
109
|
+
subject.verify_opscode_platform_credentials(subject.config)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "verify_aws_credentials" do
|
115
|
+
describe "when configuration is invalid" do
|
116
|
+
config_dir = File.join(File.dirname(__FILE__), "../../.chef")
|
117
|
+
knife_file = File.join(config_dir, "knife.rb")
|
118
|
+
|
119
|
+
before(:all) do
|
120
|
+
FileUtils.mkdir_p(config_dir)
|
121
|
+
end
|
122
|
+
|
123
|
+
after(:all) do
|
124
|
+
FileUtils.rm_rf(config_dir)
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "when configuration is invalid" do
|
128
|
+
it "should raise" do
|
129
|
+
config = "knife[:aws_access_key_id] = ''"
|
130
|
+
File.open(knife_file, 'w') { |f| f.puts config }
|
131
|
+
expect {
|
132
|
+
subject.verify_aws_credentials(subject.config)
|
133
|
+
}.to raise_error(Cucumber::Chef::ProvisionerError)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "when configuration is valid" do
|
139
|
+
it "should not raise" do
|
140
|
+
subject.verify_aws_credentials(subject.config)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "build_test_lab" do
|
146
|
+
after(:each) do
|
147
|
+
config = @config[:knife]
|
148
|
+
connection = Fog::Compute.new(:provider => 'AWS',
|
149
|
+
:aws_access_key_id => config[:aws_access_key_id],
|
150
|
+
:aws_secret_access_key => config[:aws_secret_access_key],
|
151
|
+
:region => config[:region])
|
152
|
+
connection.servers.each do |s|
|
153
|
+
s.destroy if s.tags['cucumber-chef'] == 'test' && s.state == 'running'
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should spin up a ec2 instance", :slow => true do
|
158
|
+
output = StringIO.new
|
159
|
+
subject.build_test_lab(@config, output)
|
160
|
+
output.rewind
|
161
|
+
output.read.should match(/Platform provisioned/)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should only spin up one ec2 instance", :slow => true do
|
165
|
+
subject.build_test_lab(@config, StringIO.new)
|
166
|
+
expect {
|
167
|
+
subject.build_test_lab(@config, StringIO.new)
|
168
|
+
}.to raise_error(Cucumber::Chef::ProvisionerError)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "upload_cookbook" do
|
173
|
+
before(:each) do
|
174
|
+
begin
|
175
|
+
cookbook_path = File.expand_path("cookbooks/cucumber-chef")
|
176
|
+
version_loader = ::Chef::Cookbook::CookbookVersionLoader.new(cookbook_path)
|
177
|
+
version_loader.load_cookbooks
|
178
|
+
version = version_loader.cookbook_version
|
179
|
+
version.destroy
|
180
|
+
rescue Net::HTTPServerException => err
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should upload the cucumber-chef cookbook" do
|
185
|
+
subject.upload_cookbook(@config)
|
186
|
+
::Chef::CookbookVersion.list["cucumber-chef"].should be
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "upload_role" do
|
191
|
+
before(:each) do
|
192
|
+
begin
|
193
|
+
role_path = File.expand_path("cookbooks/cucumber-chef/roles")
|
194
|
+
::Chef::Config[:role_path] = role_path
|
195
|
+
role = ::Chef::Role.from_disk("test_lab_test")
|
196
|
+
role.destroy
|
197
|
+
rescue Net::HTTPServerException => err
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should upload the test_lab role" do
|
202
|
+
subject.upload_role(@config)
|
203
|
+
::Chef::Role.list["test_lab_test"].should be
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "bootstrap_node" do
|
208
|
+
before(:each) do
|
209
|
+
server = subject.build_test_lab(@config, StringIO.new)
|
210
|
+
@dns_name = server.dns_name
|
211
|
+
puts "Hanging around..." until tcp_test_ssh(server.public_ip_address)
|
212
|
+
puts "Got ssh..."
|
213
|
+
sleep(10)
|
214
|
+
subject.upload_cookbook(@config)
|
215
|
+
subject.upload_role(@config)
|
216
|
+
end
|
217
|
+
|
218
|
+
after(:each) do
|
219
|
+
config = @config[:knife]
|
220
|
+
connection = Fog::Compute.new(:provider => 'AWS',
|
221
|
+
:aws_access_key_id => config[:aws_access_key_id],
|
222
|
+
:aws_secret_access_key => config[:aws_secret_access_key],
|
223
|
+
:region => config[:region])
|
224
|
+
connection.servers.each do |s|
|
225
|
+
s.destroy if s.tags['cucumber-chef'] == 'test' && s.state == 'running'
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should set up platform as a chef client and apply test-lab role" do
|
230
|
+
bootstrapper = subject.bootstrap_node(@dns_name, @config)
|
231
|
+
bootstrapper.run
|
232
|
+
# DEBUG: puts bootstrapper.ui.stdout.string
|
233
|
+
node = ::Chef::Node.load("cucumber-chef-test-lab")
|
234
|
+
node.run_list.to_s.should match(/role\[test_lab_test\]/)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "build_controller" do
|
239
|
+
|
240
|
+
before(:each) do
|
241
|
+
server = subject.build_test_lab(@config, StringIO.new)
|
242
|
+
@dns_name = server.dns_name
|
243
|
+
puts "Hanging around..." until tcp_test_ssh(server.public_ip_address)
|
244
|
+
puts "Got ssh..."
|
245
|
+
sleep(10)
|
246
|
+
subject.upload_cookbook(@config)
|
247
|
+
subject.upload_role(@config)
|
248
|
+
subject.bootstrap_node(@dns_name, @config).run
|
249
|
+
end
|
250
|
+
|
251
|
+
after(:each) do
|
252
|
+
config = @config[:knife]
|
253
|
+
connection = Fog::Compute.new(:provider => 'AWS',
|
254
|
+
:aws_access_key_id => config[:aws_access_key_id],
|
255
|
+
:aws_secret_access_key => config[:aws_secret_access_key],
|
256
|
+
:region => config[:region])
|
257
|
+
connection.servers.each do |s|
|
258
|
+
s.destroy if s.tags['cucumber-chef'] == 'test' && s.state == 'running'
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
it "should build a cucumber-chef controller" do
|
263
|
+
controller_builder = subject.build_controller(@dns_name, @config)
|
264
|
+
controller_builder.run
|
265
|
+
puts controller_builder.ui.stdout.string
|
266
|
+
end
|
267
|
+
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|