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 +6 -1
- data/bin/gusteau +13 -3
- data/lib/gusteau/chef.rb +4 -6
- data/lib/gusteau/config.rb +47 -23
- data/lib/gusteau/node.rb +4 -5
- data/lib/gusteau/server.rb +4 -3
- data/lib/gusteau/vagrant.rb +8 -6
- data/lib/gusteau/version.rb +1 -1
- data/spec/config/emile.yml +5 -0
- data/spec/lib/gusteau/chef_spec.rb +2 -0
- data/spec/lib/gusteau/config_spec.rb +39 -17
- data/spec/lib/gusteau/ssh_config_spec.rb +3 -2
- data/spec/lib/gusteau/vagrant_spec.rb +57 -54
- metadata +4 -2
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
|
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
|
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.
|
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
|
-
|
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
|
-
|
33
|
-
|
34
|
-
|
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
|
data/lib/gusteau/config.rb
CHANGED
@@ -2,42 +2,66 @@ require 'gusteau/erb'
|
|
2
2
|
require 'hash_deep_merge'
|
3
3
|
|
4
4
|
module Gusteau
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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(
|
34
|
-
|
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']
|
38
|
-
'before' => env_hash['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,
|
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(
|
11
|
-
@name =
|
12
|
-
@config =
|
9
|
+
def initialize(node_name, node_config)
|
10
|
+
@name = node_name
|
11
|
+
@config = node_config
|
13
12
|
|
14
|
-
@server = Server.new(@config['server'])
|
13
|
+
@server = Server.new(@config['server'])
|
15
14
|
@dna_path = '/tmp/dna.json'
|
16
15
|
end
|
17
16
|
|
data/lib/gusteau/server.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
require 'gusteau/
|
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
|
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
|
17
|
+
@chef = Gusteau::Chef.new(self, config['platform'])
|
17
18
|
end
|
18
19
|
|
19
20
|
def upload(files_and_dirs, dest_dir, opts={})
|
data/lib/gusteau/vagrant.rb
CHANGED
@@ -9,7 +9,7 @@ module Gusteau
|
|
9
9
|
extend Gusteau::Log
|
10
10
|
|
11
11
|
def detect(config)
|
12
|
-
options
|
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.
|
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 = ['
|
79
|
-
chef.roles_path = '
|
80
|
-
chef.json
|
81
|
-
chef.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
|
data/lib/gusteau/version.rb
CHANGED
@@ -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.
|
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
|
-
|
13
|
+
before { Gusteau::Config.read("./spec/config/remi.yml") }
|
14
14
|
|
15
|
-
|
16
|
-
nodes
|
17
|
-
end
|
15
|
+
describe "#nodes" do
|
16
|
+
let(:nodes) { Gusteau::Config.nodes }
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
25
|
-
|
26
|
-
'
|
27
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
5
|
-
|
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 "
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
{
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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
|
-
|
79
|
-
|
80
|
-
|
81
|
+
it "should merge in defaults" do
|
82
|
+
subject.must_equal(expected_config)
|
83
|
+
end
|
81
84
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
+
context "prefix not specified" do
|
86
|
+
let(:prefix) { nil }
|
87
|
+
let(:expected_label) { 'development-playground' }
|
85
88
|
|
86
|
-
|
87
|
-
|
89
|
+
it "should omit the prefix" do
|
90
|
+
subject.must_equal(expected_config)
|
91
|
+
end
|
88
92
|
end
|
89
|
-
end
|
90
93
|
|
91
|
-
|
92
|
-
|
94
|
+
context "box_url not specified" do
|
95
|
+
let(:defaults) { {} }
|
93
96
|
|
94
|
-
|
95
|
-
|
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
|
-
|
101
|
-
|
102
|
-
let(:chef) { stub_everything('chef') }
|
103
|
+
describe "#define_provisioner" do
|
104
|
+
let(:chef) { stub_everything('chef') }
|
103
105
|
|
104
|
-
|
105
|
-
|
106
|
-
|
106
|
+
before do
|
107
|
+
def subvm.provision(provider); yield chef; end
|
108
|
+
subvm.expects(:chef).returns(chef)
|
107
109
|
|
108
|
-
|
109
|
-
|
110
|
+
instance.expects(:vm).at_least_once.returns(subvm)
|
111
|
+
end
|
110
112
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
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
|
-
|
117
|
-
|
118
|
-
|
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.
|
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:
|
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
|