cucumber-chef 0.4.4 → 0.5.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/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:
|