cucumber-chef 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -12,7 +12,6 @@ gem "cucumber-nagios", ">= 0"
12
12
  gem "rspec", ">= 0"
13
13
  gem "fog", ">= 0"
14
14
  gem "thor", ">= 0"
15
- gem "awesome_print", ">= 0"
16
15
 
17
16
  group :development do
18
17
  gem "bundler", "~> 1.0.0"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.5.1
data/bin/cucumber-chef CHANGED
@@ -23,10 +23,6 @@ GEM_DIR = Gem.default_dir
23
23
  class CucumberChef < Thor
24
24
  include Thor::Actions
25
25
 
26
- def self.source_root
27
- File.dirname(__FILE__)
28
- end
29
-
30
26
  no_tasks do
31
27
  def create_directory_structure(project_dir)
32
28
  %w{step_definitions support}.each do |dir|
@@ -35,7 +31,7 @@ class CucumberChef < Thor
35
31
  end
36
32
 
37
33
  def generate_project_skeleton(project_dir)
38
- template_dir = self.gem_root + 'lib' + 'cucumber' + 'chef' + 'templates'
34
+ template_dir = Pathname.new(__FILE__).parent.parent + 'lib' + 'cucumber' + 'chef' + 'templates'
39
35
  templates = {
40
36
  "readme.erb" => 'README',
41
37
  "example_feature.erb" => 'features/example.feature',
@@ -47,9 +43,11 @@ class CucumberChef < Thor
47
43
  project_dir + destination)
48
44
  end
49
45
  end
50
-
51
- def gem_root
52
- Pathname.new(__FILE__).parent.parent
46
+
47
+ def config
48
+ @config ||= begin
49
+ options.test? ? Cucumber::Chef::Config.test_config : Cucumber::Chef::Config.new
50
+ end
53
51
  end
54
52
 
55
53
  def error(message)
@@ -70,11 +68,6 @@ class CucumberChef < Thor
70
68
  method_option :test, :type => :boolean
71
69
  def setup
72
70
  begin
73
- if options.test?
74
- config = Cucumber::Chef::Config.test_config
75
- else
76
- config = Cucumber::Chef::Config.new
77
- end
78
71
  config.verify
79
72
  $stdout.sync
80
73
  provisioner = ::Cucumber::Chef::Provisioner.new
@@ -82,20 +75,21 @@ class CucumberChef < Thor
82
75
  sleep(10)
83
76
  provisioner.upload_cookbook(config)
84
77
  provisioner.upload_role(config)
85
- provisioner.bootstrap_node(server.dns_name, config).run
78
+ provisioner.bootstrap_node(server.dns_name, config)
86
79
  rescue ::Cucumber::Chef::Error => err
87
80
  error(err.message)
88
81
  end
82
+
89
83
  end
90
84
 
85
+ desc "connect", "Connect to a container in your test lab"
86
+ def connect
87
+ puts "Not implemented. For now, find the IP of your test lab using the info task, and connect manually."
88
+ end
89
+
91
90
  desc "displayconfig", "Display the current config from knife.rb"
92
91
  method_option :test, :type => :boolean
93
92
  def displayconfig
94
- if options.test?
95
- config = Cucumber::Chef::Config.test_config
96
- else
97
- config = Cucumber::Chef::Config.new
98
- end
99
93
  puts config.list.join("\n")
100
94
  config.verify
101
95
  rescue ::Cucumber::Chef::Error => err
@@ -105,30 +99,41 @@ class CucumberChef < Thor
105
99
  desc "info", "Display information about the current test lab"
106
100
  method_option :test, :type => :boolean
107
101
  def info
108
- if options.test?
109
- config = Cucumber::Chef::Config.test_config
110
- else
111
- config = Cucumber::Chef::Config.new
112
- end
113
102
  config.verify
114
103
  lab = Cucumber::Chef::TestLab.new(config)
115
- if lab.exists?
116
- puts lab.info
117
- else
118
- end
104
+ puts lab.info
105
+ rescue ::Cucumber::Chef::Error => err
106
+ error(err.message)
119
107
  end
120
-
121
- desc "upload", "Upload a cucumber-chef test suite to the test lab platform"
122
- def upload
123
- puts "Project uploaded to the test-lab."
108
+
109
+ desc "destroy", "Destroy running test labs"
110
+ method_option :test, :type => :boolean
111
+ def destroy
112
+ config.verify
113
+ lab = Cucumber::Chef::TestLab.new(config)
114
+ lab.destroy
115
+ end
116
+
117
+ desc "upload <project name>", "Upload a cucumber-chef test suite to the test lab platform"
118
+ def upload(project_name)
119
+ project_dir = Pathname.new(".") + "cucumber-chef" + project_name
120
+ unless File.exists?(project_dir)
121
+ raise "Project dir '#{project_dir}' does not exist."
122
+ end
123
+ config.verify
124
+ runner = Cucumber::Chef::TestRunner.new(project_dir, config)
125
+ runner.upload_project
124
126
  end
125
127
 
126
128
  desc "test", "Run a cucumber-chef test suite from a workstation."
127
- def test
128
- puts "Running test..."
129
- puts
130
- puts "Test results will appear here."
129
+ def test(project_name)
130
+ project_dir = Pathname.new(".") + "cucumber-chef" + project_name
131
+ unless File.exists?(project_dir)
132
+ raise "Project dir '#{project_dir}' does not exist."
133
+ end
134
+ config.verify
135
+ runner = Cucumber::Chef::TestRunner.new(project_dir, config)
136
+ runner.run
131
137
  end
132
138
  end
133
-
134
139
  CucumberChef.start
@@ -144,15 +144,16 @@ EOF
144
144
  rm $image/etc/resolv.conf
145
145
  cp /etc/resolv.conf $image/etc/resolv.conf
146
146
  cp /etc/lxc/install-chef.sh $image/tmp/install-chef.sh
147
- chroot $image /bin/sh -c "/usr/bin/apt-get update && /usr/bin/apt-get --assume-yes --allow-unauthenticated install strace ruby1.9.1p180"
147
+ chroot $image /bin/sh -c "/usr/bin/apt-get update && /usr/bin/apt-get --assume-yes --allow-unauthenticated install ruby1.9.1p180"
148
148
  mkdir -p $image/$HOME
149
- chroot $image /bin/sh -c "strace /usr/local/bin/gem install chef --no-ri --no-rdoc 2>&1" 2>&1 >> /tmp/data
149
+ chroot $image /bin/sh -c "/usr/local/bin/gem install ohai --no-ri --no-rdoc"
150
+ chroot $image /bin/sh -c "/usr/local/bin/gem install chef --no-ri --no-rdoc"
150
151
  return $?
151
152
  }
152
153
 
153
154
  download_ubuntu()
154
155
  {
155
- packages=dialog,apt,apt-utils,resolvconf,iproute,inetutils-ping,vim,dhcp3-client,ssh,lsb-release,wget,gpgv,gnupg
156
+ packages=dialog,apt,apt-utils,resolvconf,iproute,inetutils-ping,dhcp3-client,ssh,lsb-release,wget,gpgv,gnupg
156
157
 
157
158
  cache=$1
158
159
  arch=$2
@@ -38,13 +38,14 @@ cookbook_file "/var/lib/lxc/controller/rootfs/etc/chef/first-boot.json" do
38
38
  source "controller-first-boot"
39
39
  end
40
40
 
41
+ controllers = search(:node, 'name:cucumber-chef-controller')
41
42
  execute 'chroot /var/lib/lxc/controller/rootfs /bin/bash -c "chef-client -j /etc/chef/first-boot.json > /dev/null 2>&1"' do
42
43
  action :run
43
- # TODO: Make idempotent perhaps with a node search
44
+ not_if { controllers.length > 0 }
44
45
  end
45
46
 
46
47
  execute 'lxc-start -d -n controller' do
47
- status = %x[lxc-info -n #{name} 2>&1]
48
+ status = %x[lxc-info -n controller 2>&1]
48
49
  not_if {status.include?("RUNNING")}
49
50
  end
50
51
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{cucumber-chef}
8
- s.version = "0.5.0"
8
+ s.version = "0.5.1"
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-09}
12
+ s.date = %q{2011-06-14}
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}
@@ -61,6 +61,7 @@ Gem::Specification.new do |s|
61
61
  "lib/cucumber/chef.rb",
62
62
  "lib/cucumber/chef/config.rb",
63
63
  "lib/cucumber/chef/handy.rb",
64
+ "lib/cucumber/chef/provisioner.rb",
64
65
  "lib/cucumber/chef/templates/controller.erb",
65
66
  "lib/cucumber/chef/templates/env.rb",
66
67
  "lib/cucumber/chef/templates/example_feature.erb",
@@ -68,11 +69,14 @@ Gem::Specification.new do |s|
68
69
  "lib/cucumber/chef/templates/readme.erb",
69
70
  "lib/cucumber/chef/templates/ubuntu10.04-gems.erb",
70
71
  "lib/cucumber/chef/test_lab.rb",
72
+ "lib/cucumber/chef/test_runner.rb",
71
73
  "lib/cucumber/chef/version.rb",
72
74
  "lib/cucumber/ec2_server_create.rb",
73
75
  "spec/unit/config_spec.rb",
74
76
  "spec/unit/cucumber_chef_spec.rb",
75
- "spec/unit/test_lab_spec.rb"
77
+ "spec/unit/provisioner_spec.rb",
78
+ "spec/unit/test_lab_spec.rb",
79
+ "spec/unit/test_runner_spec.rb"
76
80
  ]
77
81
  s.homepage = %q{http://github.com/atalanta/cucumber-chef}
78
82
  s.licenses = ["MIT"]
@@ -90,7 +94,6 @@ Gem::Specification.new do |s|
90
94
  s.add_runtime_dependency(%q<rspec>, [">= 0"])
91
95
  s.add_runtime_dependency(%q<fog>, [">= 0"])
92
96
  s.add_runtime_dependency(%q<thor>, [">= 0"])
93
- s.add_runtime_dependency(%q<awesome_print>, [">= 0"])
94
97
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
95
98
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.2"])
96
99
  s.add_development_dependency(%q<rcov>, [">= 0"])
@@ -101,7 +104,6 @@ Gem::Specification.new do |s|
101
104
  s.add_dependency(%q<rspec>, [">= 0"])
102
105
  s.add_dependency(%q<fog>, [">= 0"])
103
106
  s.add_dependency(%q<thor>, [">= 0"])
104
- s.add_dependency(%q<awesome_print>, [">= 0"])
105
107
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
106
108
  s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
107
109
  s.add_dependency(%q<rcov>, [">= 0"])
@@ -113,7 +115,6 @@ Gem::Specification.new do |s|
113
115
  s.add_dependency(%q<rspec>, [">= 0"])
114
116
  s.add_dependency(%q<fog>, [">= 0"])
115
117
  s.add_dependency(%q<thor>, [">= 0"])
116
- s.add_dependency(%q<awesome_print>, [">= 0"])
117
118
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
118
119
  s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
119
120
  s.add_dependency(%q<rcov>, [">= 0"])
data/lib/cucumber/chef.rb CHANGED
@@ -6,6 +6,7 @@ require 'chef/knife/core/bootstrap_context'
6
6
  require 'chef/knife/ssh'
7
7
  require 'socket'
8
8
  require 'net/ssh/multi'
9
+ require 'net/scp'
9
10
  require "fog"
10
11
  require 'readline'
11
12
  require 'stringio'
@@ -15,78 +16,9 @@ module Cucumber
15
16
  class Error < StandardError ; end
16
17
 
17
18
  autoload :Config, "cucumber/chef/config"
19
+ autoload :Provisioner, "cucumber/chef/provisioner"
18
20
  autoload :TestLab, "cucumber/chef/test_lab"
19
-
20
- class ProvisionerError < Error ; end
21
- class Provisioner
22
- def initialize
23
- @cookbook_path = File.join(File.dirname(__FILE__), "../../cookbooks/cucumber-chef")
24
- end
25
-
26
- def config
27
- Config.new.config
28
- end
29
-
30
- def bootstrap_node(dns_name, config)
31
- template_file = File.join(File.dirname(__FILE__),
32
- "chef/templates/ubuntu10.04-gems.erb")
33
- bootstrap = ::Chef::Knife::Bootstrap.new
34
- @stdout, @stderr, @stdout = StringIO.new, StringIO.new, StringIO.new
35
- ui = ::Chef::Knife::UI.new(@stdout, @stderr, @stdout, bootstrap.config)
36
- bootstrap.ui = ui
37
- bootstrap.name_args = [dns_name]
38
- bootstrap.config[:run_list] = "role[test_lab_test]"
39
- bootstrap.config[:ssh_user] = "ubuntu"
40
- bootstrap.config[:identity_file] = config[:knife][:identity_file]
41
- bootstrap.config[:chef_node_name] = "cucumber-chef-test-lab"
42
- bootstrap.config[:use_sudo] = true
43
- bootstrap.config[:template_file] = template_file
44
- bootstrap.config[:validation_client_name] = config["validation_client_name"]
45
- bootstrap.config[:validation_key] = config["validation_key"]
46
- bootstrap.config[:chef_server_url] = config["chef_server_url"]
47
- bootstrap
48
- end
49
-
50
- def build_controller(dns_name, config)
51
- template_file = File.join(File.dirname(__FILE__),
52
- "chef/templates/controller.erb")
53
- bootstrap = ::Chef::Knife::Bootstrap.new
54
- @stdout, @stderr, @stdout = StringIO.new, StringIO.new, StringIO.new
55
- ui = ::Chef::Knife::UI.new(@stdout, @stderr, @stdout, bootstrap.config)
56
- bootstrap.ui = ui
57
- bootstrap.name_args = [dns_name]
58
- bootstrap.config[:ssh_user] = "ubuntu"
59
- bootstrap.config[:identity_file] = config[:knife][:identity_file]
60
- bootstrap.config[:chef_node_name] = "cucumber-chef-controller"
61
- bootstrap.config[:use_sudo] = true
62
- bootstrap.config[:template_file] = template_file
63
- bootstrap.config[:validation_client_name] = config["validation_client_name"]
64
- bootstrap.config[:validation_key] = config["validation_key"]
65
- bootstrap.config[:chef_server_url] = config["chef_server_url"]
66
- bootstrap
67
- end
68
-
69
- def upload_cookbook(config)
70
- version_loader = ::Chef::Cookbook::CookbookVersionLoader.new(@cookbook_path)
71
- version_loader.load_cookbooks
72
- uploader = ::Chef::CookbookUploader.new(version_loader.cookbook_version,
73
- @cookbook_path)
74
- uploader.upload_cookbook
75
- end
76
-
77
- def upload_role(config)
78
- role_path = File.join(@cookbook_path, "roles")
79
- ::Chef::Config[:role_path] = role_path
80
- role = ::Chef::Role.from_disk("test_lab_test")
81
- role.save
82
- role = ::Chef::Role.from_disk("controller")
83
- role.save
84
- end
85
-
86
- def build_test_lab(config, output)
87
- TestLab.new(config).build(output)
88
- end
89
- end
21
+ autoload :TestRunner, "cucumber/chef/test_runner"
90
22
  end
91
23
  end
92
24
 
@@ -10,10 +10,10 @@ module Cucumber
10
10
  config[:mode] = "user"
11
11
  end
12
12
 
13
- def self.test_config
14
- config = self.new
15
- config[:mode] = "test"
16
- config
13
+
14
+
15
+ def self.mode
16
+ config.test_mode? ? 'test' : 'user'
17
17
  end
18
18
 
19
19
  def [](key)
@@ -40,6 +40,16 @@ module Cucumber
40
40
  @config
41
41
  end
42
42
 
43
+ def test_config
44
+ config = self.new
45
+ config[:mode] = "test"
46
+ config
47
+ end
48
+
49
+ def test_mode?
50
+ config[:mode] == "test"
51
+ end
52
+
43
53
  def list
44
54
  values = []
45
55
  KEYS.each do |key|
@@ -0,0 +1,92 @@
1
+ require "digest"
2
+
3
+ module Cucumber
4
+ module Chef
5
+ class ProvisionerError < Error ; end
6
+
7
+ class Provisioner
8
+ def initialize
9
+ @cookbook_path = File.join(File.dirname(__FILE__), "../../../cookbooks/cucumber-chef")
10
+ end
11
+
12
+ def bootstrap_node(dns_name, config)
13
+ template_file = File.join(File.dirname(__FILE__), "templates/ubuntu10.04-gems.erb")
14
+ bootstrap = ::Chef::Knife::Bootstrap.new
15
+ @stdout, @stderr, @stdout = StringIO.new, StringIO.new, StringIO.new
16
+ ui = ::Chef::Knife::UI.new(@stdout, @stderr, @stdout, bootstrap.config)
17
+ bootstrap.ui = ui
18
+ nodename = chef_node_name(config)
19
+ bootstrap.name_args = [dns_name]
20
+ bootstrap.config[:run_list] = "role[test_lab_test]"
21
+ bootstrap.config[:ssh_user] = "ubuntu"
22
+ bootstrap.config[:identity_file] = config[:knife][:identity_file]
23
+ bootstrap.config[:chef_node_name] = nodename
24
+ bootstrap.config[:use_sudo] = true
25
+ bootstrap.config[:template_file] = template_file
26
+ bootstrap.config[:validation_client_name] = config["validation_client_name"]
27
+ bootstrap.config[:validation_key] = config["validation_key"]
28
+ bootstrap.config[:chef_server_url] = config["chef_server_url"]
29
+ bootstrap
30
+ bootstrap.run
31
+ tag_node(config)
32
+ end
33
+
34
+ def build_controller(dns_name, config)
35
+ template_file = File.join(File.dirname(__FILE__), "templates/controller.erb")
36
+ bootstrap = ::Chef::Knife::Bootstrap.new
37
+ @stdout, @stderr, @stdout = StringIO.new, StringIO.new, StringIO.new
38
+ ui = ::Chef::Knife::UI.new(@stdout, @stderr, @stdout, bootstrap.config)
39
+ bootstrap.ui = ui
40
+ bootstrap.name_args = [dns_name]
41
+ bootstrap.config[:ssh_user] = "ubuntu"
42
+ bootstrap.config[:identity_file] = config[:knife][:identity_file]
43
+ bootstrap.config[:chef_node_name] = "cucumber-chef-controller"
44
+ bootstrap.config[:use_sudo] = true
45
+ bootstrap.config[:template_file] = template_file
46
+ bootstrap.config[:validation_client_name] = config["validation_client_name"]
47
+ bootstrap.config[:validation_key] = config["validation_key"]
48
+ bootstrap.config[:chef_server_url] = config["chef_server_url"]
49
+
50
+ end
51
+
52
+ def upload_cookbook(config)
53
+ version_loader = ::Chef::Cookbook::CookbookVersionLoader.new(@cookbook_path)
54
+ version_loader.load_cookbooks
55
+ uploader = ::Chef::CookbookUploader.new(version_loader.cookbook_version,
56
+ @cookbook_path)
57
+ uploader.upload_cookbook
58
+ end
59
+
60
+ def upload_role(config)
61
+ role_path = File.join(@cookbook_path, "roles")
62
+ ::Chef::Config[:role_path] = role_path
63
+ role = ::Chef::Role.from_disk("test_lab_test")
64
+ role.save
65
+ role = ::Chef::Role.from_disk("controller")
66
+ role.save
67
+ end
68
+
69
+ def build_test_lab(config, output)
70
+ TestLab.new(config).build(output)
71
+ end
72
+
73
+ def tag_node(config)
74
+ node = ::Chef::Node.load(chef_node_name)
75
+ node.tags << (config.test_mode? ? 'test' : 'user')
76
+ node.save
77
+ end
78
+
79
+ private
80
+
81
+ def chef_node_name(config=nil)
82
+ @node_name ||= begin
83
+ if config.test_mode?
84
+ "cucumber-chef-#{Digest::SHA1.hexdigest(Time.now.to_s)[0..7]}"
85
+ else
86
+ "cucumber-chef-test-lab"
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -1,10 +1,8 @@
1
1
  Welcome to the <%= @project %> suite of cucumber-chef tests
2
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$
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 behaviour, expressing them as cucumer scenarios.
4
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 %>
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 run the tests with:
8
6
 
9
7
  Then run your tests with:
10
8
 
@@ -14,15 +12,3 @@ For an example feature, take a look at ./<%= @project %>/features/example.featur
14
12
 
15
13
  For an example step definition, look at ./<%= @project %>/features/example.feature
16
14
 
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
-
@@ -10,7 +10,6 @@ module Cucumber
10
10
  :aws_access_key_id => @config[:knife][:aws_access_key_id],
11
11
  :aws_secret_access_key => @config[:knife][:aws_secret_access_key],
12
12
  :region => @config[:knife][:region])
13
- @mode = @config[:mode]
14
13
  end
15
14
 
16
15
  def build(output)
@@ -38,20 +37,41 @@ module Cucumber
38
37
  end
39
38
 
40
39
  def destroy
41
- @connection.servers.each do |s|
42
- s.destroy if s.tags['cucumber-chef'] == @mode && s.state == 'running'
40
+ running_labs.each do |server|
41
+ #server.destroy
42
+ puts server.public_ip_address
43
+ end
44
+ nodes.each do |node|
45
+ # node.destroy
46
+ puts node[:ec2][:public_ipv4]
43
47
  end
44
48
  end
45
49
 
46
50
  def exists?
47
- running_labs_count > 0
51
+ running_labs.size > 0
48
52
  end
49
53
 
50
54
  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
+ "#{node.name}: #{node[:ec2][:public_ipv4]}"
56
+ end
57
+
58
+ def public_hostname
59
+ node.cloud.public_hostname
60
+ end
61
+
62
+ def node
63
+ @node ||= begin
64
+ search = ::Chef::Search::Query.new
65
+ mode = @config[:mode]
66
+ query = "roles:test_lab_test AND tags:#{mode}"
67
+ nodes, offset, total = search.search("node", URI.escape(query))
68
+ nodes.compact.first
69
+ end
70
+ end
71
+
72
+ def running_labs
73
+ @connection.servers.select do |s|
74
+ s.tags['cucumber-chef'] == @config[:mode] && s.state == 'running'
55
75
  end
56
76
  end
57
77
 
@@ -60,15 +80,9 @@ module Cucumber
60
80
  tag = @connection.tags.new
61
81
  tag.resource_id = @server.id
62
82
  tag.key = "cucumber-chef"
63
- tag.value = @mode
83
+ tag.value = @config[:mode]
64
84
  tag.save
65
85
  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
86
  end
73
87
  end
74
88
  end
@@ -0,0 +1,32 @@
1
+ module Cucumber
2
+ module Chef
3
+ class TestRunnerError < Error ; end
4
+
5
+ class TestRunner
6
+
7
+ require 'cucumber/chef/test_lab'
8
+
9
+ def initialize(project_dir, config)
10
+ @project_dir = project_dir
11
+ @config = config
12
+ end
13
+
14
+ def run
15
+ upload_project
16
+ @project_path = File.join('/home/ubuntu', File.basename(@project_dir), 'features')
17
+ connection = Net::SSH.start(@hostname, 'ubuntu', :keys => @key) do |ssh|
18
+ @output = ssh.exec!("sudo cucumber #{@project_path}")
19
+ end
20
+ puts @output
21
+ end
22
+
23
+ def upload_project
24
+ lab = Cucumber::Chef::TestLab.new(@config)
25
+ @hostname = lab.public_hostname
26
+ @key = File.expand_path(@config[:knife][:identity_file])
27
+ %x[scp -r -i #{@key} #{@project_dir} ubuntu@#{@hostname}: 2>/dev/null]
28
+ puts "Cucumber-chef project: #{File.basename(@project_dir)} sucessfully uploaded to the test lab."
29
+ end
30
+ end
31
+ end
32
+ end
@@ -103,6 +103,14 @@ describe Cucumber::Chef::Config do
103
103
  config = Cucumber::Chef::Config.test_config
104
104
  config[:mode].should == "test"
105
105
  end
106
+
107
+ it "should know it is in test mode" do
108
+ Cucumber::Chef::Config.test_config.test_mode?.should be
109
+ end
110
+
111
+ it "should know it is not in test_mode" do
112
+ Cucumber::Chef::Config.new.test_mode?.should_not be
113
+ end
106
114
  end
107
115
  end
108
116
 
@@ -2,126 +2,3 @@ require "rubygems"
2
2
  require "bundler/setup"
3
3
  require File.join(File.dirname(__FILE__), "../../lib/cucumber-chef")
4
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::Provisioner do
24
- before(:all) do
25
- @config = subject.config
26
- @config[:mode] = "test"
27
- end
28
-
29
- describe "upload_cookbook" do
30
- before(:each) do
31
- begin
32
- cookbook_path = File.expand_path("cookbooks/cucumber-chef")
33
- version_loader = ::Chef::Cookbook::CookbookVersionLoader.new(cookbook_path)
34
- version_loader.load_cookbooks
35
- version = version_loader.cookbook_version
36
- version.destroy
37
- rescue Net::HTTPServerException => err
38
- end
39
- end
40
-
41
- it "should upload the cucumber-chef cookbook" do
42
- subject.upload_cookbook(@config)
43
- ::Chef::CookbookVersion.list["cucumber-chef"].should be
44
- end
45
- end
46
-
47
- describe "upload_role" do
48
- before(:each) do
49
- begin
50
- role_path = File.expand_path("cookbooks/cucumber-chef/roles")
51
- ::Chef::Config[:role_path] = role_path
52
- role = ::Chef::Role.from_disk("test_lab_test")
53
- role.destroy
54
- rescue Net::HTTPServerException => err
55
- end
56
- end
57
-
58
- it "should upload the test_lab role" do
59
- subject.upload_role(@config)
60
- ::Chef::Role.list["test_lab_test"].should be
61
- end
62
- end
63
-
64
- describe "bootstrap_node" do
65
- before(:each) do
66
- server = subject.build_test_lab(@config, StringIO.new)
67
- @dns_name = server.dns_name
68
- puts "Hanging around..." until tcp_test_ssh(server.public_ip_address)
69
- puts "Got ssh..."
70
- sleep(10)
71
- subject.upload_cookbook(@config)
72
- subject.upload_role(@config)
73
- end
74
-
75
- after(:each) do
76
- config = @config[:knife]
77
- connection = Fog::Compute.new(:provider => 'AWS',
78
- :aws_access_key_id => config[:aws_access_key_id],
79
- :aws_secret_access_key => config[:aws_secret_access_key],
80
- :region => config[:region])
81
- connection.servers.each do |s|
82
- s.destroy if s.tags['cucumber-chef'] == 'test' && s.state == 'running'
83
- end
84
- end
85
-
86
- it "should set up platform as a chef client and apply test-lab role" do
87
- bootstrapper = subject.bootstrap_node(@dns_name, @config)
88
- bootstrapper.run
89
- # DEBUG: puts bootstrapper.ui.stdout.string
90
- node = ::Chef::Node.load("cucumber-chef-test-lab")
91
- node.run_list.to_s.should match(/role\[test_lab_test\]/)
92
- end
93
- end
94
-
95
- describe "build_controller" do
96
-
97
- before(:each) do
98
- server = subject.build_test_lab(@config, StringIO.new)
99
- @dns_name = server.dns_name
100
- puts "Hanging around..." until tcp_test_ssh(server.public_ip_address)
101
- puts "Got ssh..."
102
- sleep(10)
103
- subject.upload_cookbook(@config)
104
- subject.upload_role(@config)
105
- subject.bootstrap_node(@dns_name, @config).run
106
- end
107
-
108
- after(:each) do
109
- config = @config[:knife]
110
- connection = Fog::Compute.new(:provider => 'AWS',
111
- :aws_access_key_id => config[:aws_access_key_id],
112
- :aws_secret_access_key => config[:aws_secret_access_key],
113
- :region => config[:region])
114
- connection.servers.each do |s|
115
- s.destroy if s.tags['cucumber-chef'] == 'test' && s.state == 'running'
116
- end
117
- end
118
-
119
- it "should build a cucumber-chef controller" do
120
- controller_builder = subject.build_controller(@dns_name, @config)
121
- controller_builder.run
122
- puts controller_builder.ui.stdout.string
123
- end
124
-
125
- end
126
-
127
- end
@@ -0,0 +1,120 @@
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::Provisioner do
24
+ before(:all) do
25
+ @config = Cucumber::Chef::Config.test_config
26
+ end
27
+
28
+ describe "upload_cookbook" do
29
+ before(:each) do
30
+ begin
31
+ cookbook_path = File.expand_path("cookbooks/cucumber-chef")
32
+ version_loader = ::Chef::Cookbook::CookbookVersionLoader.new(cookbook_path)
33
+ version_loader.load_cookbooks
34
+ version = version_loader.cookbook_version
35
+ version.destroy
36
+ rescue Net::HTTPServerException => err
37
+ end
38
+ end
39
+
40
+ it "should upload the cucumber-chef cookbook" do
41
+ subject.upload_cookbook(@config)
42
+ ::Chef::CookbookVersion.list["cucumber-chef"].should be
43
+ end
44
+ end
45
+
46
+ describe "upload_role" do
47
+ before(:each) do
48
+ begin
49
+ role_path = File.expand_path("cookbooks/cucumber-chef/roles")
50
+ ::Chef::Config[:role_path] = role_path
51
+ role = ::Chef::Role.from_disk("test_lab_test")
52
+ role.destroy
53
+ rescue Net::HTTPServerException => err
54
+ end
55
+ end
56
+
57
+ it "should upload the test_lab role" do
58
+ subject.upload_role(@config)
59
+ ::Chef::Role.list["test_lab_test"].should be
60
+ end
61
+ end
62
+
63
+ describe "bootstrap_node" do
64
+ before(:each) do
65
+ @test_lab = Cucumber::Chef::TestLab.new(@config)
66
+ @test_lab.destroy
67
+ server = subject.build_test_lab(@config, StringIO.new)
68
+ @dns_name = server.dns_name
69
+ puts "Hanging around..." until tcp_test_ssh(server.public_ip_address)
70
+ puts "Got ssh..."
71
+ sleep(10)
72
+ subject.upload_cookbook(@config)
73
+ subject.upload_role(@config)
74
+ end
75
+
76
+ after(:each) do
77
+ @test_lab.destroy
78
+ end
79
+
80
+ it "should assign a random name to the node" do
81
+ bootstrapper = subject.bootstrap_node(@dns_name, @config)
82
+ bootstrapper.run
83
+ @test_lab.nodes.detect do |node|
84
+ node.name.match /^cucumber-chef-[0-9a-f]{8}$/
85
+ end.should be
86
+ end
87
+ end
88
+
89
+ describe "build_controller" do
90
+
91
+ before(:each) do
92
+ server = subject.build_test_lab(@config, StringIO.new)
93
+ @dns_name = server.dns_name
94
+ puts "Hanging around..." until tcp_test_ssh(server.public_ip_address)
95
+ puts "Got ssh..."
96
+ sleep(10)
97
+ subject.upload_cookbook(@config)
98
+ subject.upload_role(@config)
99
+ subject.bootstrap_node(@dns_name, @config).run
100
+ end
101
+
102
+ after(:each) do
103
+ config = @config[:knife]
104
+ connection = Fog::Compute.new(:provider => 'AWS',
105
+ :aws_access_key_id => config[:aws_access_key_id],
106
+ :aws_secret_access_key => config[:aws_secret_access_key],
107
+ :region => config[:region])
108
+ connection.servers.each do |s|
109
+ s.destroy if s.tags['cucumber-chef'] == 'test' && s.state == 'running'
110
+ end
111
+ end
112
+
113
+ it "should build a cucumber-chef controller" do
114
+ controller_builder = subject.build_controller(@dns_name, @config)
115
+ controller_builder.run
116
+ puts controller_builder.ui.stdout.string
117
+ end
118
+
119
+ end
120
+ end
@@ -4,8 +4,7 @@ require File.join(File.dirname(__FILE__), "../../lib/cucumber-chef")
4
4
 
5
5
  describe Cucumber::Chef::TestLab do
6
6
  before(:all) do
7
- @config = Cucumber::Chef::Config.new.config
8
- @config[:mode] = "test"
7
+ @config = Cucumber::Chef::Config.test_config
9
8
  end
10
9
 
11
10
  subject { Cucumber::Chef::TestLab.new(@config) }
@@ -54,7 +53,7 @@ describe Cucumber::Chef::TestLab do
54
53
  after(:each) { subject.destroy }
55
54
 
56
55
  it "should report its public ip address", :slow => true do
57
- subject.info.should == @public_ip_address
56
+ subject.info.should match(/#{@public_ip_address}/)
58
57
  end
59
58
  end
60
59
  end
@@ -0,0 +1,10 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+ require File.join(File.dirname(__FILE__), "../../lib/cucumber-chef")
4
+
5
+ describe Cucumber::Chef::TestRunner do
6
+ before(:all) do
7
+ @config = Cucumber::Chef::Config.test_config
8
+ end
9
+ end
10
+
metadata CHANGED
@@ -1,136 +1,127 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: cucumber-chef
3
- version: !ruby/object:Gem::Version
4
- version: 0.5.0
3
+ version: !ruby/object:Gem::Version
5
4
  prerelease:
5
+ version: 0.5.1
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Stephen Nelson-Smith
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-06-09 00:00:00.000000000 +00:00
12
+
13
+ date: 2011-06-14 00:00:00 +01:00
13
14
  default_executable: cucumber-chef
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
16
17
  name: chef
17
- requirement: &24043900 !ruby/object:Gem::Requirement
18
+ requirement: &id001 !ruby/object:Gem::Requirement
18
19
  none: false
19
- requirements:
20
- - - ! '>='
21
- - !ruby/object:Gem::Version
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
22
23
  version: 0.10.0
23
24
  type: :runtime
24
25
  prerelease: false
25
- version_requirements: *24043900
26
- - !ruby/object:Gem::Dependency
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
27
28
  name: cucumber
28
- requirement: &24043420 !ruby/object:Gem::Requirement
29
+ requirement: &id002 !ruby/object:Gem::Requirement
29
30
  none: false
30
- requirements:
31
- - - ! '>='
32
- - !ruby/object:Gem::Version
33
- version: '0'
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
34
35
  type: :runtime
35
36
  prerelease: false
36
- version_requirements: *24043420
37
- - !ruby/object:Gem::Dependency
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
38
39
  name: cucumber-nagios
39
- requirement: &24042940 !ruby/object:Gem::Requirement
40
+ requirement: &id003 !ruby/object:Gem::Requirement
40
41
  none: false
41
- requirements:
42
- - - ! '>='
43
- - !ruby/object:Gem::Version
44
- version: '0'
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
45
46
  type: :runtime
46
47
  prerelease: false
47
- version_requirements: *24042940
48
- - !ruby/object:Gem::Dependency
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
49
50
  name: rspec
50
- requirement: &24042460 !ruby/object:Gem::Requirement
51
+ requirement: &id004 !ruby/object:Gem::Requirement
51
52
  none: false
52
- requirements:
53
- - - ! '>='
54
- - !ruby/object:Gem::Version
55
- version: '0'
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
56
57
  type: :runtime
57
58
  prerelease: false
58
- version_requirements: *24042460
59
- - !ruby/object:Gem::Dependency
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
60
61
  name: fog
61
- requirement: &24041980 !ruby/object:Gem::Requirement
62
+ requirement: &id005 !ruby/object:Gem::Requirement
62
63
  none: false
63
- requirements:
64
- - - ! '>='
65
- - !ruby/object:Gem::Version
66
- version: '0'
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
67
68
  type: :runtime
68
69
  prerelease: false
69
- version_requirements: *24041980
70
- - !ruby/object:Gem::Dependency
70
+ version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
71
72
  name: thor
72
- requirement: &24041500 !ruby/object:Gem::Requirement
73
+ requirement: &id006 !ruby/object:Gem::Requirement
73
74
  none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: '0'
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
78
79
  type: :runtime
79
80
  prerelease: false
80
- version_requirements: *24041500
81
- - !ruby/object:Gem::Dependency
82
- name: awesome_print
83
- requirement: &24041020 !ruby/object:Gem::Requirement
84
- none: false
85
- requirements:
86
- - - ! '>='
87
- - !ruby/object:Gem::Version
88
- version: '0'
89
- type: :runtime
90
- prerelease: false
91
- version_requirements: *24041020
92
- - !ruby/object:Gem::Dependency
81
+ version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
93
83
  name: bundler
94
- requirement: &24061420 !ruby/object:Gem::Requirement
84
+ requirement: &id007 !ruby/object:Gem::Requirement
95
85
  none: false
96
- requirements:
86
+ requirements:
97
87
  - - ~>
98
- - !ruby/object:Gem::Version
88
+ - !ruby/object:Gem::Version
99
89
  version: 1.0.0
100
90
  type: :development
101
91
  prerelease: false
102
- version_requirements: *24061420
103
- - !ruby/object:Gem::Dependency
92
+ version_requirements: *id007
93
+ - !ruby/object:Gem::Dependency
104
94
  name: jeweler
105
- requirement: &24060940 !ruby/object:Gem::Requirement
95
+ requirement: &id008 !ruby/object:Gem::Requirement
106
96
  none: false
107
- requirements:
97
+ requirements:
108
98
  - - ~>
109
- - !ruby/object:Gem::Version
99
+ - !ruby/object:Gem::Version
110
100
  version: 1.6.2
111
101
  type: :development
112
102
  prerelease: false
113
- version_requirements: *24060940
114
- - !ruby/object:Gem::Dependency
103
+ version_requirements: *id008
104
+ - !ruby/object:Gem::Dependency
115
105
  name: rcov
116
- requirement: &24060460 !ruby/object:Gem::Requirement
106
+ requirement: &id009 !ruby/object:Gem::Requirement
117
107
  none: false
118
- requirements:
119
- - - ! '>='
120
- - !ruby/object:Gem::Version
121
- version: '0'
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: "0"
122
112
  type: :development
123
113
  prerelease: false
124
- version_requirements: *24060460
114
+ version_requirements: *id009
125
115
  description: Framework for behaviour-drive infrastructure development.
126
116
  email: stephen@atalanta-systems.com
127
- executables:
117
+ executables:
128
118
  - cucumber-chef
129
119
  extensions: []
130
- extra_rdoc_files:
120
+
121
+ extra_rdoc_files:
131
122
  - LICENSE
132
123
  - README.md
133
- files:
124
+ files:
134
125
  - .document
135
126
  - .gitignore
136
127
  - Gemfile
@@ -173,6 +164,7 @@ files:
173
164
  - lib/cucumber/chef.rb
174
165
  - lib/cucumber/chef/config.rb
175
166
  - lib/cucumber/chef/handy.rb
167
+ - lib/cucumber/chef/provisioner.rb
176
168
  - lib/cucumber/chef/templates/controller.erb
177
169
  - lib/cucumber/chef/templates/env.rb
178
170
  - lib/cucumber/chef/templates/example_feature.erb
@@ -180,38 +172,44 @@ files:
180
172
  - lib/cucumber/chef/templates/readme.erb
181
173
  - lib/cucumber/chef/templates/ubuntu10.04-gems.erb
182
174
  - lib/cucumber/chef/test_lab.rb
175
+ - lib/cucumber/chef/test_runner.rb
183
176
  - lib/cucumber/chef/version.rb
184
177
  - lib/cucumber/ec2_server_create.rb
185
178
  - spec/unit/config_spec.rb
186
179
  - spec/unit/cucumber_chef_spec.rb
180
+ - spec/unit/provisioner_spec.rb
187
181
  - spec/unit/test_lab_spec.rb
182
+ - spec/unit/test_runner_spec.rb
188
183
  has_rdoc: true
189
184
  homepage: http://github.com/atalanta/cucumber-chef
190
- licenses:
185
+ licenses:
191
186
  - MIT
192
187
  post_install_message:
193
188
  rdoc_options: []
194
- require_paths:
189
+
190
+ require_paths:
195
191
  - lib
196
- required_ruby_version: !ruby/object:Gem::Requirement
192
+ required_ruby_version: !ruby/object:Gem::Requirement
197
193
  none: false
198
- requirements:
199
- - - ! '>='
200
- - !ruby/object:Gem::Version
201
- version: '0'
202
- segments:
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ hash: 4460646559625670767
198
+ segments:
203
199
  - 0
204
- hash: -3689892462055237010
205
- required_rubygems_version: !ruby/object:Gem::Requirement
200
+ version: "0"
201
+ required_rubygems_version: !ruby/object:Gem::Requirement
206
202
  none: false
207
- requirements:
208
- - - ! '>='
209
- - !ruby/object:Gem::Version
210
- version: '0'
203
+ requirements:
204
+ - - ">="
205
+ - !ruby/object:Gem::Version
206
+ version: "0"
211
207
  requirements: []
208
+
212
209
  rubyforge_project:
213
210
  rubygems_version: 1.6.2
214
211
  signing_key:
215
212
  specification_version: 3
216
213
  summary: Tests Chef-built infrastructure
217
214
  test_files: []
215
+