butcher 0.1.0 → 1.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 49d85ccf4a1aac378a410c2c4738535add224f0b
4
- data.tar.gz: 81f1860c81f6d7bb796e696546c2e302d7fab35e
3
+ metadata.gz: df03308964023fc67e995645841fd7626c20cdbe
4
+ data.tar.gz: c56762d59d52c4fb9c7fe6dcc19726b03537aa64
5
5
  SHA512:
6
- metadata.gz: 6eb34d9f3b333e761396e3d95657fc87be1d728acd53904ba9af2ef9eb853ffda2c7526e8c1c8297d7cdae62298178316fbc919df9a1576a42bd360c7e4d9b32
7
- data.tar.gz: 0fe9c38286638147123ddde85095c2da004840540a31194982ebc6a1f0438eec80d1b1d5d8080b27a7902e1a24a662a1c9456b777808a6dcba4c106432b307e8
6
+ metadata.gz: 55b204f81f80998fbbad7927faf6033162f03d8caad10a53df6101daeaa9c7e64202c1b49524d1bcd0f310f123592332c69867162596f47e3a35fdb93a37bf55
7
+ data.tar.gz: 91c194896fb1df3da4391628166c383271314f54ce93a92a085d4b6032a643c8f25f27cf298f2d6f7e7d522992b1bf49b498e38a968018e87dcc9efe03e1c6ea
@@ -2,7 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 1.8.7
5
- - 2.0.0-p195
5
+ - 2.0.0-p247
6
6
  - ree
7
7
  script: "bundle exec rspec spec && bundle exec cucumber features"
8
8
  notifications:
data/Gemfile CHANGED
@@ -11,4 +11,5 @@ group :test do
11
11
  gem "guard-rspec"
12
12
  gem "guard-cucumber"
13
13
  gem "mocha"
14
+ gem 'pry-nav'
14
15
  end
data/bin/stab CHANGED
@@ -5,56 +5,17 @@ require 'optparse'
5
5
 
6
6
  EX_USAGE = 64
7
7
  EX_UNMATCHED = 65
8
- EX_AMBIGUOUS = 66
9
8
  EX_KNIFE = 67
10
9
 
11
- options = {}
12
- parser = OptionParser.new do |opts|
13
- opts.banner = "Usage: stab [options] node_name"
14
-
15
- opts.on('-c', '--cache-dir DIR', 'Location to save cache files (default: ~/.butcher/cache)') do |dir|
16
- ENV["CACHE_DIR"] = dir
17
- end
18
-
19
- opts.on('-f', '--force', 'Check for new nodes even if a cache file exists') do
20
- options[:force] = true
21
- end
22
-
23
- opts.on('-h', '--help', 'Display this screen') do
24
- puts opts
25
- exit
26
- end
27
-
28
- opts.on('-l', '--login LOGIN', 'Use LOGIN for ssh session') do |login|
29
- options[:login] = login
30
- end
31
-
32
- opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
33
- options[:verbose] = v
34
- end
35
- end
36
-
37
- begin parser.parse!
38
- rescue OptionParser::InvalidOption => e
39
- puts e
40
- puts parser
41
- exit EX_USAGE
42
- end
43
-
44
- if ARGV == []
45
- puts parser
46
- exit EX_USAGE
47
- end
48
-
10
+ runner = Butcher::Stab::CLI.new(ARGV)
49
11
  begin
50
- Butcher::Stab::CLI.new.run(ARGV, options)
12
+ runner.execute!
13
+ rescue Butcher::Stab::UsageError => e
14
+ STDERR.puts e.message
15
+ exit EX_USAGE
51
16
  rescue Butcher::UnmatchedNode
52
- STDERR.puts %Q{Unable to find node "#{ARGV.first}"}
17
+ STDERR.puts %Q{Unable to find node "#{runner.node_name}"}
53
18
  exit EX_UNMATCHED
54
- rescue Butcher::AmbiguousNode => e
55
- STDERR.puts %Q{Multiple nodes match "#{ARGV.first}"}
56
- STDERR.puts e.message
57
- exit EX_AMBIGUOUS
58
19
  rescue Butcher::NoKnifeRB
59
20
  STDERR.puts "Unable to find knife.rb in ./.chef"
60
21
  STDERR.puts "Are you stabbing from a valid working chef directory?"
@@ -18,5 +18,5 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = %W(lib)
20
20
 
21
- s.add_runtime_dependency "chef", "~> 10.14"
21
+ s.add_runtime_dependency "chef", ">= 10.14"
22
22
  end
@@ -16,7 +16,7 @@ Feature: Stab
16
16
  Then the exit status should be 0
17
17
  And the output should contain:
18
18
  """
19
- Usage: stab [options] node_name
19
+ Usage: stab [options] <node name> [ssh options]
20
20
  """
21
21
 
22
22
  Scenario: Usage information when no node name is given
@@ -24,49 +24,35 @@ Feature: Stab
24
24
  Then the exit status should be 64
25
25
  And the output should contain:
26
26
  """
27
- Usage: stab [options] node_name
27
+ Usage: stab [options] <node name> [ssh options]
28
28
  """
29
29
 
30
- Scenario: Invalid option
31
- When I run `stab --invalid-option`
32
- Then the exit status should be 64
33
- And the output should contain:
34
- """
35
- invalid option: --invalid-option
36
- Usage: stab [options] node_name
37
- """
38
-
39
- Scenario: Set cache directory
40
- Given a directory named "tmp/test_dir" should not exist
41
- When I run `stab app.node -c tmp/test_dir`
42
- Then a directory named "tmp/test_dir" should exist
43
-
44
30
  Scenario: Tell user what IP address ssh uses
45
31
  Given I have the following chef nodes:
46
32
  | 1 minute ago | app.node | app.domain | 1.1.1.1 | os |
47
- When I run `stab app.node -c tmp/test -v`
33
+ When I run `stab app.node -v`
48
34
  Then the output should contain "Connecting to app.node at 1.1.1.1"
49
35
  Then the output should contain "ssh yay!"
50
36
 
51
37
  Scenario: Don't download node list if already cached
52
38
  Given I have the following chef nodes:
53
39
  | 1 minute ago | app.node | app.domain | 1.1.1.1 | os |
54
- Then a file named "tmp/test/my_organization.cache" should exist
55
- When I run `stab app.node -c tmp/test -v`
40
+ Then a file named "tmp/test/.butcher/cache/my_organization.cache" should exist
41
+ When I run `stab app.node -v`
56
42
  Then the output should not contain "Creating cache file of nodes"
57
43
 
58
44
  Scenario: Force download of cache file
59
45
  Given I have the following chef nodes:
60
46
  | 1 minute ago | app.node | app.domain | 1.1.1.1 | os |
61
- When I run `stab app.node -c tmp/test -f -v`
47
+ When I run `stab app.node -f -v`
62
48
  Then the output should contain "Creating cache file of nodes"
63
- And the double `knife status` should have been run
64
49
  And the exit status should be 0
50
+ And the double `knife status` should have been run
65
51
 
66
52
  Scenario: User sees error message if no node matches given name
67
53
  Given I have the following chef nodes:
68
54
  | 1 minute ago | app.node | app.domain | 1.1.1.1 | os |
69
- When I run `stab some.node -c tmp/test`
55
+ When I run `stab some.node`
70
56
  Then the stderr should contain:
71
57
  """
72
58
  Unable to find node "some.node"
@@ -77,14 +63,16 @@ Feature: Stab
77
63
  Given I have the following chef nodes:
78
64
  | 1 minute ago | other.node | other.domain | 1.1.1.2 | os |
79
65
  | 1 minute ago | app.node | app.domain | 1.1.1.1 | os |
80
- When I run `stab node -c tmp/test`
81
- Then the stderr should contain:
66
+ And I double `ssh 1.1.1.2`
67
+ When I run `stab node` interactively
68
+ And I type "2"
69
+ Then the stdout should contain:
82
70
  """
83
- Multiple nodes match "node"
84
- ["app.node", "app.domain"] => 1.1.1.1
85
- ["other.node", "other.domain"] => 1.1.1.2
71
+ 1 "app.node" => 1.1.1.1
72
+ 2 "other.node" => 1.1.1.2
86
73
  """
87
- And the exit status should be 66
74
+ Then the exit status should be 0
75
+ And the double `ssh 1.1.1.2` should have been run
88
76
 
89
77
  Scenario: User can connect to server with given user name
90
78
  Given I have the following chef nodes:
@@ -93,15 +81,22 @@ Feature: Stab
93
81
  """
94
82
  user: I'm a computer!
95
83
  """
96
- When I run `stab app.node -c tmp/test -l user`
84
+ When I run `stab app.node -l user`
97
85
  Then the stdout should contain:
98
86
  """
99
87
  user: I'm a computer!
100
88
  """
101
89
 
90
+ Scenario: Arbitrary command line options are passed to ssh
91
+ Given I have the following chef nodes:
92
+ | 1 minute ago | app.node | app.domain | 1.1.1.1 | os |
93
+ Given I double `ssh 1.1.1.1 -l user --arrrh`
94
+ When I run `stab app.node -l user --arrrh`
95
+ Then the double `ssh 1.1.1.1 -l user --arrrh` should have been run
96
+
102
97
  Scenario: User sees error message if knife.rb cannot be found
103
98
  Given I don't have a knife configuration file
104
- When I run `stab app.node -c tmp/test`
99
+ When I run `stab app.node`
105
100
  Then the stderr should contain:
106
101
  """
107
102
  Unable to find knife.rb in ./.chef
@@ -111,7 +106,7 @@ Feature: Stab
111
106
 
112
107
  Scenario: User sees error message if knife.rb is invalid
113
108
  Given I have an invalid knife configuration file
114
- When I run `stab app.node -c tmp/test`
109
+ When I run `stab app.node`
115
110
  Then the stderr should contain:
116
111
  """
117
112
  Unable to read organization from knife.rb
@@ -0,0 +1,3 @@
1
+ Given /I pry/ do
2
+ binding.pry
3
+ end
@@ -5,5 +5,6 @@ require 'aruba/cucumber'
5
5
  require 'fileutils'
6
6
  require 'rspec/expectations'
7
7
  require 'butcher'
8
+ require 'pry'
8
9
 
9
10
  Dir["#{File.dirname(__FILE__)}/../../spec/support/**/*.rb"].each { |f| require f unless /_spec\.rb$/.match(f) }
@@ -1,4 +1,4 @@
1
- require "mocha"
1
+ require "mocha/api"
2
2
 
3
3
  World(Mocha::API)
4
4
 
@@ -12,4 +12,4 @@ After do
12
12
  ensure
13
13
  mocha_teardown
14
14
  end
15
- end
15
+ end
@@ -3,7 +3,6 @@ require "fileutils"
3
3
 
4
4
  module Butcher
5
5
  class UnmatchedNode < Exception;end
6
- class AmbiguousNode < Exception;end
7
6
  class NoKnifeRB < Exception;end
8
7
  class NoKnifeOrganization < Exception;end
9
8
  end
@@ -4,32 +4,29 @@ require 'chef/config'
4
4
  class Butcher::Cache
5
5
  include Singleton
6
6
 
7
- CACHE_DIR = "#{ENV["HOME"]}/.butcher/cache"
8
7
  KNIFE_FILE = ".chef/knife.rb"
9
8
 
10
- def initialize
11
- FileUtils.mkdir_p(cache_dir)
12
- end
13
-
14
9
  def nodes(options = {})
15
- hash = {}
10
+ n = []
16
11
  cache_file(options) do |file|
17
12
  while file.gets
18
13
  node = $_.split(", ")
19
- hash[node[3]] = [node[1],node[2]]
14
+ n << {:ip => node[3], :name => node[1], :fqdn => node[2]}
20
15
  end
21
16
  end
22
- hash
17
+ n.sort{ |a,b| a[:name] <=> b[:name] }
23
18
  end
24
19
 
25
20
  def cache_dir # :nodoc:
26
- ENV["CACHE_DIR"] || CACHE_DIR
21
+ "#{ENV["HOME"]}/.butcher/cache"
27
22
  end
28
23
 
29
- def self.format_nodes_for_stderr(nodes)
30
- nodes.map do |key, value|
31
- %Q{#{value.inspect} => #{key}}
32
- end.sort.join("\n")
24
+ def self.formatted_nodes_for_output(nodes)
25
+ i = 0
26
+ nodes.map do |node|
27
+ i += 1
28
+ sprintf("%- 5d %p => %s", i, node[:name], node[:ip])
29
+ end.join("\n")
33
30
  end
34
31
 
35
32
  def nodes_file
@@ -54,6 +51,7 @@ class Butcher::Cache
54
51
 
55
52
  def create_node_cachefile
56
53
  with_safe_paths do
54
+ FileUtils.mkdir_p(cache_dir)
57
55
  File.open(nodes_file, "w") do |file|
58
56
  file.puts %x[knife status]
59
57
  end
@@ -1,2 +1,4 @@
1
1
  module Butcher::Stab
2
- end
2
+ class UsageError < StandardError
3
+ end
4
+ end
@@ -1,38 +1,71 @@
1
1
  class Butcher::Stab::CLI
2
- attr_accessor :node_matcher
3
- attr_accessor :options
2
+ attr_accessor :argv, :options, :stdin, :stdout, :stderr, :kernel
4
3
 
5
- def run(arguments, options = {})
6
- self.options = options
7
- self.node_matcher = Array(arguments).first
8
- return "" if node_matcher.nil?
4
+ def initialize(argv, stdin=STDIN, stdout=STDOUT, stderr=STDERR, kernel=Kernel)
5
+ self.argv = argv
6
+ self.stdin = stdin
7
+ self.stdout = stdout
8
+ self.stderr = stderr
9
+ self.kernel = kernel
10
+ self.options = {}
11
+ optparse
12
+ end
13
+
14
+ def execute!
15
+ return stdout.puts(usage) if options[:help]
16
+ raise Butcher::Stab::UsageError.new(usage) if node_name.nil?
9
17
 
10
18
  ssh_to(matching_node)
11
19
  end
12
20
 
13
- private
21
+ def node_name
22
+ @node_name ||= argv.shift
23
+ end
14
24
 
15
- def ssh_to(ip)
16
- STDOUT.sync = true # exec takes over stdout in tests, so sync output
17
- puts "Connecting to #{node_matcher} at #{ip}" if options[:verbose]
18
- exec("ssh #{ip}#{ssh_options}")
25
+ def usage
26
+ <<-END.gsub(/^ {6}/, '')
27
+ Usage: stab [options] <node name> [ssh options]
28
+ -f --force # download new node list even if a cache file exists
29
+ -v --verbose # be expressive
30
+ -h --help # print this info
31
+ END
19
32
  end
20
33
 
34
+ private
35
+
21
36
  def matching_node
22
- raise(Butcher::UnmatchedNode) if nodes.size == 0
23
- raise(Butcher::AmbiguousNode, Butcher::Cache.format_nodes_for_stderr(nodes)) if nodes.size > 1
24
- nodes.keys.first
25
- end
37
+ @node ||= begin
38
+ nodes = Butcher::Cache.instance.nodes(options).reject do |node|
39
+ ! node[:name].include? self.node_name
40
+ end
41
+
42
+ raise(Butcher::UnmatchedNode) if nodes.size == 0
26
43
 
27
- def ssh_options
28
- if options[:login]
29
- " -l #{options[:login]}"
44
+ if nodes.size > 1
45
+ stdout.puts Butcher::Cache.formatted_nodes_for_output(nodes)
46
+ stdout.write "\n which server? > "
47
+ begin
48
+ choice = stdin.gets.chomp.to_i - 1
49
+ rescue Interrupt
50
+ exit
51
+ end
52
+ else
53
+ choice = 0
54
+ end
55
+
56
+ nodes[choice]
30
57
  end
31
58
  end
32
59
 
33
- def nodes
34
- @nodes ||= Butcher::Cache.instance.nodes(options).reject do |k, v|
35
- ! String(v).include? self.node_matcher
36
- end
60
+ def optparse
61
+ options[:force] = !(argv.delete("--force") || argv.delete("-f")).nil?
62
+ options[:verbose] = !(argv.delete("--verbose") || argv.delete("-v")).nil?
63
+ options[:help] = !(argv.delete("--help") || argv.delete("-h")).nil?
64
+ end
65
+
66
+ def ssh_to(node)
67
+ STDOUT.sync = true # exec takes over stdout in tests, so sync output
68
+ puts "Connecting to #{node[:name]} at #{node[:ip]}" if options[:verbose]
69
+ exec("ssh #{[node[:ip], argv].flatten.join(' ')}")
37
70
  end
38
71
  end
@@ -1,3 +1,3 @@
1
1
  module Butcher
2
- VERSION = "0.1.0"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,26 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Butcher::Cache, "initialization" do
4
- ## singletons do not reset after initialization, so we run tests against clones
5
-
6
- class CacheSingletonForEnv < Butcher::Cache; end
7
- it "should accept cache_dir from env" do
8
- ENV["CACHE_DIR"] = "tmp/cache_from_options"
9
- test(?d, "tmp/cache_from_options").should be_false
10
- CacheSingletonForEnv.instance
11
- ENV["CACHE_DIR"] = nil
12
- test(?d, "tmp/cache_from_options").should be_true
13
- end
14
-
15
- class CacheSingleton < Butcher::Cache; end
16
- it "should create cache directory" do
17
- CacheSingleton.any_instance.stubs(:cache_dir).returns("tmp/cache_stub")
18
- test(?d, "tmp/cache_stub").should be_false
19
- CacheSingleton.instance
20
- test(?d, "tmp/cache_stub").should be_true
21
- end
22
- end
23
-
24
3
  describe Butcher::Cache, "#nodes_file" do
25
4
  context "cannot find knife.rb" do
26
5
  it "should raise an error" do
@@ -89,10 +68,21 @@ describe Butcher::Cache, "#nodes" do
89
68
  end
90
69
 
91
70
  it "maps file to hash" do
92
- Butcher::Cache.instance.nodes.should == {
93
- "192.168.1.1" => %W(app.node app.domain.com),
94
- "192.168.1.2" => %W(other.node other.domain.com)
95
- }
71
+ Butcher::Cache.instance.nodes.should == [
72
+ {:ip => "192.168.1.1", :name => "app.node", :fqdn => "app.domain.com"},
73
+ {:ip => "192.168.1.2", :name => "other.node", :fqdn => "other.domain.com"}
74
+ ]
96
75
  end
97
76
  end
98
77
  end
78
+
79
+ describe Butcher::Cache, '.formatted_nodes_for_output' do
80
+ it 'returns node info in a numbered list' do
81
+ nodes = [
82
+ {:ip => "123.4.5.6", :name => "node1", :fqdn => "node1.prod"},
83
+ {:ip => "901.4.5.6", :name => "node2", :fqdn => "node2.prod"}
84
+ ]
85
+ expect(Butcher::Cache.formatted_nodes_for_output(nodes)).
86
+ to eql(%Q{ 1 "node1" => 123.4.5.6\n 2 "node2" => 901.4.5.6})
87
+ end
88
+ end
@@ -1,60 +1,155 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Butcher::Stab::CLI do
3
+ describe Butcher::Stab::CLI, 'option parsing' do
4
+ let(:cli) { Butcher::Stab::CLI.new(args) }
5
+ let(:options) { cli.options }
4
6
 
5
- context "arguments are nil" do
6
- it "should return empty string" do
7
- Butcher::Stab::CLI.new.run(nil).should == ""
7
+ describe 'defaults' do
8
+ let(:args) { [''] }
9
+ it "sets :force to false" do
10
+ expect(options[:force]).to be_false
11
+ end
12
+
13
+ it "sets :verbose to false" do
14
+ expect(options[:verbose]).to be_false
15
+ end
16
+
17
+ it "sets :help to false" do
18
+ expect(options[:help]).to be_false
8
19
  end
9
20
  end
10
21
 
11
- context "node cache file exists" do
12
- mock_cache(:nodes) do
13
- {"10.1.1.1" => %W(app.node app.node.com), "10.1.1.2" => %W(other.node other.node.com)}
22
+ describe '--force' do
23
+ context 'long' do
24
+ let(:args) { ["--force"] }
25
+ it "sets option :force to true" do
26
+ expect(options[:force]).to be_true
27
+ end
28
+ end
29
+
30
+ context "short" do
31
+ let(:args) { ["-f"] }
32
+ it "sets option :force to true" do
33
+ expect(options[:force]).to be_true
34
+ end
14
35
  end
36
+ end
37
+
38
+ describe '--verbose' do
39
+ context 'long' do
40
+ let(:args) { ["--verbose"] }
41
+ it "sets option :verbose to true" do
42
+ expect(options[:verbose]).to be_true
43
+ end
44
+ end
45
+
46
+ context 'short' do
47
+ let(:args) { ["-v"] }
48
+ it "sets option :verbose to true" do
49
+ expect(options[:verbose]).to be_true
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '--help' do
55
+ context 'long' do
56
+ let(:args) { ['--help']}
57
+ it "sets :help to true" do
58
+ expect(options[:help]).to be_true
59
+ end
60
+ end
61
+
62
+ context 'short' do
63
+ let(:args) { ['-h']}
64
+ it "sets :help to true" do
65
+ expect(options[:help]).to be_true
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ describe Butcher::Stab::CLI, '#usage' do
72
+ it 'returns usage info' do
73
+ expect(Butcher::Stab::CLI.new([]).usage).to eql(<<-END.gsub(/^ {6}/, ''))
74
+ Usage: stab [options] <node name> [ssh options]
75
+ -f --force # download new node list even if a cache file exists
76
+ -v --verbose # be expressive
77
+ -h --help # print this info
78
+ END
79
+ end
80
+ end
81
+
82
+ describe Butcher::Stab::CLI, '#execute!' do
83
+ context 'when :help is true' do
84
+ let(:stdout) { mock() }
85
+ let(:runner) { Butcher::Stab::CLI.new([], mock, stdout) }
86
+
87
+ it 'writes usage and exits' do
88
+ runner.options[:help] = true
89
+ stdout.expects(:puts).with(runner.usage)
90
+ runner.execute!
91
+ end
92
+ end
93
+
94
+ context "when arguments are empty" do
95
+ it "raises a Usage error" do
96
+ runner = Butcher::Stab::CLI.new([])
97
+ expect { runner.execute! }.to raise_error(Butcher::Stab::UsageError, runner.usage)
98
+ end
99
+ end
100
+
101
+ context "node cache file exists" do
102
+ let(:nodes) {
103
+ [
104
+ {:ip => "10.1.1.1", :name => 'app.node', :fqdn => 'app.node.com'},
105
+ {:ip => "10.1.1.2", :name => 'other.node', :fqdn => 'other.node.com'}
106
+ ]
107
+ }
108
+ before { Butcher::Cache.any_instance.stubs(:nodes).returns(nodes) }
15
109
 
16
110
  context "stabbing an existing node" do
17
111
  it "should open an SSH session to named node" do
18
112
  Butcher::Stab::CLI.any_instance.expects(:exec).with("ssh 10.1.1.1").returns(true).once
19
- Butcher::Stab::CLI.new.run("app")
113
+ Butcher::Stab::CLI.new(['app']).execute!
20
114
  end
21
115
 
22
116
  it "should ssh to IP based on matched node" do
23
117
  Butcher::Stab::CLI.any_instance.expects(:exec).with("ssh 10.1.1.1").never
24
118
  Butcher::Stab::CLI.any_instance.expects(:exec).with("ssh 10.1.1.2").returns(true).once
25
- Butcher::Stab::CLI.new.run("other")
119
+ Butcher::Stab::CLI.new(["other"]).execute!
26
120
  end
27
121
  end
28
122
 
29
123
  context "stabbing a non-existing node" do
30
124
  it "should raise an UnmatchedNode error" do
31
125
  Butcher::Stab::CLI.any_instance.expects(:exec).never
32
- lambda {
33
- Butcher::Stab::CLI.new.run("nil.node")
34
- }.should raise_error(Butcher::UnmatchedNode)
126
+ expect {
127
+ Butcher::Stab::CLI.new(["nil.node"]).execute!
128
+ }.to raise_error(Butcher::UnmatchedNode)
35
129
  end
36
130
  end
37
131
 
38
132
  context "ambiguous stabbing" do
39
- it "should raise an AmbiguousNode error" do
40
- Butcher::Stab::CLI.any_instance.expects(:exec).never
41
- lambda {
42
- Butcher::Stab::CLI.new.run("node")
43
- }.should raise_error(Butcher::AmbiguousNode)
133
+ it "asks the user which server to connect to" do
134
+ stdin = mock(:gets => "2")
135
+ stdout = mock(:puts => Butcher::Cache.formatted_nodes_for_output(nodes), :write => "\n which server? > ")
136
+ Butcher::Stab::CLI.any_instance.expects(:exec).with("ssh 10.1.1.2").returns(true).once
137
+
138
+ Butcher::Stab::CLI.new(["node"], stdin, stdout).execute!
44
139
  end
45
140
  end
46
141
  end
47
142
 
48
- context "options" do
143
+ context "ssh options" do
49
144
  mock_cache(:nodes) do
50
- {"10.1.1.1" => %W(app.node app.node.com)}
145
+ [{:ip => "10.1.1.1", :name => 'app.node', :fqdn => 'app.node.com'}]
51
146
  end
52
147
 
53
148
  describe ":login" do
54
149
  it "should include login in ssh params" do
55
150
  Butcher::Stab::CLI.any_instance.expects(:exec).with("ssh 10.1.1.1 -l username").returns(true).once
56
- Butcher::Stab::CLI.new.run("app", {:login => "username"})
151
+ Butcher::Stab::CLI.new(["app", "-l", "username"]).execute!
57
152
  end
58
153
  end
59
154
  end
60
- end
155
+ end
@@ -4,6 +4,7 @@
4
4
  # loaded once.
5
5
  #
6
6
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ require 'pry'
7
8
  require "butcher"
8
9
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f unless /_spec\.rb$/.match(f) }
9
10
 
@@ -20,7 +20,8 @@
20
20
  # World(Butcher::TestCache::TestHelpers)
21
21
  #
22
22
  module Butcher::TestCache
23
- PWD = ENV["PWD"]
23
+ PWD = ENV['PWD']
24
+ HOME = ENV['HOME']
24
25
 
25
26
  def self.setup_rspec(config)
26
27
  config.before(:each) do
@@ -42,26 +43,23 @@ module Butcher::TestCache
42
43
 
43
44
  def self.cleanup # :nodoc:
44
45
  FileUtils.rm_rf("tmp")
45
- ENV.delete("CACHE_DIR")
46
- ENV["PWD"] = PWD
46
+ ENV['PWD'] = PWD
47
+ ENV['HOME'] = HOME
47
48
  end
48
49
 
49
50
  def self.cache_dir # :nodoc:
50
- File.expand_path("tmp/test")
51
+ File.expand_path("tmp/test/.butcher/cache")
51
52
  end
52
53
 
53
54
  private
54
55
 
55
56
  def self.setup
56
- ENV["PWD"] = "#{PWD}/tmp"
57
- stub_cache
57
+ pwd = "#{PWD}/tmp/test"
58
+ ENV["PWD"] = pwd
59
+ ENV['HOME'] = pwd
58
60
  FileUtils.mkdir_p("tmp/test")
59
61
  end
60
62
 
61
- def self.stub_cache
62
- ENV["CACHE_DIR"] = cache_dir
63
- end
64
-
65
63
  public
66
64
 
67
65
  # == RSpecExampleHelpers
@@ -106,6 +104,7 @@ module Butcher::TestCache
106
104
 
107
105
  # Creates a file that Butcher::Cache can parse
108
106
  def create_cache_file(filename)
107
+ FileUtils.mkdir_p(Butcher::TestCache.cache_dir)
109
108
  File.open("#{Butcher::TestCache.cache_dir}/#{filename}", "w") do |file|
110
109
  yield file
111
110
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: butcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Saxby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-19 00:00:00.000000000 Z
11
+ date: 2013-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '10.14'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '10.14'
27
27
  description: Chef is a tool for managing server automation. A good butcher makes for
@@ -34,7 +34,6 @@ extensions: []
34
34
  extra_rdoc_files: []
35
35
  files:
36
36
  - .gitignore
37
- - .rbenv-version
38
37
  - .rspec
39
38
  - .travis.yml
40
39
  - Gemfile
@@ -46,6 +45,7 @@ files:
46
45
  - butcher.gemspec
47
46
  - features/stab.feature
48
47
  - features/step_definitions/chef_steps.rb
48
+ - features/step_definitions/pry_steps.rb
49
49
  - features/support/aruba.rb
50
50
  - features/support/env.rb
51
51
  - features/support/mocha.rb
@@ -78,13 +78,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
78
  version: '0'
79
79
  requirements: []
80
80
  rubyforge_project: butcher
81
- rubygems_version: 2.0.2
81
+ rubygems_version: 2.0.3
82
82
  signing_key:
83
83
  specification_version: 4
84
84
  summary: All the things to make a chef
85
85
  test_files:
86
86
  - features/stab.feature
87
87
  - features/step_definitions/chef_steps.rb
88
+ - features/step_definitions/pry_steps.rb
88
89
  - features/support/aruba.rb
89
90
  - features/support/env.rb
90
91
  - features/support/mocha.rb
@@ -93,3 +94,4 @@ test_files:
93
94
  - spec/lib/stab/cli_spec.rb
94
95
  - spec/spec_helper.rb
95
96
  - spec/support/test_cache.rb
97
+ has_rdoc:
@@ -1 +0,0 @@
1
- 2.0.0-p195