gusteau 1.0.2.dev → 1.0.3.dev

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/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: