sous-chef 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -2,4 +2,5 @@
2
2
  .rvmrc
3
3
  .ruby-version
4
4
  *.gem
5
+ tmp
5
6
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sous-chef (0.0.0)
4
+ sous-chef (0.0.3)
5
5
  knife-solo (~> 0.1.0)
6
6
  rake (~> 10.0.3)
7
7
 
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # SousChef
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
- SuperAwesomeNode:
22
- HostName: 12.34.56.789
23
- Port 1234
24
- IdentityFile: ~/.ssh/other_id_rsa
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
- HostName: localhost
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
+
@@ -1,5 +1,4 @@
1
- require 'tempfile'
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 #{agents_ssh_config_path} #{node} -N #{node} nodes/buildAgent.json"
10
+ run "knife solo #{command} -F #{node.ssh_config_path} #{node.hostname} -N #{node.name} #{node.config}"
12
11
  end
13
12
 
14
- def agents
15
- agents_path = File.join(Dir.pwd, "nodes", "nodes.yml")
16
- unless File.exists? agents_path
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 #{node}"
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 #{node}"
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
- namespace :vagrant do
62
- def vagrant_ssh_config_path
63
- @vagrant_ssh_config_paths ||= begin
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
- attr_accessor :agents
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,2 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'sous-chef', 'tasks'))
2
+
@@ -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.3"
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 = %q{http://github.com/substantial/sous-chef}
13
- s.rubyforge_project = "sous-chef"
12
+ s.homepage = %q{http://github.com/substantial/sous-chef}
13
+ s.license = "MIT"
14
14
 
15
- s.license = "MIT"
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,7 @@
1
+ SuperAwesomeNode:
2
+ node_config: some/path/to/node/config
3
+ ssh_config:
4
+ HostName: Some IP
5
+ Port: 1234
6
+ IdentityFile: ~/.ssh/other_id_rsa
7
+
@@ -0,0 +1,12 @@
1
+ SuperAwesomeNode:
2
+ node_config: some/path/to/node/config
3
+ ssh_config:
4
+ HostName: 12.34.56.789
5
+ Port: 1234
6
+ IdentityFile: ~/.ssh/other_id_rsa
7
+
8
+ OtherAwesome:
9
+ node_config: some/path/to/node/config
10
+ ssh_config:
11
+ HostName: localhost
12
+
@@ -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
+
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+
4
+ SPEC_ROOT = File.dirname(__FILE__)
5
+
6
+ RSpec.configure do |config|
7
+ config.mock_with :rspec
8
+ end
9
+
10
+ require File.join(SPEC_ROOT, '/../lib/sous-chef')
11
+
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.3
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-24 00:00:00.000000000 Z
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/sous-chef/tasks/sous-chef.rake
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
@@ -1,2 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '../sous-chef', 'tasks'))
2
-