gusteau 1.0.3.dev → 1.0.4.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,5 +1,10 @@
1
+ ## 1.0.4.dev / 2013-07-08
2
+ * Bugfix: `after` hook was not taking effect
3
+ * Add a quick `show nodename` subcommand for printing out individual node configuration
4
+ * Add an ability to configure `cookbooks_path` and `roles_path` from within `.gusteau.yml`
5
+
1
6
  ## 1.0.3.dev / 2013-07-07
2
- * Implement 'before' and 'after' hooks (global and environment-based)
7
+ * Implement `before` and `after` hooks (global and environment-based)
3
8
 
4
9
  ## 1.0.2.dev / 2013-07-06
5
10
  * Fix Ruby 1.8.7 and Rubinius compatibility
data/bin/gusteau CHANGED
@@ -40,21 +40,31 @@ class Gusteau::CLI < Optitron::CLI
40
40
 
41
41
  desc 'Lists all known nodes'
42
42
  def list
43
- puts "Known nodes are:\n - #{nodes.keys.join("\n - ")}"
43
+ puts nodes_list
44
+ end
45
+
46
+ desc 'Show the configuration of a specific node'
47
+ def show(node_name)
48
+ puts node(node_name).config.to_yaml
44
49
  end
45
50
 
46
51
  private
47
52
 
48
53
  def node(node_name)
49
54
  unless node = nodes[node_name]
50
- abort "Node '#{node_name}' is unknown. Known nodes are #{nodes.keys.join(', ')}."
55
+ abort "Node '#{node_name}' is unknown. #{nodes_list}"
51
56
  else
52
57
  node
53
58
  end
54
59
  end
55
60
 
56
61
  def nodes
57
- @nodes ||= Gusteau::Config.nodes(".gusteau.yml")
62
+ Gusteau::Config.read('.gusteau.yml')
63
+ Gusteau::Config.nodes
64
+ end
65
+
66
+ def nodes_list
67
+ "Known nodes are:\n - #{nodes.keys.join("\n - ")}"
58
68
  end
59
69
 
60
70
  end
data/lib/gusteau/chef.rb CHANGED
@@ -26,14 +26,12 @@ module Gusteau
26
26
  private
27
27
 
28
28
  def src_files(dna_path)
29
- %W(
29
+ list = %W(
30
30
  #{dna_path}
31
31
  #{File.expand_path("../../../bootstrap", __FILE__)}
32
- ./cookbooks
33
- ./site-cookbooks
34
- ./roles
35
- ./data_bags
36
- ).select { |file| File.exists? file }
32
+ data_bags
33
+ ) + Gusteau::Config.settings['cookbooks_path'] + [ Gusteau::Config.settings['roles_path']]
34
+ list.select { |file| File.exists? file }
37
35
  end
38
36
  end
39
37
  end
@@ -2,42 +2,66 @@ require 'gusteau/erb'
2
2
  require 'hash_deep_merge'
3
3
 
4
4
  module Gusteau
5
- module Config
6
- extend self
7
- extend Gusteau::ERB
8
-
9
- def nodes(config_path)
10
- if File.exists?(config_path)
11
- config = read_erb_yaml(config_path)
12
- env_config = config['environments']
13
-
14
- env_config.inject({}) do |nodes, (env_name, env_hash)|
15
- if env_hash['nodes']
16
- env_hash['nodes'].each_pair do |node_name, node_hash|
17
- node_name = "#{env_name}-#{node_name}"
18
- nodes[node_name] = build_node(config, node_name, env_hash, node_hash)
19
- end
20
- end
21
- nodes
22
- end
5
+ class Config
6
+ include Gusteau::ERB
7
+
8
+ def self.read(config_path)
9
+ @instance = Gusteau::Config.new(config_path)
10
+ end
11
+
12
+ def self.nodes
13
+ @instance.send(:nodes)
14
+ end
15
+
16
+ def self.settings
17
+ @instance.send(:settings)
18
+ end
19
+
20
+ def initialize(config_path)
21
+ @config = if File.exists?(config_path)
22
+ read_erb_yaml(config_path)
23
23
  else
24
24
  abort ".gusteau.yml not found"
25
25
  end
26
26
  end
27
27
 
28
+ private
29
+
30
+ def nodes
31
+ env_config = @config['environments']
32
+
33
+ @nodes ||= env_config.inject({}) do |nodes, (env_name, env_hash)|
34
+ if env_hash['nodes']
35
+ env_hash['nodes'].each_pair do |node_name, node_hash|
36
+ node_name = "#{env_name}-#{node_name}"
37
+ nodes[node_name] = build_node(node_name, env_hash, node_hash)
38
+ end
39
+ end
40
+ nodes
41
+ end
42
+ end
43
+
44
+ def settings
45
+ {
46
+ 'cookbooks_path' => @config['cookbooks_path'] || ['cookbooks', 'site-cookbooks'],
47
+ 'roles_path' => @config['roles_path'] || 'roles'
48
+ }
49
+ end
50
+
28
51
  #
29
52
  # Node attributes get deep-merged with the environment ones
30
53
  # Node run_list overrides the environment one
31
54
  # Environment before hooks override global ones
32
55
  #
33
- def build_node(config, node_name, env_hash, node_hash)
34
- config = {
56
+ def build_node(node_name, env_hash, node_hash)
57
+ node_config = {
35
58
  'server' => node_hash,
36
59
  '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']
60
+ 'run_list' => node_hash['run_list'] || env_hash['run_list'],
61
+ 'before' => env_hash['before'] || @config['before'],
62
+ 'after' => env_hash['after'] || @config['after']
39
63
  }
40
- Gusteau::Node.new(node_name, config)
64
+ Gusteau::Node.new(node_name, node_config)
41
65
  end
42
66
  end
43
67
  end
data/lib/gusteau/node.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'gusteau/server'
2
- require 'gusteau/chef'
3
2
 
4
3
  module Gusteau
5
4
  class Node
@@ -7,11 +6,11 @@ module Gusteau
7
6
 
8
7
  attr_reader :name, :config, :server
9
8
 
10
- def initialize(name, config)
11
- @name = name
12
- @config = config
9
+ def initialize(node_name, node_config)
10
+ @name = node_name
11
+ @config = node_config
13
12
 
14
- @server = Server.new(@config['server']) if @config['server']
13
+ @server = Server.new(@config['server'])
15
14
  @dna_path = '/tmp/dna.json'
16
15
  end
17
16
 
@@ -1,5 +1,6 @@
1
- require 'gusteau/log'
1
+ require 'gusteau/chef'
2
2
  require 'gusteau/ssh'
3
+ require 'gusteau/log'
3
4
 
4
5
  module Gusteau
5
6
  class Server
@@ -8,12 +9,12 @@ module Gusteau
8
9
 
9
10
  attr_reader :host, :port, :user, :password, :chef
10
11
 
11
- def initialize(config, opts={})
12
+ def initialize(config)
12
13
  @host = config['host']
13
14
  @port = config['port'] || 22
14
15
  @user = config['user'] || 'root'
15
16
  @password = config['password']
16
- @chef = Gusteau::Chef.new(self, config['platform'])
17
+ @chef = Gusteau::Chef.new(self, config['platform'])
17
18
  end
18
19
 
19
20
  def upload(files_and_dirs, dest_dir, opts={})
@@ -9,7 +9,7 @@ module Gusteau
9
9
  extend Gusteau::Log
10
10
 
11
11
  def detect(config)
12
- options = Hashie::Mash.new
12
+ options = Hashie::Mash.new
13
13
  options.defaults = Hashie::Mash.new
14
14
 
15
15
  yield options if block_given?
@@ -17,7 +17,9 @@ module Gusteau
17
17
  end
18
18
 
19
19
  def define_nodes(config, options, prefix = nil)
20
- Gusteau::Config.nodes(options[:config_path] || ".gusteau.yml").each_pair do |name, node|
20
+ Gusteau::Config.read(options[:config_path] || ".gusteau.yml")
21
+
22
+ Gusteau::Config.nodes.each_pair do |name, node|
21
23
  if node.config['server']['vagrant']
22
24
  define_vm config, node, options
23
25
  end
@@ -75,10 +77,10 @@ module Gusteau
75
77
  def define_provisioner(instance, node)
76
78
  instance.vm.provision 'chef_solo' do |chef|
77
79
  chef.data_bags_path = 'data_bags'
78
- chef.cookbooks_path = ['cookbooks', 'site-cookbooks']
79
- chef.roles_path = 'roles'
80
- chef.json = node.config['attributes'] || {}
81
- chef.run_list = node.config['run_list'] || []
80
+ chef.cookbooks_path = Gusteau::Config.settings['cookbooks_path']
81
+ chef.roles_path = Gusteau::Config.settings['roles_path']
82
+ chef.json = node.config['attributes'] || {}
83
+ chef.run_list = node.config['run_list'] || []
82
84
  end
83
85
  end
84
86
  end
@@ -1,3 +1,3 @@
1
1
  module Gusteau
2
- VERSION = "1.0.3.dev"
2
+ VERSION = "1.0.4.dev"
3
3
  end
@@ -0,0 +1,5 @@
1
+ cookbooks_path:
2
+ - private-cookbooks
3
+ - /home/user/.cookbooks
4
+
5
+ roles_path: basic-roles
@@ -1,6 +1,8 @@
1
1
  require './spec/spec_helper.rb'
2
2
 
3
3
  describe Gusteau::Chef do
4
+ before { Gusteau::Config.read('./spec/config/emile.yml') }
5
+
4
6
  let(:platform) { 'centos' }
5
7
  let(:server) { Gusteau::Server.new('host' => 'example.com', 'platform' => platform) }
6
8
  let(:chef) { Gusteau::Chef.new(server, platform) }
@@ -2,7 +2,7 @@ require './spec/spec_helper'
2
2
 
3
3
  describe Gusteau::Config do
4
4
  context "config not found" do
5
- subject { Gusteau::Config.nodes("/tmp/nonexistent/nonsence111") }
5
+ subject { Gusteau::Config.read("/tmp/nonexistent/nonsence111") }
6
6
 
7
7
  it "should exit with an error" do
8
8
  proc { subject }.must_raise SystemExit
@@ -10,27 +10,49 @@ describe Gusteau::Config do
10
10
  end
11
11
 
12
12
  context "config is found" do
13
- let(:nodes) { Gusteau::Config.nodes("./spec/config/remi.yml") }
13
+ before { Gusteau::Config.read("./spec/config/remi.yml") }
14
14
 
15
- it "should name nodes as per environment-node" do
16
- nodes.keys.sort.must_equal ["production-db", "production-www", "staging-vm"]
17
- end
15
+ describe "#nodes" do
16
+ let(:nodes) { Gusteau::Config.nodes }
18
17
 
19
- it "should override run_list if defined for a node" do
20
- nodes['production-db'].config['run_list'].must_equal(["recipe[git]", "recipe[postgresql::server]"])
21
- nodes['production-www'].config['run_list'].must_equal(["recipe[varnish]", "recipe[nginx]"])
22
- end
18
+ it "should name nodes as per environment-node" do
19
+ nodes.keys.sort.must_equal ["production-db", "production-www", "staging-vm"]
20
+ end
21
+
22
+ it "should override run_list if defined for a node" do
23
+ nodes['production-db'].config['run_list'].must_equal(["recipe[git]", "recipe[postgresql::server]"])
24
+ nodes['production-www'].config['run_list'].must_equal(["recipe[varnish]", "recipe[nginx]"])
25
+ end
26
+
27
+ it "should deeply merge the attributes" do
28
+ nodes['production-db'].config['attributes'].must_equal({
29
+ 'users' => ['alex', 'simon'],
30
+ 'mysql' => {'server_port' => 3307, 'server_root_password' => 'prodsecret' }
31
+ })
32
+ end
23
33
 
24
- it "should deeply merge the attributes" do
25
- nodes['production-db'].config['attributes'].must_equal({
26
- 'users' => ['alex', 'simon'],
27
- 'mysql' => {'server_port' => 3307, 'server_root_password' => 'prodsecret' }
28
- })
34
+ it "should override the global before hook with an environment one" do
35
+ nodes['production-www'].config['before'].must_equal(['bundle exec berks install'])
36
+ nodes['staging-vm'].config['before'].must_equal(['echo "Hello World!"'])
37
+ end
29
38
  end
30
39
 
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!"'])
40
+ describe "#settings" do
41
+ let(:settings) { Gusteau::Config.settings }
42
+
43
+ it "should have defaults for cookbooks_path, roles_path" do
44
+ settings['cookbooks_path'].must_equal ['cookbooks', 'site-cookbooks']
45
+ settings['roles_path'].must_equal 'roles'
46
+ end
47
+
48
+ context "settings defined in the config yml" do
49
+ before { Gusteau::Config.read("./spec/config/emile.yml") }
50
+
51
+ it "should have defaults for cookbooks_path, roles_path" do
52
+ settings['cookbooks_path'].must_equal ['private-cookbooks', '/home/user/.cookbooks']
53
+ settings['roles_path'].must_equal 'basic-roles'
54
+ end
55
+ end
34
56
  end
35
57
  end
36
58
  end
@@ -1,8 +1,9 @@
1
1
  require './spec/spec_helper.rb'
2
2
 
3
3
  describe Gusteau::SSHConfig do
4
- let(:nodes) { Gusteau::Config.nodes("./spec/config/gusteau.yml") }
5
- subject { Gusteau::SSHConfig.new(nodes) }
4
+ before { Gusteau::Config.read("./spec/config/gusteau.yml") }
5
+
6
+ subject { Gusteau::SSHConfig.new(Gusteau::Config.nodes) }
6
7
 
7
8
  let(:config) do
8
9
  <<-eos
@@ -49,73 +49,76 @@ describe Gusteau::Vagrant do
49
49
  end
50
50
  end
51
51
 
52
- describe "#vm_config" do
53
- let(:node) { Gusteau::Config.nodes("./spec/config/gusteau.yml")['development-playground'] }
54
- subject { Gusteau::Vagrant.vm_config(node, options) }
55
-
56
- let(:defaults) do
57
- {
58
- :box_url => 'https://opscode.s3.amazonaws.com/centos-6.4.box',
59
- :cpus => 64,
60
- :memory => 4096,
61
- }
62
- end
63
- let(:prefix) { 'hyper' }
64
- let(:options) { { :defaults => defaults, :prefix => prefix } }
65
-
66
- let(:expected_label) { 'hyper-development-playground' }
67
- let(:expected_config) do
68
- {
69
- :name => 'development-playground',
70
- :label => expected_label,
71
- :box_url => 'https://opscode.s3.amazonaws.com/centos-6.4.box',
72
- :ip => '192.168.100.21',
73
- :cpus => 2,
74
- :memory => 4096
75
- }
76
- end
52
+ describe "internal methods" do
53
+ before { Gusteau::Config.read("./spec/config/gusteau.yml") }
54
+ let(:node) { Gusteau::Config.nodes['development-playground'] }
55
+
56
+ describe "#vm_config" do
57
+ subject { Gusteau::Vagrant.vm_config(node, options) }
58
+
59
+ let(:defaults) do
60
+ {
61
+ :box_url => 'https://opscode.s3.amazonaws.com/centos-6.4.box',
62
+ :cpus => 64,
63
+ :memory => 4096,
64
+ }
65
+ end
66
+ let(:prefix) { 'hyper' }
67
+ let(:options) { { :defaults => defaults, :prefix => prefix } }
68
+
69
+ let(:expected_label) { 'hyper-development-playground' }
70
+ let(:expected_config) do
71
+ {
72
+ :name => 'development-playground',
73
+ :label => expected_label,
74
+ :box_url => 'https://opscode.s3.amazonaws.com/centos-6.4.box',
75
+ :ip => '192.168.100.21',
76
+ :cpus => 2,
77
+ :memory => 4096
78
+ }
79
+ end
77
80
 
78
- it "should merge in defaults" do
79
- subject.must_equal(expected_config)
80
- end
81
+ it "should merge in defaults" do
82
+ subject.must_equal(expected_config)
83
+ end
81
84
 
82
- context "prefix not specified" do
83
- let(:prefix) { nil }
84
- let(:expected_label) { 'development-playground' }
85
+ context "prefix not specified" do
86
+ let(:prefix) { nil }
87
+ let(:expected_label) { 'development-playground' }
85
88
 
86
- it "should omit the prefix" do
87
- subject.must_equal(expected_config)
89
+ it "should omit the prefix" do
90
+ subject.must_equal(expected_config)
91
+ end
88
92
  end
89
- end
90
93
 
91
- context "box_url not specified" do
92
- let(:defaults) { {} }
94
+ context "box_url not specified" do
95
+ let(:defaults) { {} }
93
96
 
94
- it "should raise an exception" do
95
- proc { subject }.must_raise RuntimeError
97
+ it "should raise an exception" do
98
+ proc { subject }.must_raise RuntimeError
99
+ end
96
100
  end
97
101
  end
98
- end
99
102
 
100
- describe "#define_provisioner" do
101
- let(:node) { Gusteau::Config.nodes("./spec/config/gusteau.yml")['development-playground'] }
102
- let(:chef) { stub_everything('chef') }
103
+ describe "#define_provisioner" do
104
+ let(:chef) { stub_everything('chef') }
103
105
 
104
- before do
105
- def subvm.provision(provider); yield chef; end
106
- subvm.expects(:chef).returns(chef)
106
+ before do
107
+ def subvm.provision(provider); yield chef; end
108
+ subvm.expects(:chef).returns(chef)
107
109
 
108
- instance.expects(:vm).at_least_once.returns(subvm)
109
- end
110
+ instance.expects(:vm).at_least_once.returns(subvm)
111
+ end
110
112
 
111
- it "should set the correct Chef JSON" do
112
- chef.expects('json='.to_sym).with({"mysql"=>{"server_root_password"=>"guesswhat"}})
113
- Gusteau::Vagrant.define_provisioner(instance, node)
114
- end
113
+ it "should set the correct Chef JSON" do
114
+ chef.expects('json='.to_sym).with({"mysql"=>{"server_root_password"=>"guesswhat"}})
115
+ Gusteau::Vagrant.define_provisioner(instance, node)
116
+ end
115
117
 
116
- it "should set the correct Chef run_list" do
117
- chef.expects('run_list='.to_sym).with(["recipe[zsh]", "recipe[mysql::server]"])
118
- Gusteau::Vagrant.define_provisioner(instance, node)
118
+ it "should set the correct Chef run_list" do
119
+ chef.expects('run_list='.to_sym).with(["recipe[zsh]", "recipe[mysql::server]"])
120
+ Gusteau::Vagrant.define_provisioner(instance, node)
121
+ end
119
122
  end
120
123
  end
121
124
  end
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.3.dev
4
+ version: 1.0.4.dev
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -240,6 +240,7 @@ files:
240
240
  - lib/gusteau/ssh_config.rb
241
241
  - lib/gusteau/vagrant.rb
242
242
  - lib/gusteau/version.rb
243
+ - spec/config/emile.yml
243
244
  - spec/config/gusteau.yml
244
245
  - spec/config/remi.yml
245
246
  - spec/lib/gusteau/bureau_spec.rb
@@ -285,7 +286,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
285
286
  version: '0'
286
287
  segments:
287
288
  - 0
288
- hash: -1682856364526822878
289
+ hash: 201267403645685756
289
290
  required_rubygems_version: !ruby/object:Gem::Requirement
290
291
  none: false
291
292
  requirements:
@@ -299,6 +300,7 @@ signing_key:
299
300
  specification_version: 3
300
301
  summary: Making servers provisioning enjoyable since 2013.
301
302
  test_files:
303
+ - spec/config/emile.yml
302
304
  - spec/config/gusteau.yml
303
305
  - spec/config/remi.yml
304
306
  - spec/lib/gusteau/bureau_spec.rb