sous-chef 0.0.3 → 0.0.4
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/.gitignore +1 -0
- data/Gemfile.lock +1 -1
- data/README.md +25 -7
- data/Rakefile +16 -0
- data/lib/sous-chef/manager.rb +25 -0
- data/lib/sous-chef/node.rb +54 -0
- data/lib/sous-chef/parser.rb +22 -0
- data/lib/sous-chef/tasks.rb +10 -78
- data/lib/sous-chef.rb +16 -4
- data/lib/tasks/sous-chef.rake +2 -0
- data/lib/templates/nodes.example.yml +13 -0
- data/sous-chef.gemspec +4 -4
- data/spec/fixtures/single_node.yml +7 -0
- data/spec/fixtures/some_nodes.yml +12 -0
- data/spec/sous-chef/manager_spec.rb +22 -0
- data/spec/sous-chef/node_spec.rb +35 -0
- data/spec/sous-chef/parser_spec.rb +20 -0
- data/spec/spec_helper.rb +11 -0
- metadata +21 -4
- data/lib/sous-chef/tasks/sous-chef.rake +0 -2
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
#
|
1
|
+
# Sous Chef
|
2
2
|
|
3
3
|
Note: This gem is a work in progress.
|
4
4
|
|
5
|
-
Manage knife-solo nodes.
|
5
|
+
Manage [knife-solo](http://matschaffer.github.com/knife-solo/) nodes.
|
6
6
|
|
7
7
|
## Install
|
8
8
|
|
@@ -12,20 +12,38 @@ Add the following to your `Rakefile`:
|
|
12
12
|
require 'sous-chef'
|
13
13
|
```
|
14
14
|
|
15
|
+
You may run `rake sous_chef` to generate sample `nodes.yml` to `nodes/nodes.yml`
|
16
|
+
|
15
17
|
## Configure
|
16
18
|
|
17
19
|
Create configuration in knife-solo nodes dir e.g. `nodes/nodes.yml`. Node
|
18
20
|
configuration is used for sshconfig as well as nodename. Example `nodes.yml`:
|
19
21
|
|
20
22
|
```yaml
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
# Format:
|
24
|
+
#
|
25
|
+
# <node name>:
|
26
|
+
# node_config: <knife-solo node config e.g. nodes/someNode.json>
|
27
|
+
# ssh_config:
|
28
|
+
# <ssh config options>
|
29
|
+
# e.g.
|
30
|
+
# Host: <host alias. defaults to node name>
|
31
|
+
# HostName: 12.34.56.789
|
32
|
+
# Port: 1234
|
33
|
+
# IdentityFile: ~/.ssh/other_id_rsa
|
34
|
+
#
|
25
35
|
|
36
|
+
SuperAwesomeNode:
|
37
|
+
node_config: nodes/some_node.json
|
38
|
+
ssh_config:
|
39
|
+
HostName: 12.34.56.789
|
40
|
+
Port 1234
|
41
|
+
IdentityFile: ~/.ssh/other_id_rsa
|
26
42
|
|
27
43
|
OtherAwesome:
|
28
|
-
|
44
|
+
node_config: nodes/some_node.json
|
45
|
+
ssh_config:
|
46
|
+
HostName: 12.34.56.789
|
29
47
|
```
|
30
48
|
|
31
49
|
## Usage
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'bundler/gem_tasks'
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
|
8
|
+
desc 'Default: run unit tests.'
|
9
|
+
task :default => :spec
|
10
|
+
|
11
|
+
desc "Run all specs"
|
12
|
+
RSpec::Core::RakeTask.new do |t|
|
13
|
+
t.pattern = 'spec/**/*_spec.rb'
|
14
|
+
t.rspec_opts = '--color'
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module SousChef
|
2
|
+
class Manager
|
3
|
+
attr_accessor :nodes
|
4
|
+
attr_reader :parser
|
5
|
+
|
6
|
+
def initialize(config_file)
|
7
|
+
@parser = Parser.new(config_file)
|
8
|
+
@nodes = {}
|
9
|
+
initialize_nodes
|
10
|
+
end
|
11
|
+
|
12
|
+
def all
|
13
|
+
@nodes.keys
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def initialize_nodes
|
19
|
+
@parser.parse.each do |node, settings|
|
20
|
+
@nodes[node] = Node.new(node, settings)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class SousChef::Node
|
2
|
+
attr_reader :name
|
3
|
+
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
def initialize(node, settings)
|
7
|
+
@settings = settings
|
8
|
+
@name = node
|
9
|
+
end
|
10
|
+
|
11
|
+
def config
|
12
|
+
@config ||= @settings['node_config'] || {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def hostname
|
16
|
+
@hostname ||= ssh_hash['Host'] || @name
|
17
|
+
end
|
18
|
+
|
19
|
+
def ssh_config
|
20
|
+
@ssh_config ||= begin
|
21
|
+
config = "Host #{hostname}\n"
|
22
|
+
ssh_attrs.each do |key, value|
|
23
|
+
config << " #{key} #{value}\n"
|
24
|
+
end
|
25
|
+
config
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def ssh_config_path
|
30
|
+
@ssh_config_file ||= begin
|
31
|
+
config_file = Tempfile.new('agent_ssh_config')
|
32
|
+
config_file.write(ssh_config)
|
33
|
+
config_file.close
|
34
|
+
at_exit { config_file.delete }
|
35
|
+
config_file
|
36
|
+
end
|
37
|
+
@ssh_config_file.path
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def ssh_hash
|
43
|
+
@ssh_hash ||= @settings['ssh_config'] || {}
|
44
|
+
end
|
45
|
+
|
46
|
+
def ssh_attrs
|
47
|
+
@ssh_attrs ||= begin
|
48
|
+
ssh_attrs = ssh_hash.clone
|
49
|
+
ssh_attrs.delete('Host')
|
50
|
+
ssh_attrs
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class SousChef::Parser
|
2
|
+
attr_reader :config_file
|
3
|
+
|
4
|
+
def initialize(config_file)
|
5
|
+
@config_file = config_file
|
6
|
+
end
|
7
|
+
|
8
|
+
def parse
|
9
|
+
parse_yaml(@config_file)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def parse_yaml(config_file)
|
15
|
+
if File.exists?(config_file)
|
16
|
+
YAML.load_file(config_file)
|
17
|
+
else
|
18
|
+
{}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
data/lib/sous-chef/tasks.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
require 'yaml'
|
1
|
+
require 'rake'
|
3
2
|
|
4
3
|
def run(command)
|
5
4
|
puts "Running: #{command}"
|
@@ -8,97 +7,30 @@ def run(command)
|
|
8
7
|
end
|
9
8
|
|
10
9
|
def run_knife(command, node)
|
11
|
-
run "knife solo #{command} -F #{
|
10
|
+
run "knife solo #{command} -F #{node.ssh_config_path} #{node.hostname} -N #{node.name} #{node.config}"
|
12
11
|
end
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
puts "Can't find #{agents_path}"
|
18
|
-
exit 1
|
19
|
-
end
|
20
|
-
YAML.load_file(agents_path)
|
21
|
-
end
|
22
|
-
|
23
|
-
def agents_ssh_config_path
|
24
|
-
@agents_ssh_config_path ||= begin
|
25
|
-
ssh_config_file = Tempfile.new('agent_ssh_config')
|
26
|
-
agents.each do |node, attrs|
|
27
|
-
ssh_config_file.write("Host #{node}\n")
|
28
|
-
attrs.each do |key, value|
|
29
|
-
ssh_config_file.write(" #{key} #{value}\n")
|
30
|
-
end
|
31
|
-
end
|
32
|
-
ssh_config_file.close
|
33
|
-
at_exit { ssh_config_file.delete }
|
34
|
-
ssh_config_file.path
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def agent_names
|
39
|
-
agents.map { |key, value| key }
|
40
|
-
end
|
41
|
-
|
42
|
-
agent_names.each do |node|
|
43
|
-
namespace node do
|
44
|
-
desc "Run knife solo prepare for #{node}"
|
13
|
+
SousChef::Manager.new(SousChef::CONFIG_FILE).nodes.each do |name, node|
|
14
|
+
namespace name do
|
15
|
+
desc "Run knife solo prepare for #{name}"
|
45
16
|
task :prepare do
|
46
17
|
run_knife 'prepare', node
|
47
18
|
end
|
48
19
|
|
49
|
-
desc "Run knife solo cook for #{
|
20
|
+
desc "Run knife solo cook for #{name}"
|
50
21
|
task :cook do
|
51
22
|
run_knife 'cook', node
|
52
23
|
end
|
53
24
|
|
54
|
-
desc "Run knife solo bootstrap for #{
|
25
|
+
desc "Run knife solo bootstrap for #{name}"
|
55
26
|
task :bootstrap do
|
56
27
|
run_knife 'bootstrap', node
|
57
28
|
end
|
58
29
|
end
|
59
30
|
end
|
60
31
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
ssh_config_file = Tempfile.new('vagrant-ssh-config')
|
65
|
-
ssh_config_file.write(`vagrant ssh-config`)
|
66
|
-
ssh_config_file.write(' LogLevel quiet')
|
67
|
-
ssh_config_file.close
|
68
|
-
ssh_config_file.path
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def run_knife_vagrant(command)
|
73
|
-
run "knife solo #{command} -F #{vagrant_ssh_config_path} default nodes/buildAgent.json"
|
74
|
-
end
|
75
|
-
|
76
|
-
desc "Start the VM for the Vagrant Utility box"
|
77
|
-
task :up do
|
78
|
-
run "vagrant up"
|
79
|
-
end
|
80
|
-
|
81
|
-
desc "Prepare the Vagrant Utility box for provisioning"
|
82
|
-
task :prepare => [:up] do
|
83
|
-
run_knife_vagrant 'prepare'
|
84
|
-
end
|
85
|
-
|
86
|
-
desc "Provision the Vagrant Utility box"
|
87
|
-
task :cook do
|
88
|
-
run_knife_vagrant 'cook'
|
89
|
-
end
|
90
|
-
|
91
|
-
desc "Bootstrap (prepare & cook) the Vagrant Utility box"
|
92
|
-
task :bootstrap => [:up] do
|
93
|
-
run_knife_vagrant 'bootstrap'
|
94
|
-
end
|
95
|
-
|
96
|
-
desc "Destroy Vagrant Utility box"
|
97
|
-
task :destroy do
|
98
|
-
run "vagrant destroy -f"
|
99
|
-
end
|
100
|
-
|
101
|
-
desc "Cleans Vagrant Utility box, creating a fresh box"
|
102
|
-
task :clean => [:destroy, :up]
|
32
|
+
desc "Generate nodes.yml example config"
|
33
|
+
task :sous_chef do
|
34
|
+
SousChef.create_config
|
103
35
|
end
|
104
36
|
|
data/lib/sous-chef.rb
CHANGED
@@ -1,10 +1,22 @@
|
|
1
|
-
require 'rake'
|
2
|
-
|
3
|
-
load 'sous-chef/tasks.rb'
|
4
1
|
|
5
2
|
module SousChef
|
3
|
+
CONFIG_FILE = File.join(Dir.pwd, "nodes", "nodes.yml")
|
4
|
+
|
6
5
|
class << self
|
7
|
-
|
6
|
+
def create_config
|
7
|
+
template = File.expand_path(File.join(File.dirname(__FILE__), 'templates', 'nodes.example.yml'))
|
8
|
+
if File.exists?(CONFIG_FILE)
|
9
|
+
puts "nodes.yml already exists"
|
10
|
+
else
|
11
|
+
puts "Coping example nodes.yml and placing in #{SousChef::CONFIG_FILE}"
|
12
|
+
FileUtils.cp(template, CONFIG_FILE)
|
13
|
+
end
|
14
|
+
end
|
8
15
|
end
|
9
16
|
end
|
10
17
|
|
18
|
+
require 'sous-chef/parser.rb'
|
19
|
+
require 'sous-chef/node.rb'
|
20
|
+
require 'sous-chef/manager.rb'
|
21
|
+
require 'sous-chef/tasks.rb'
|
22
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Format:
|
2
|
+
#
|
3
|
+
# <node name>:
|
4
|
+
# node_config: <knife-solo node config e.g. nodes/someNode.json>
|
5
|
+
# ssh_config:
|
6
|
+
# <ssh config options>
|
7
|
+
# e.g.
|
8
|
+
# Host: <host alias. defaults to node name>
|
9
|
+
# HostName: 12.34.56.789
|
10
|
+
# Port: 1234
|
11
|
+
# IdentityFile: ~/.ssh/other_id_rsa
|
12
|
+
#
|
13
|
+
|
data/sous-chef.gemspec
CHANGED
@@ -6,13 +6,13 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.email = "shaun@substantail.com"
|
7
7
|
|
8
8
|
s.name = 'sous-chef'
|
9
|
-
s.version = "0.0.
|
9
|
+
s.version = "0.0.4"
|
10
10
|
s.description = %q{Manage knife-solo nodes}
|
11
11
|
s.summary = %q{Manage knife-solo nodes}
|
12
|
-
s.homepage
|
13
|
-
s.
|
12
|
+
s.homepage = %q{http://github.com/substantial/sous-chef}
|
13
|
+
s.license = "MIT"
|
14
14
|
|
15
|
-
s.
|
15
|
+
s.rubyforge_project = "sous-chef"
|
16
16
|
|
17
17
|
s.files = `git ls-files`.split("\n")
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SousChef::Manager do
|
4
|
+
let(:manager) { SousChef::Manager.new(File.join(SPEC_ROOT, "fixtures", "some_nodes.yml")) }
|
5
|
+
|
6
|
+
describe "#initialize" do
|
7
|
+
it "instantiates a parser with the config file" do
|
8
|
+
manager.parser.should be_a SousChef::Parser
|
9
|
+
end
|
10
|
+
|
11
|
+
it "instantiates nodes" do
|
12
|
+
manager.nodes.should be_a Hash
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#all" do
|
17
|
+
it "returns node names" do
|
18
|
+
manager.all.should =~ %w[SuperAwesomeNode OtherAwesome]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SousChef::Node do
|
4
|
+
let(:node_hash) { {
|
5
|
+
"node_config" => "some/path/to/node/config",
|
6
|
+
"ssh_config" => { "HostName" => "Some IP" }
|
7
|
+
}}
|
8
|
+
|
9
|
+
subject { SousChef::Node.new('SuperAwesomeNode', node_hash) }
|
10
|
+
|
11
|
+
describe "#name" do
|
12
|
+
its(:name) { should == "SuperAwesomeNode" }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#config" do
|
16
|
+
its(:config) { should == 'some/path/to/node/config' }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#hostname" do
|
20
|
+
its(:hostname) { should == 'SuperAwesomeNode' }
|
21
|
+
|
22
|
+
context "with host in ssh_config" do
|
23
|
+
before { node_hash["ssh_config"]["Host"] = 'Some other name'}
|
24
|
+
its(:hostname) { should == 'Some other name'}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#ssh_config" do
|
29
|
+
it "returns ssh_config" do
|
30
|
+
subject.ssh_config.should include "Host SuperAwesomeNode\n"
|
31
|
+
subject.ssh_config.should include "HostName Some IP\n"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SousChef::Parser do
|
4
|
+
describe "#initialize" do
|
5
|
+
let(:parser) { SousChef::Parser.new('some config file') }
|
6
|
+
|
7
|
+
it 'sets config file' do
|
8
|
+
parser.config_file.should == 'some config file'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#parse" do
|
13
|
+
subject { SousChef::Parser.new(File.join(SPEC_ROOT, "fixtures", "some_nodes.yml")).parse }
|
14
|
+
|
15
|
+
it "parses yaml" do
|
16
|
+
subject.keys.should =~ %w[SuperAwesomeNode OtherAwesome]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sous-chef
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -101,10 +101,21 @@ files:
|
|
101
101
|
- Gemfile
|
102
102
|
- Gemfile.lock
|
103
103
|
- README.md
|
104
|
+
- Rakefile
|
104
105
|
- lib/sous-chef.rb
|
106
|
+
- lib/sous-chef/manager.rb
|
107
|
+
- lib/sous-chef/node.rb
|
108
|
+
- lib/sous-chef/parser.rb
|
105
109
|
- lib/sous-chef/tasks.rb
|
106
|
-
- lib/
|
110
|
+
- lib/tasks/sous-chef.rake
|
111
|
+
- lib/templates/nodes.example.yml
|
107
112
|
- sous-chef.gemspec
|
113
|
+
- spec/fixtures/single_node.yml
|
114
|
+
- spec/fixtures/some_nodes.yml
|
115
|
+
- spec/sous-chef/manager_spec.rb
|
116
|
+
- spec/sous-chef/node_spec.rb
|
117
|
+
- spec/sous-chef/parser_spec.rb
|
118
|
+
- spec/spec_helper.rb
|
108
119
|
homepage: http://github.com/substantial/sous-chef
|
109
120
|
licenses:
|
110
121
|
- MIT
|
@@ -130,4 +141,10 @@ rubygems_version: 1.8.24
|
|
130
141
|
signing_key:
|
131
142
|
specification_version: 3
|
132
143
|
summary: Manage knife-solo nodes
|
133
|
-
test_files:
|
144
|
+
test_files:
|
145
|
+
- spec/fixtures/single_node.yml
|
146
|
+
- spec/fixtures/some_nodes.yml
|
147
|
+
- spec/sous-chef/manager_spec.rb
|
148
|
+
- spec/sous-chef/node_spec.rb
|
149
|
+
- spec/sous-chef/parser_spec.rb
|
150
|
+
- spec/spec_helper.rb
|