gusteau 1.0.2.dev → 1.0.3.dev

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## 1.0.3.dev / 2013-07-07
2
+ * Implement 'before' and 'after' hooks (global and environment-based)
3
+
1
4
  ## 1.0.2.dev / 2013-07-06
2
5
  * Fix Ruby 1.8.7 and Rubinius compatibility
3
6
 
data/README.md CHANGED
@@ -12,7 +12,7 @@ Introduction
12
12
 
13
13
  Gusteau is an easy to use configuration manager for Chef Solo and Vagrant.
14
14
  It aims to:
15
-
15
+
16
16
  1. Provide Chef Solo users with a more efficient workflow
17
17
  2. Encourage new users to try and to switch to Chef by avoiding the complexity of Chef Server.
18
18
 
@@ -45,6 +45,9 @@ Make sure you read through `project-name/README.md` first.
45
45
  A typical `.gusteau.yml` looks like this:
46
46
 
47
47
  ```
48
+ before:
49
+ - bundle exec berks install --path ./cookbooks
50
+
48
51
  environments:
49
52
  development:
50
53
  attributes:
data/lib/gusteau/chef.rb CHANGED
@@ -6,7 +6,7 @@ module Gusteau
6
6
  @dest_dir = dest_dir
7
7
  end
8
8
 
9
- def run(opts, dna)
9
+ def run(dna, opts)
10
10
  @server.run "rm -rf #{@dest_dir} && mkdir #{@dest_dir} && mkdir -p /tmp/chef"
11
11
 
12
12
  @server.upload(src_files(dna[:path]), @dest_dir, :exclude => '.git/')
@@ -8,12 +8,14 @@ module Gusteau
8
8
 
9
9
  def nodes(config_path)
10
10
  if File.exists?(config_path)
11
- env_config = read_erb_yaml(config_path)['environments']
11
+ config = read_erb_yaml(config_path)
12
+ env_config = config['environments']
13
+
12
14
  env_config.inject({}) do |nodes, (env_name, env_hash)|
13
15
  if env_hash['nodes']
14
16
  env_hash['nodes'].each_pair do |node_name, node_hash|
15
17
  node_name = "#{env_name}-#{node_name}"
16
- nodes[node_name] = build_node(node_name, env_hash, node_hash)
18
+ nodes[node_name] = build_node(config, node_name, env_hash, node_hash)
17
19
  end
18
20
  end
19
21
  nodes
@@ -26,12 +28,14 @@ module Gusteau
26
28
  #
27
29
  # Node attributes get deep-merged with the environment ones
28
30
  # Node run_list overrides the environment one
31
+ # Environment before hooks override global ones
29
32
  #
30
- def build_node(node_name, env_hash, node_hash)
33
+ def build_node(config, node_name, env_hash, node_hash)
31
34
  config = {
32
35
  'server' => node_hash,
33
- 'attributes' => env_hash['attributes'].deep_merge(node_hash['attributes'] || {}),
34
- 'run_list' => node_hash['run_list'] || env_hash['run_list']
36
+ 'attributes' => (env_hash['attributes'] || {}).deep_merge(node_hash['attributes'] || {}),
37
+ 'run_list' => node_hash['run_list'] || env_hash['run_list'],
38
+ 'before' => env_hash['before'] || config['before']
35
39
  }
36
40
  Gusteau::Node.new(node_name, config)
37
41
  end
data/lib/gusteau/node.rb CHANGED
@@ -3,6 +3,8 @@ require 'gusteau/chef'
3
3
 
4
4
  module Gusteau
5
5
  class Node
6
+ include Gusteau::Log
7
+
6
8
  attr_reader :name, :config, :server
7
9
 
8
10
  def initialize(name, config)
@@ -14,11 +16,15 @@ module Gusteau
14
16
  end
15
17
 
16
18
  def converge(opts = {})
17
- server.chef.run opts, dna
19
+ with_hooks do
20
+ server.chef.run dna, opts
21
+ end
18
22
  end
19
23
 
20
24
  def apply(run_list, opts = {})
21
- server.chef.run opts, dna(run_list)
25
+ with_hooks do
26
+ server.chef.run dna(run_list), opts
27
+ end
22
28
  end
23
29
 
24
30
  def ssh
@@ -27,6 +33,22 @@ module Gusteau
27
33
 
28
34
  private
29
35
 
36
+ def with_hooks(&block)
37
+ hook 'before'
38
+ yield
39
+ hook 'after'
40
+ end
41
+
42
+ def hook(hook_type)
43
+ (@config[hook_type] || []).each do |cmd|
44
+ Kernel.system cmd
45
+ unless $?.exitstatus == 0
46
+ log_error "Error executing a #{hook_type} hook: '#{cmd}'"
47
+ exit 1
48
+ end
49
+ end
50
+ end
51
+
30
52
  def dna(run_list = nil)
31
53
  node_dna = {
32
54
  :path => @dna_path,
@@ -1,3 +1,3 @@
1
1
  module Gusteau
2
- VERSION = "1.0.2.dev"
2
+ VERSION = "1.0.3.dev"
3
3
  end
data/spec/config/remi.yml CHANGED
@@ -2,7 +2,12 @@ default_node: &default_node
2
2
  platform: centos
3
3
  user: billy
4
4
 
5
+ before:
6
+ - bundle exec berks install
7
+
5
8
  environments:
9
+ staging: { before: [ echo "Hello World!" ], nodes: { vm: { host: '192.168.1.15'} } }
10
+
6
11
  production:
7
12
  attributes:
8
13
  users:
@@ -21,7 +21,7 @@ describe Gusteau::Chef do
21
21
  context "bootstrap option is not specified" do
22
22
  it "should run chef solo" do
23
23
  expects_run_chef_solo
24
- chef.run(opts, { :path => '/tmp/node.json' })
24
+ chef.run({ :path => '/tmp/node.json' }, opts)
25
25
  end
26
26
  end
27
27
 
@@ -31,7 +31,7 @@ describe Gusteau::Chef do
31
31
  it "should run the bootstrap script and chef solo" do
32
32
  server.expects(:run).with('sh /etc/chef/bootstrap/centos.sh')
33
33
  expects_run_chef_solo
34
- chef.run(opts, { :path => '/tmp/node.json' })
34
+ chef.run({ :path => '/tmp/node.json' }, opts)
35
35
  end
36
36
  end
37
37
  end
@@ -13,7 +13,7 @@ describe Gusteau::Config do
13
13
  let(:nodes) { Gusteau::Config.nodes("./spec/config/remi.yml") }
14
14
 
15
15
  it "should name nodes as per environment-node" do
16
- nodes.keys.sort.must_equal ["production-db", "production-www"]
16
+ nodes.keys.sort.must_equal ["production-db", "production-www", "staging-vm"]
17
17
  end
18
18
 
19
19
  it "should override run_list if defined for a node" do
@@ -27,5 +27,10 @@ describe Gusteau::Config do
27
27
  'mysql' => {'server_port' => 3307, 'server_root_password' => 'prodsecret' }
28
28
  })
29
29
  end
30
+
31
+ it "should override the global before hook with an environment one" do
32
+ nodes['production-www'].config['before'].must_equal(['bundle exec berks install'])
33
+ nodes['staging-vm'].config['before'].must_equal(['echo "Hello World!"'])
34
+ end
30
35
  end
31
36
  end
@@ -12,39 +12,49 @@ describe Gusteau::Node do
12
12
  end
13
13
  end
14
14
 
15
+ let(:before_hooks) { ['bundle', 'vagrant up'] }
16
+
15
17
  let(:node) do
16
18
  config = {
17
19
  'run_list' => [ "recipe[zsh]", "recipe[git]" ],
18
- 'server' => { 'host' => 'example.com' }
20
+ 'server' => { 'host' => 'example.com' },
21
+ 'before' => before_hooks
19
22
  }
20
23
  Gusteau::Node.new 'test', config
21
24
  end
22
25
 
23
- describe "#converge" do
24
- it "should run chef with the full run_list" do
25
- dna = {
26
- :path => '/tmp/dna.json',
27
- :hash => {
28
- :instance_role => 'test',
29
- :run_list => ['recipe[zsh]', 'recipe[git]']
26
+ describe "provisioning" do
27
+ before do
28
+ node.expects(:hook).once.with 'before'
29
+ node.expects(:hook).once.with 'after'
30
+ end
31
+
32
+ describe "#converge" do
33
+ it "should run chef with the full run_list" do
34
+ dna = {
35
+ :path => '/tmp/dna.json',
36
+ :hash => {
37
+ :instance_role => 'test',
38
+ :run_list => ['recipe[zsh]', 'recipe[git]']
39
+ }
30
40
  }
31
- }
32
- node.server.chef.expects(:run).with({}, dna)
33
- node.converge
41
+ node.server.chef.expects(:run).with(dna, {})
42
+ node.converge
43
+ end
34
44
  end
35
- end
36
45
 
37
- describe "#apply" do
38
- it "should run chef with the specific run_list" do
39
- dna = {
40
- :path => '/tmp/dna.json',
41
- :hash => {
42
- :instance_role => 'test',
43
- :run_list => ['recipe[nagios]', 'role[base]']
46
+ describe "#apply" do
47
+ it "should run chef with the specific run_list" do
48
+ dna = {
49
+ :path => '/tmp/dna.json',
50
+ :hash => {
51
+ :instance_role => 'test',
52
+ :run_list => ['recipe[nagios]', 'role[base]']
53
+ }
44
54
  }
45
- }
46
- node.server.chef.expects(:run).with({}, dna)
47
- node.apply([ "recipe[nagios]", "role[base]" ], {})
55
+ node.server.chef.expects(:run).with(dna, {})
56
+ node.apply([ "recipe[nagios]", "role[base]" ], {})
57
+ end
48
58
  end
49
59
  end
50
60
 
@@ -54,4 +64,21 @@ describe Gusteau::Node do
54
64
  node.ssh
55
65
  end
56
66
  end
67
+
68
+ describe "#hook" do
69
+ it "should execute system commands" do
70
+ Kernel.expects(:system).with('bundle')
71
+ Kernel.expects(:system).with('vagrant up')
72
+ node.server.chef.expects(:run)
73
+ node.apply([], {})
74
+ end
75
+
76
+ context "command doesn't succeed" do
77
+ let(:before_hooks) { %w{ohwhatthehellerror} }
78
+
79
+ it "should exit with error" do
80
+ proc { node.apply([], {}) }.must_raise SystemExit
81
+ end
82
+ end
83
+ end
57
84
  end
@@ -1,3 +1,6 @@
1
+ before:
2
+ - bundle exec berks install --path ./cookbooks
3
+
1
4
  environments:
2
5
  example:
3
6
  attributes:
@@ -4,7 +4,7 @@ driver_plugin: vagrant
4
4
  platforms:
5
5
  - name: ubuntu-13.04
6
6
  driver_config:
7
- box: opscode-ubuntu-13.04
7
+ box: example-box # opscode-ubuntu-13.04
8
8
  box_url: https://opscode-vm.s3.amazonaws.com/vagrant/opscode_ubuntu-13.04_provisionerless.box
9
9
  require_chef_omnibus: true
10
10
 
data/template/Gemfile CHANGED
@@ -6,6 +6,6 @@ gem 'berkshelf'
6
6
  gem 'gusteau'
7
7
 
8
8
  group :integration do
9
- gem 'test-kitchen', github: 'opscode/test-kitchen'
9
+ gem 'test-kitchen', '~> 1.0.0.alpha.7'
10
10
  gem 'kitchen-vagrant', '~> 0.10.0'
11
11
  end
data/template/init.sh CHANGED
@@ -7,9 +7,6 @@ ok() { echo -e "\033[00;32m$1\033[0m"; }
7
7
  info "Installing gem dependencies..."
8
8
  bundle
9
9
 
10
- info "Downloading cookbooks..."
11
- bundle exec berks install --path ./cookbooks
12
-
13
10
  if [ ! $(vagrant -v | cut -f3 -d ' ' | cut -f2 -d '.') = "2" ]; then
14
11
  error "Sorry, 'gusteau init' only works with Vagrant 1.2.x"
15
12
  exit 1
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gusteau
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2.dev
4
+ version: 1.0.3.dev
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-07-05 00:00:00.000000000 Z
13
+ date: 2013-07-07 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: optitron
@@ -285,7 +285,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
285
285
  version: '0'
286
286
  segments:
287
287
  - 0
288
- hash: 1972838977099657427
288
+ hash: -1682856364526822878
289
289
  required_rubygems_version: !ruby/object:Gem::Requirement
290
290
  none: false
291
291
  requirements: