butcher 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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