cucumber-chef 0.4.4 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/bin/cucumber-chef +34 -62
- data/cucumber-chef.gemspec +7 -3
- data/features/steps/usage_steps.rb +1 -1
- data/lib/cucumber/chef/config.rb +121 -0
- data/lib/cucumber/chef/handy.rb +1 -1
- data/lib/cucumber/chef/test_lab.rb +74 -0
- data/lib/cucumber/chef.rb +3 -98
- data/spec/unit/config_spec.rb +108 -0
- data/spec/unit/cucumber_chef_spec.rb +0 -143
- data/spec/unit/test_lab_spec.rb +61 -0
- metadata +27 -23
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/bin/cucumber-chef
CHANGED
@@ -27,46 +27,7 @@ class CucumberChef < Thor
|
|
27
27
|
File.dirname(__FILE__)
|
28
28
|
end
|
29
29
|
|
30
|
-
def initialize(args = [], options = {}, config = {})
|
31
|
-
@provisioner = ::Cucumber::Chef::Provisioner.new
|
32
|
-
super(args, options, config)
|
33
|
-
end
|
34
|
-
|
35
30
|
no_tasks do
|
36
|
-
def tcp_test_ssh(hostname)
|
37
|
-
tcp_socket = TCPSocket.new(hostname, 22)
|
38
|
-
IO.select([tcp_socket], nil, nil, 5)
|
39
|
-
rescue Errno::ETIMEDOUT
|
40
|
-
false
|
41
|
-
rescue Errno::EPERM
|
42
|
-
false
|
43
|
-
rescue Errno::ECONNREFUSED
|
44
|
-
sleep 2
|
45
|
-
false
|
46
|
-
# This happens on EC2 quite often
|
47
|
-
rescue Errno::EHOSTUNREACH
|
48
|
-
sleep 2
|
49
|
-
false
|
50
|
-
ensure
|
51
|
-
tcp_socket && tcp_socket.close
|
52
|
-
end
|
53
|
-
|
54
|
-
def get_latest_version
|
55
|
-
installed_versions = []
|
56
|
-
Gem::source_index.find_name('cucumber-chef').map do |g|
|
57
|
-
version = g.version.version
|
58
|
-
if version == ""
|
59
|
-
version = "0"
|
60
|
-
end
|
61
|
-
installed_versions << version
|
62
|
-
end
|
63
|
-
version = installed_versions.sort { |a, b| a.to_i <=> b.to_i }.last
|
64
|
-
if version == "0"
|
65
|
-
version = ""
|
66
|
-
end
|
67
|
-
return "cucumber-chef-" + version
|
68
|
-
end
|
69
|
-
|
70
31
|
def create_directory_structure(project_dir)
|
71
32
|
%w{step_definitions support}.each do |dir|
|
72
33
|
FileUtils.mkdir_p(project_dir + "features" + dir)
|
@@ -95,12 +56,6 @@ class CucumberChef < Thor
|
|
95
56
|
warn message
|
96
57
|
exit 255
|
97
58
|
end
|
98
|
-
|
99
|
-
def find_knife_config
|
100
|
-
@provisioner.config
|
101
|
-
rescue ::Cucumber::Chef::ProvisionerError => err
|
102
|
-
error(err.message)
|
103
|
-
end
|
104
59
|
end
|
105
60
|
|
106
61
|
desc "project <project name>" , "Create a project template for testing an infrastructure"
|
@@ -115,35 +70,53 @@ class CucumberChef < Thor
|
|
115
70
|
method_option :test, :type => :boolean
|
116
71
|
def setup
|
117
72
|
begin
|
118
|
-
config = find_knife_config
|
119
73
|
if options.test?
|
120
|
-
config
|
74
|
+
config = Cucumber::Chef::Config.test_config
|
121
75
|
else
|
122
|
-
config
|
76
|
+
config = Cucumber::Chef::Config.new
|
123
77
|
end
|
124
|
-
|
125
|
-
@provisioner.verify_aws_credentials(config)
|
78
|
+
config.verify
|
126
79
|
$stdout.sync
|
127
|
-
|
80
|
+
provisioner = ::Cucumber::Chef::Provisioner.new
|
81
|
+
server = provisioner.build_test_lab(config, $stdout)
|
128
82
|
sleep(10)
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
rescue ::Cucumber::Chef::
|
83
|
+
provisioner.upload_cookbook(config)
|
84
|
+
provisioner.upload_role(config)
|
85
|
+
provisioner.bootstrap_node(server.dns_name, config).run
|
86
|
+
rescue ::Cucumber::Chef::Error => err
|
133
87
|
error(err.message)
|
134
88
|
end
|
135
89
|
end
|
136
90
|
|
137
91
|
desc "displayconfig", "Display the current config from knife.rb"
|
92
|
+
method_option :test, :type => :boolean
|
138
93
|
def displayconfig
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
94
|
+
if options.test?
|
95
|
+
config = Cucumber::Chef::Config.test_config
|
96
|
+
else
|
97
|
+
config = Cucumber::Chef::Config.new
|
143
98
|
end
|
144
|
-
|
99
|
+
puts config.list.join("\n")
|
100
|
+
config.verify
|
101
|
+
rescue ::Cucumber::Chef::Error => err
|
145
102
|
error(err.message)
|
146
103
|
end
|
104
|
+
|
105
|
+
desc "info", "Display information about the current test lab"
|
106
|
+
method_option :test, :type => :boolean
|
107
|
+
def info
|
108
|
+
if options.test?
|
109
|
+
config = Cucumber::Chef::Config.test_config
|
110
|
+
else
|
111
|
+
config = Cucumber::Chef::Config.new
|
112
|
+
end
|
113
|
+
config.verify
|
114
|
+
lab = Cucumber::Chef::TestLab.new(config)
|
115
|
+
if lab.exists?
|
116
|
+
puts lab.info
|
117
|
+
else
|
118
|
+
end
|
119
|
+
end
|
147
120
|
|
148
121
|
desc "upload", "Upload a cucumber-chef test suite to the test lab platform"
|
149
122
|
def upload
|
@@ -156,7 +129,6 @@ class CucumberChef < Thor
|
|
156
129
|
puts
|
157
130
|
puts "Test results will appear here."
|
158
131
|
end
|
159
|
-
|
160
|
-
|
161
132
|
end
|
133
|
+
|
162
134
|
CucumberChef.start
|
data/cucumber-chef.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{cucumber-chef}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.5.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Stephen Nelson-Smith"]
|
12
|
-
s.date = %q{2011-06-
|
12
|
+
s.date = %q{2011-06-09}
|
13
13
|
s.default_executable = %q{cucumber-chef}
|
14
14
|
s.description = %q{Framework for behaviour-drive infrastructure development.}
|
15
15
|
s.email = %q{stephen@atalanta-systems.com}
|
@@ -59,6 +59,7 @@ Gem::Specification.new do |s|
|
|
59
59
|
"features/usage.feature",
|
60
60
|
"lib/cucumber-chef.rb",
|
61
61
|
"lib/cucumber/chef.rb",
|
62
|
+
"lib/cucumber/chef/config.rb",
|
62
63
|
"lib/cucumber/chef/handy.rb",
|
63
64
|
"lib/cucumber/chef/templates/controller.erb",
|
64
65
|
"lib/cucumber/chef/templates/env.rb",
|
@@ -66,9 +67,12 @@ Gem::Specification.new do |s|
|
|
66
67
|
"lib/cucumber/chef/templates/example_step.erb",
|
67
68
|
"lib/cucumber/chef/templates/readme.erb",
|
68
69
|
"lib/cucumber/chef/templates/ubuntu10.04-gems.erb",
|
70
|
+
"lib/cucumber/chef/test_lab.rb",
|
69
71
|
"lib/cucumber/chef/version.rb",
|
70
72
|
"lib/cucumber/ec2_server_create.rb",
|
71
|
-
"spec/unit/
|
73
|
+
"spec/unit/config_spec.rb",
|
74
|
+
"spec/unit/cucumber_chef_spec.rb",
|
75
|
+
"spec/unit/test_lab_spec.rb"
|
72
76
|
]
|
73
77
|
s.homepage = %q{http://github.com/atalanta/cucumber-chef}
|
74
78
|
s.licenses = ["MIT"]
|
@@ -22,7 +22,7 @@ When /^the config file contains invalid credentials$/ do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
Then /^I should be alerted that my credentials are invalid$/ do
|
25
|
-
@output.should
|
25
|
+
@output.should match(/Invalid Opscode platform credentials. Please check/m)
|
26
26
|
end
|
27
27
|
|
28
28
|
When /^I create a project called test_project$/ do
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Chef
|
3
|
+
class ConfigError < Error ; end
|
4
|
+
|
5
|
+
class Config
|
6
|
+
KEYS = %w[mode node_name chef_server_url client_key validation_key validation_client_name]
|
7
|
+
KNIFE_KEYS = %w[aws_access_key_id aws_secret_access_key region availability_zone aws_ssh_key_id identity_file]
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
config[:mode] = "user"
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.test_config
|
14
|
+
config = self.new
|
15
|
+
config[:mode] = "test"
|
16
|
+
config
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](key)
|
20
|
+
config[key]
|
21
|
+
end
|
22
|
+
|
23
|
+
def []=(key, value)
|
24
|
+
config[key] = value
|
25
|
+
end
|
26
|
+
|
27
|
+
def config
|
28
|
+
unless @config
|
29
|
+
full_path = Dir.pwd.split(File::SEPARATOR)
|
30
|
+
(full_path.length - 1).downto(0) do |i|
|
31
|
+
knife_file = File.join(full_path[0..i] + [".chef", "knife.rb"])
|
32
|
+
if File.exist?(knife_file)
|
33
|
+
::Chef::Config.from_file(knife_file)
|
34
|
+
@config = ::Chef::Config
|
35
|
+
return @config
|
36
|
+
end
|
37
|
+
end
|
38
|
+
raise ConfigError.new("Couldn't find knife.rb")
|
39
|
+
end
|
40
|
+
@config
|
41
|
+
end
|
42
|
+
|
43
|
+
def list
|
44
|
+
values = []
|
45
|
+
KEYS.each do |key|
|
46
|
+
value = config[key]
|
47
|
+
values << "#{key}: #{value}"
|
48
|
+
end
|
49
|
+
KNIFE_KEYS.each do |key|
|
50
|
+
value = config[:knife][key.to_sym]
|
51
|
+
values << "knife[:#{key}]: #{value}"
|
52
|
+
end
|
53
|
+
values
|
54
|
+
end
|
55
|
+
|
56
|
+
def verify
|
57
|
+
@errors = []
|
58
|
+
verify_orgname
|
59
|
+
verify_opscode_user
|
60
|
+
verify_keys
|
61
|
+
verify_opscode_platform_credentials
|
62
|
+
verify_aws_credentials
|
63
|
+
if @errors.size > 0
|
64
|
+
raise ConfigError.new(@errors.join("\n"))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def verify_orgname
|
71
|
+
if !ENV["ORGNAME"] || ENV["ORGNAME"] == ""
|
72
|
+
@errors << "Your organisation must be set using the environment variable ORGNAME."
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def verify_opscode_user
|
77
|
+
if !ENV["OPSCODE_USER"] || ENV["OPSCODE_USER"] == ""
|
78
|
+
@errors << "Your Opscode platform username must be set using the environment variable OPSCODE_USER."
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def verify_keys
|
83
|
+
missing_keys = []
|
84
|
+
KEYS.each do |key|
|
85
|
+
value = config[key]
|
86
|
+
missing_keys << key unless value && value != ""
|
87
|
+
end
|
88
|
+
KNIFE_KEYS.each do |key|
|
89
|
+
missing_keys << "knife[:#{key}]" unless value = config[:knife][key.to_sym]
|
90
|
+
end
|
91
|
+
if missing_keys.size > 0
|
92
|
+
@errors << "Incomplete config file, please specify: #{missing_keys.join(", ")}."
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def verify_opscode_platform_credentials
|
97
|
+
username = config['node_name']
|
98
|
+
if username
|
99
|
+
req = Net::HTTP.new('community.opscode.com', 80)
|
100
|
+
code = req.request_head("/users/#{username}").code
|
101
|
+
end
|
102
|
+
if username == "" || code != "200"
|
103
|
+
@errors << "Invalid Opscode platform credentials. Please check."
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def verify_aws_credentials
|
108
|
+
if config[:knife][:aws_access_key_id] && config[:knife][:aws_secret_access_key]
|
109
|
+
compute = Fog::Compute.new(:provider => 'AWS',
|
110
|
+
:aws_access_key_id => config[:knife][:aws_access_key_id],
|
111
|
+
:aws_secret_access_key => config[:knife][:aws_secret_access_key])
|
112
|
+
compute.describe_availability_zones
|
113
|
+
else
|
114
|
+
@errors << "Invalid AWS credentials. Please check."
|
115
|
+
end
|
116
|
+
rescue Fog::Service::Error => err
|
117
|
+
@errors << "Invalid AWS credentials. Please check."
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/lib/cucumber/chef/handy.rb
CHANGED
@@ -0,0 +1,74 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Chef
|
3
|
+
class TestLabError < Error ; end
|
4
|
+
|
5
|
+
class TestLab
|
6
|
+
def initialize(config)
|
7
|
+
@config = config
|
8
|
+
@connection =
|
9
|
+
Fog::Compute.new(:provider => 'AWS',
|
10
|
+
:aws_access_key_id => @config[:knife][:aws_access_key_id],
|
11
|
+
:aws_secret_access_key => @config[:knife][:aws_secret_access_key],
|
12
|
+
:region => @config[:knife][:region])
|
13
|
+
@mode = @config[:mode]
|
14
|
+
end
|
15
|
+
|
16
|
+
def build(output)
|
17
|
+
if exists?
|
18
|
+
raise TestLabError.new("A test lab already exists using the AWS credentials you supplied")
|
19
|
+
end
|
20
|
+
server_definition = {
|
21
|
+
:image_id => "ami-339ca947",
|
22
|
+
:groups => "default",
|
23
|
+
:flavor_id => "m1.small",
|
24
|
+
:key_name => @config[:knife][:aws_ssh_key_id],
|
25
|
+
:availability_zone => @config[:knife][:availability_zone],
|
26
|
+
:tags => {"purpose" => "cucumber-chef"},
|
27
|
+
:identity_file => @config[:knife][:identity_file]
|
28
|
+
}
|
29
|
+
@server = @connection.servers.create(server_definition)
|
30
|
+
output.puts "Provisioning cucumber-chef test lab platform."
|
31
|
+
output.print "Waiting for server"
|
32
|
+
@server.wait_for { output.print "."; ready? }
|
33
|
+
output.puts("\n")
|
34
|
+
tag_server
|
35
|
+
output.puts "Instance ID: #{@server.id} ; IP Address #{@server.public_ip_address}"
|
36
|
+
output.puts "Platform provisioned. Run cucumber-chef project to get started."
|
37
|
+
@server
|
38
|
+
end
|
39
|
+
|
40
|
+
def destroy
|
41
|
+
@connection.servers.each do |s|
|
42
|
+
s.destroy if s.tags['cucumber-chef'] == @mode && s.state == 'running'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def exists?
|
47
|
+
running_labs_count > 0
|
48
|
+
end
|
49
|
+
|
50
|
+
def info
|
51
|
+
if exists?
|
52
|
+
query = ::Chef::Search::Query.new
|
53
|
+
node, offset, total = query.search("node", URI.escape("roles:test_lab_test"))
|
54
|
+
node.first && node.first[:ec2][:public_ipv4]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def tag_server
|
60
|
+
tag = @connection.tags.new
|
61
|
+
tag.resource_id = @server.id
|
62
|
+
tag.key = "cucumber-chef"
|
63
|
+
tag.value = @mode
|
64
|
+
tag.save
|
65
|
+
end
|
66
|
+
|
67
|
+
def running_labs_count
|
68
|
+
@connection.servers.select do |s|
|
69
|
+
s.tags["cucumber-chef"] == @mode && s.state == "running"
|
70
|
+
end.size
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/cucumber/chef.rb
CHANGED
@@ -14,44 +14,8 @@ module Cucumber
|
|
14
14
|
module Chef
|
15
15
|
class Error < StandardError ; end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
KEYS = %w[node_name chef_server_url client_key validation_key validation_client_name]
|
20
|
-
KNIFE_KEYS = %w[aws_access_key_id aws_secret_access_key region availability_zone aws_ssh_key_id identity_file]
|
21
|
-
|
22
|
-
def config
|
23
|
-
full_path = Dir.pwd.split(File::SEPARATOR)
|
24
|
-
(full_path.length - 1).downto(0) do |i|
|
25
|
-
knife_file = File.join(full_path[0..i] + [".chef", "knife.rb"])
|
26
|
-
if File.exist?(knife_file)
|
27
|
-
::Chef::Config.from_file(knife_file)
|
28
|
-
return ::Chef::Config
|
29
|
-
end
|
30
|
-
end
|
31
|
-
raise ConfigError.new("Couldn't find knife.rb")
|
32
|
-
end
|
33
|
-
|
34
|
-
def display
|
35
|
-
current_config = config
|
36
|
-
values, missing_keys = [], []
|
37
|
-
KEYS.each do |key|
|
38
|
-
value = current_config[key]
|
39
|
-
if value && value != ""
|
40
|
-
values << "#{key}: #{value}"
|
41
|
-
else
|
42
|
-
missing_keys << key
|
43
|
-
end
|
44
|
-
end
|
45
|
-
KNIFE_KEYS.each do |key|
|
46
|
-
if value = current_config[:knife][key.to_sym]
|
47
|
-
values << "knife[:#{key}]: #{value}"
|
48
|
-
else
|
49
|
-
missing_keys << "knife[:#{key}]"
|
50
|
-
end
|
51
|
-
end
|
52
|
-
[values, missing_keys]
|
53
|
-
end
|
54
|
-
end
|
17
|
+
autoload :Config, "cucumber/chef/config"
|
18
|
+
autoload :TestLab, "cucumber/chef/test_lab"
|
55
19
|
|
56
20
|
class ProvisionerError < Error ; end
|
57
21
|
class Provisioner
|
@@ -63,27 +27,6 @@ module Cucumber
|
|
63
27
|
Config.new.config
|
64
28
|
end
|
65
29
|
|
66
|
-
def running_labs(connection, mode)
|
67
|
-
connection.servers.select {|s| s.tags['cucumber-chef'] == mode && s.state == 'running'}
|
68
|
-
end
|
69
|
-
|
70
|
-
def lab_exists?(connection, mode)
|
71
|
-
number_of_labs = running_labs(connection, mode).size
|
72
|
-
if number_of_labs > 0
|
73
|
-
return true
|
74
|
-
else
|
75
|
-
return false
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def tag_server(connection, id, tag)
|
80
|
-
t = connection.tags.new
|
81
|
-
t.resource_id = id
|
82
|
-
t.key = "cucumber-chef"
|
83
|
-
t.value = tag
|
84
|
-
t.save
|
85
|
-
end
|
86
|
-
|
87
30
|
def bootstrap_node(dns_name, config)
|
88
31
|
template_file = File.join(File.dirname(__FILE__),
|
89
32
|
"chef/templates/ubuntu10.04-gems.erb")
|
@@ -123,26 +66,6 @@ module Cucumber
|
|
123
66
|
bootstrap
|
124
67
|
end
|
125
68
|
|
126
|
-
def verify_opscode_platform_credentials(config)
|
127
|
-
username = config['node_name']
|
128
|
-
if username
|
129
|
-
req = Net::HTTP.new('community.opscode.com', 80)
|
130
|
-
code = req.request_head("/users/#{username}").code
|
131
|
-
end
|
132
|
-
if username == "" || code != "200"
|
133
|
-
raise ProvisionerError.new("Invalid Opscode platform credentials. Please check.")
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
def verify_aws_credentials(config)
|
138
|
-
compute = Fog::Compute.new(:provider => 'AWS',
|
139
|
-
:aws_access_key_id => config[:knife][:aws_access_key_id],
|
140
|
-
:aws_secret_access_key => config[:knife][:aws_secret_access_key])
|
141
|
-
compute.describe_availability_zones
|
142
|
-
rescue Fog::Service::Error => err
|
143
|
-
raise ProvisionerError.new("Invalid AWS credentials. Please check.")
|
144
|
-
end
|
145
|
-
|
146
69
|
def upload_cookbook(config)
|
147
70
|
version_loader = ::Chef::Cookbook::CookbookVersionLoader.new(@cookbook_path)
|
148
71
|
version_loader.load_cookbooks
|
@@ -161,25 +84,7 @@ module Cucumber
|
|
161
84
|
end
|
162
85
|
|
163
86
|
def build_test_lab(config, output)
|
164
|
-
|
165
|
-
:aws_access_key_id => config[:knife][:aws_access_key_id],
|
166
|
-
:aws_secret_access_key => config[:knife][:aws_secret_access_key],
|
167
|
-
:region => config[:knife][:region])
|
168
|
-
mode = config["mode"]
|
169
|
-
if lab_exists?(connection, mode)
|
170
|
-
raise ProvisionerError.new("A test lab already exists using the AWS credentials you supplied")
|
171
|
-
end
|
172
|
-
ami = connection.images.get("ami-339ca947")
|
173
|
-
server_def = { :image_id => "ami-339ca947", :groups => "default", :flavor_id => "m1.small", :key_name => config[:knife][:aws_ssh_key_id], :availability_zone => config[:knife][:availability_zone], :tags => {"purpose" => "cucumber-chef"}, :identity_file => config[:knife][:identity_file] }
|
174
|
-
server = connection.servers.create(server_def)
|
175
|
-
output.puts "Provisioning cucumber-chef test lab platform."
|
176
|
-
output.print "Waiting for server"
|
177
|
-
server.wait_for { output.print "."; ready? }
|
178
|
-
output.puts("\n")
|
179
|
-
tag_server(connection, server.id, config["mode"])
|
180
|
-
output.puts "Instance ID: #{server.id} ; IP Address #{server.public_ip_address}"
|
181
|
-
output.puts "Platform provisioned. Run cucumber-chef project to get started."
|
182
|
-
server
|
87
|
+
TestLab.new(config).build(output)
|
183
88
|
end
|
184
89
|
end
|
185
90
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
require File.join(File.dirname(__FILE__), "../../lib/cucumber-chef")
|
4
|
+
|
5
|
+
describe Cucumber::Chef::Config do
|
6
|
+
before(:all) do
|
7
|
+
@orgname = ENV["ORGNAME"]
|
8
|
+
@opscode_user = ENV["OPSCODE_USER"]
|
9
|
+
end
|
10
|
+
|
11
|
+
after(:each) do
|
12
|
+
ENV["ORGNAME"] = @orgname
|
13
|
+
ENV["OPSCODE_USER"] = @opscode_user
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "verification" do
|
17
|
+
describe "when ORGNAME is not set" do
|
18
|
+
it "should raise" do
|
19
|
+
ENV["ORGNAME"] = ""
|
20
|
+
expect {
|
21
|
+
subject.verify
|
22
|
+
}.to raise_error(Cucumber::Chef::ConfigError, /ORGNAME/)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "when OPSCODE_USER is not set" do
|
27
|
+
it "should raise" do
|
28
|
+
ENV["OPSCODE_USER"] = ""
|
29
|
+
expect {
|
30
|
+
subject.verify
|
31
|
+
}.to raise_error(Cucumber::Chef::ConfigError, /OPSCODE_USER/)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "when configuration is invalid" do
|
36
|
+
it "should complain about missing keys" do
|
37
|
+
subject.config[:chef_server_url] = nil
|
38
|
+
subject.config[:knife][:aws_access_key_id] = nil
|
39
|
+
expect {
|
40
|
+
subject.verify
|
41
|
+
}.to raise_error(Cucumber::Chef::ConfigError, /chef_server_url.*aws_access_key_id/)
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "when node name is invalid" do
|
45
|
+
it "should raise" do
|
46
|
+
ENV["OPSCODE_USER"] = "REALLYBOGUSORGNAME"
|
47
|
+
expect {
|
48
|
+
subject.verify
|
49
|
+
}.to raise_error(Cucumber::Chef::ConfigError, /Opscode platform credentials/)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "when aws_access_key_id is empty" do
|
54
|
+
it "should raise" do
|
55
|
+
subject.config[:knife][:aws_access_key_id] = "bogus"
|
56
|
+
expect {
|
57
|
+
subject.verify
|
58
|
+
}.to raise_error(Cucumber::Chef::ConfigError, /AWS credentials/)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "when configuration is valid" do
|
64
|
+
it "should not raise" do
|
65
|
+
subject.verify
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "when knife.rb is missing" do
|
71
|
+
it "should raise" do
|
72
|
+
begin
|
73
|
+
chef_dir = Pathname("~/.chef").expand_path
|
74
|
+
(chef_dir + "knife.rb").rename(chef_dir + "knife.rb.bak")
|
75
|
+
config_file = chef_dir + "knife.rb"
|
76
|
+
expect { subject.config }.to raise_error(Cucumber::Chef::ConfigError)
|
77
|
+
ensure
|
78
|
+
(chef_dir + "knife.rb.bak").rename(chef_dir + "knife.rb")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "when configuration is valid" do
|
84
|
+
it "should list the configuration values" do
|
85
|
+
output = subject.list.join("\n")
|
86
|
+
output.should match(/node_name:/)
|
87
|
+
output.should match(/knife\[:aws_secret_access_key\]:/)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should return the configuration values" do
|
91
|
+
subject[:node_name].should == @opscode_user
|
92
|
+
subject[:knife][:ssh_user].should == "ubuntu"
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should allow setting configuration values" do
|
96
|
+
subject[:mode] = "blah"
|
97
|
+
subject[:knife][:aws_access_key_id] = "bogus"
|
98
|
+
subject[:mode].should == "blah"
|
99
|
+
subject[:knife][:aws_access_key_id].should == "bogus"
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should provide a method for getting a test mode configuration" do
|
103
|
+
config = Cucumber::Chef::Config.test_config
|
104
|
+
config[:mode].should == "test"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
@@ -20,155 +20,12 @@ ensure
|
|
20
20
|
tcp_socket && tcp_socket.close
|
21
21
|
end
|
22
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
23
|
describe Cucumber::Chef::Provisioner do
|
68
24
|
before(:all) do
|
69
25
|
@config = subject.config
|
70
26
|
@config[:mode] = "test"
|
71
27
|
end
|
72
28
|
|
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
29
|
describe "upload_cookbook" do
|
173
30
|
before(:each) do
|
174
31
|
begin
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
require File.join(File.dirname(__FILE__), "../../lib/cucumber-chef")
|
4
|
+
|
5
|
+
describe Cucumber::Chef::TestLab do
|
6
|
+
before(:all) do
|
7
|
+
@config = Cucumber::Chef::Config.new.config
|
8
|
+
@config[:mode] = "test"
|
9
|
+
end
|
10
|
+
|
11
|
+
subject { Cucumber::Chef::TestLab.new(@config) }
|
12
|
+
|
13
|
+
describe "build" do
|
14
|
+
after(:each) { subject.destroy }
|
15
|
+
|
16
|
+
it "should spin up an ec2 instance", :slow => true do
|
17
|
+
output = StringIO.new
|
18
|
+
subject.build(output)
|
19
|
+
output.rewind
|
20
|
+
output.read.should match(/Platform provisioned/)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should only spin up one ec2 instance", :slow => true do
|
24
|
+
subject.build(StringIO.new)
|
25
|
+
expect {
|
26
|
+
subject.build(StringIO.new)
|
27
|
+
}.to raise_error(Cucumber::Chef::TestLabError)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "destroy" do
|
33
|
+
it "should destroy the running ec2 instance", :slow => true do
|
34
|
+
subject.build(StringIO.new)
|
35
|
+
subject.destroy
|
36
|
+
subject.exists?.should_not be
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "against a bootstrapped lab" do
|
41
|
+
before(:each) do
|
42
|
+
provisioner = Cucumber::Chef::Provisioner.new
|
43
|
+
server = provisioner.build_test_lab(@config, StringIO.new)
|
44
|
+
@dns_name = server.dns_name
|
45
|
+
@public_ip_address = server.public_ip_address
|
46
|
+
puts "Hanging around..." until tcp_test_ssh(server.public_ip_address)
|
47
|
+
puts "Got ssh..."
|
48
|
+
sleep(10)
|
49
|
+
provisioner.upload_cookbook(@config)
|
50
|
+
provisioner.upload_role(@config)
|
51
|
+
provisioner.bootstrap_node(@dns_name, @config).run
|
52
|
+
end
|
53
|
+
|
54
|
+
after(:each) { subject.destroy }
|
55
|
+
|
56
|
+
it "should report its public ip address", :slow => true do
|
57
|
+
subject.info.should == @public_ip_address
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cucumber-chef
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-06-
|
12
|
+
date: 2011-06-09 00:00:00.000000000 +00:00
|
13
13
|
default_executable: cucumber-chef
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: chef
|
17
|
-
requirement: &
|
17
|
+
requirement: &24043900 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: 0.10.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *24043900
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: cucumber
|
28
|
-
requirement: &
|
28
|
+
requirement: &24043420 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *24043420
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: cucumber-nagios
|
39
|
-
requirement: &
|
39
|
+
requirement: &24042940 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ! '>='
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: '0'
|
45
45
|
type: :runtime
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *24042940
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: rspec
|
50
|
-
requirement: &
|
50
|
+
requirement: &24042460 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ! '>='
|
@@ -55,10 +55,10 @@ dependencies:
|
|
55
55
|
version: '0'
|
56
56
|
type: :runtime
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *24042460
|
59
59
|
- !ruby/object:Gem::Dependency
|
60
60
|
name: fog
|
61
|
-
requirement: &
|
61
|
+
requirement: &24041980 !ruby/object:Gem::Requirement
|
62
62
|
none: false
|
63
63
|
requirements:
|
64
64
|
- - ! '>='
|
@@ -66,10 +66,10 @@ dependencies:
|
|
66
66
|
version: '0'
|
67
67
|
type: :runtime
|
68
68
|
prerelease: false
|
69
|
-
version_requirements: *
|
69
|
+
version_requirements: *24041980
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: thor
|
72
|
-
requirement: &
|
72
|
+
requirement: &24041500 !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
75
|
- - ! '>='
|
@@ -77,10 +77,10 @@ dependencies:
|
|
77
77
|
version: '0'
|
78
78
|
type: :runtime
|
79
79
|
prerelease: false
|
80
|
-
version_requirements: *
|
80
|
+
version_requirements: *24041500
|
81
81
|
- !ruby/object:Gem::Dependency
|
82
82
|
name: awesome_print
|
83
|
-
requirement: &
|
83
|
+
requirement: &24041020 !ruby/object:Gem::Requirement
|
84
84
|
none: false
|
85
85
|
requirements:
|
86
86
|
- - ! '>='
|
@@ -88,10 +88,10 @@ dependencies:
|
|
88
88
|
version: '0'
|
89
89
|
type: :runtime
|
90
90
|
prerelease: false
|
91
|
-
version_requirements: *
|
91
|
+
version_requirements: *24041020
|
92
92
|
- !ruby/object:Gem::Dependency
|
93
93
|
name: bundler
|
94
|
-
requirement: &
|
94
|
+
requirement: &24061420 !ruby/object:Gem::Requirement
|
95
95
|
none: false
|
96
96
|
requirements:
|
97
97
|
- - ~>
|
@@ -99,10 +99,10 @@ dependencies:
|
|
99
99
|
version: 1.0.0
|
100
100
|
type: :development
|
101
101
|
prerelease: false
|
102
|
-
version_requirements: *
|
102
|
+
version_requirements: *24061420
|
103
103
|
- !ruby/object:Gem::Dependency
|
104
104
|
name: jeweler
|
105
|
-
requirement: &
|
105
|
+
requirement: &24060940 !ruby/object:Gem::Requirement
|
106
106
|
none: false
|
107
107
|
requirements:
|
108
108
|
- - ~>
|
@@ -110,10 +110,10 @@ dependencies:
|
|
110
110
|
version: 1.6.2
|
111
111
|
type: :development
|
112
112
|
prerelease: false
|
113
|
-
version_requirements: *
|
113
|
+
version_requirements: *24060940
|
114
114
|
- !ruby/object:Gem::Dependency
|
115
115
|
name: rcov
|
116
|
-
requirement: &
|
116
|
+
requirement: &24060460 !ruby/object:Gem::Requirement
|
117
117
|
none: false
|
118
118
|
requirements:
|
119
119
|
- - ! '>='
|
@@ -121,7 +121,7 @@ dependencies:
|
|
121
121
|
version: '0'
|
122
122
|
type: :development
|
123
123
|
prerelease: false
|
124
|
-
version_requirements: *
|
124
|
+
version_requirements: *24060460
|
125
125
|
description: Framework for behaviour-drive infrastructure development.
|
126
126
|
email: stephen@atalanta-systems.com
|
127
127
|
executables:
|
@@ -171,6 +171,7 @@ files:
|
|
171
171
|
- features/usage.feature
|
172
172
|
- lib/cucumber-chef.rb
|
173
173
|
- lib/cucumber/chef.rb
|
174
|
+
- lib/cucumber/chef/config.rb
|
174
175
|
- lib/cucumber/chef/handy.rb
|
175
176
|
- lib/cucumber/chef/templates/controller.erb
|
176
177
|
- lib/cucumber/chef/templates/env.rb
|
@@ -178,9 +179,12 @@ files:
|
|
178
179
|
- lib/cucumber/chef/templates/example_step.erb
|
179
180
|
- lib/cucumber/chef/templates/readme.erb
|
180
181
|
- lib/cucumber/chef/templates/ubuntu10.04-gems.erb
|
182
|
+
- lib/cucumber/chef/test_lab.rb
|
181
183
|
- lib/cucumber/chef/version.rb
|
182
184
|
- lib/cucumber/ec2_server_create.rb
|
185
|
+
- spec/unit/config_spec.rb
|
183
186
|
- spec/unit/cucumber_chef_spec.rb
|
187
|
+
- spec/unit/test_lab_spec.rb
|
184
188
|
has_rdoc: true
|
185
189
|
homepage: http://github.com/atalanta/cucumber-chef
|
186
190
|
licenses:
|
@@ -197,7 +201,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
197
201
|
version: '0'
|
198
202
|
segments:
|
199
203
|
- 0
|
200
|
-
hash:
|
204
|
+
hash: -3689892462055237010
|
201
205
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
202
206
|
none: false
|
203
207
|
requirements:
|