rhc 1.6.8 → 1.7.8

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.
Files changed (85) hide show
  1. data/autocomplete/rhc_bash +1167 -0
  2. data/features/README.md +1 -1
  3. data/features/domain.feature +1 -1
  4. data/features/lib/rhc_helper/persistable.rb +4 -1
  5. data/features/multiple_cartridge.feature +4 -3
  6. data/features/sshkey.feature +3 -3
  7. data/features/support/assumptions.rb +3 -3
  8. data/features/support/env.rb +10 -0
  9. data/features/support/platform_support.rb +2 -2
  10. data/lib/rhc.rb +6 -0
  11. data/lib/rhc/auth/token.rb +4 -0
  12. data/lib/rhc/autocomplete.rb +50 -52
  13. data/lib/rhc/autocomplete_templates/{rhc.erb → bash.erb} +8 -2
  14. data/lib/rhc/cartridge_helpers.rb +1 -1
  15. data/lib/rhc/cli.rb +1 -7
  16. data/lib/rhc/command_runner.rb +45 -16
  17. data/lib/rhc/commands.rb +75 -55
  18. data/lib/rhc/commands/account.rb +7 -51
  19. data/lib/rhc/commands/alias.rb +26 -17
  20. data/lib/rhc/commands/app.rb +75 -39
  21. data/lib/rhc/commands/authorization.rb +4 -2
  22. data/lib/rhc/commands/base.rb +31 -29
  23. data/lib/rhc/commands/cartridge.rb +66 -44
  24. data/lib/rhc/commands/domain.rb +20 -8
  25. data/lib/rhc/commands/git_clone.rb +3 -3
  26. data/lib/rhc/commands/logout.rb +51 -0
  27. data/lib/rhc/commands/port_forward.rb +15 -11
  28. data/lib/rhc/commands/setup.rb +25 -0
  29. data/lib/rhc/commands/snapshot.rb +20 -10
  30. data/lib/rhc/commands/sshkey.rb +21 -7
  31. data/lib/rhc/commands/tail.rb +2 -2
  32. data/lib/rhc/commands/threaddump.rb +2 -2
  33. data/lib/rhc/context_helper.rb +0 -4
  34. data/lib/rhc/core_ext.rb +96 -76
  35. data/lib/rhc/exceptions.rb +6 -0
  36. data/lib/rhc/help_formatter.rb +19 -2
  37. data/lib/rhc/helpers.rb +32 -194
  38. data/lib/rhc/highline_extensions.rb +412 -0
  39. data/lib/rhc/output_helpers.rb +31 -67
  40. data/lib/rhc/rest.rb +4 -2
  41. data/lib/rhc/rest/alias.rb +0 -2
  42. data/lib/rhc/rest/application.rb +9 -4
  43. data/lib/rhc/rest/authorization.rb +0 -2
  44. data/lib/rhc/rest/base.rb +1 -1
  45. data/lib/rhc/rest/client.rb +11 -9
  46. data/lib/rhc/rest/domain.rb +5 -1
  47. data/lib/rhc/rest/gear_group.rb +0 -2
  48. data/lib/rhc/rest/key.rb +0 -2
  49. data/lib/rhc/rest/mock.rb +32 -10
  50. data/lib/rhc/ssh_helpers.rb +2 -2
  51. data/lib/rhc/usage_templates/command_help.erb +20 -13
  52. data/lib/rhc/usage_templates/command_syntax_help.erb +1 -3
  53. data/lib/rhc/usage_templates/help.erb +15 -16
  54. data/lib/rhc/usage_templates/options_help.erb +7 -9
  55. data/lib/rhc/wizard.rb +193 -159
  56. data/spec/rest_spec_helper.rb +2 -2
  57. data/spec/rhc/cli_spec.rb +36 -5
  58. data/spec/rhc/command_spec.rb +94 -42
  59. data/spec/rhc/commands/account_spec.rb +1 -75
  60. data/spec/rhc/commands/alias_spec.rb +28 -28
  61. data/spec/rhc/commands/app_spec.rb +141 -33
  62. data/spec/rhc/commands/apps_spec.rb +4 -4
  63. data/spec/rhc/commands/authorization_spec.rb +8 -8
  64. data/spec/rhc/commands/cartridge_spec.rb +18 -9
  65. data/spec/rhc/commands/domain_spec.rb +16 -16
  66. data/spec/rhc/commands/git_clone_spec.rb +3 -3
  67. data/spec/rhc/commands/logout_spec.rb +86 -0
  68. data/spec/rhc/commands/port_forward_spec.rb +9 -9
  69. data/spec/rhc/commands/server_spec.rb +5 -5
  70. data/spec/rhc/commands/setup_spec.rb +19 -5
  71. data/spec/rhc/commands/snapshot_spec.rb +12 -12
  72. data/spec/rhc/commands/sshkey_spec.rb +11 -11
  73. data/spec/rhc/commands/tail_spec.rb +5 -5
  74. data/spec/rhc/commands/threaddump_spec.rb +3 -3
  75. data/spec/rhc/config_spec.rb +6 -6
  76. data/spec/rhc/helpers_spec.rb +72 -219
  77. data/spec/rhc/highline_extensions_spec.rb +269 -0
  78. data/spec/rhc/rest_application_spec.rb +28 -1
  79. data/spec/rhc/rest_client_spec.rb +20 -21
  80. data/spec/rhc/rest_spec.rb +10 -0
  81. data/spec/rhc/wizard_spec.rb +72 -32
  82. data/spec/spec_helper.rb +86 -56
  83. data/spec/wizard_spec_helper.rb +7 -4
  84. metadata +165 -160
  85. data/spec/spec.opts +0 -1
@@ -43,6 +43,7 @@ describe RHC::Rest::Domain do
43
43
 
44
44
  it{ domain.add_application('foo', :cartridges => ['bar']).should be_true }
45
45
  it{ expect{ domain.add_application('foo', :cartridges => ['bar', 'other']) }.to raise_error(RHC::Rest::MultipleCartridgeCreationNotSupported) }
46
+ it{ expect{ domain.add_application('foo', :initial_git_url => 'a_url') }.to raise_error(RHC::Rest::InitialGitUrlNotSupported) }
46
47
  it{ domain.add_application('foo', :cartridges => 'bar').should be_true }
47
48
  it{ domain.add_application('foo', :cartridge => 'bar').should be_true }
48
49
  it{ domain.add_application('foo', :cartridge => ['bar']).should be_true }
@@ -66,6 +67,15 @@ describe RHC::Rest::Domain do
66
67
  it{ domain.add_application('foo', :cartridges => cartridges).should be_true }
67
68
  it{ domain.add_application('foo', :cartridge => cartridges).should be_true }
68
69
  end
70
+
71
+ context "with a url" do
72
+ before do
73
+ stub_api_request(:post, 'broker/rest/domains/bar/applications', false).
74
+ with(:body => {:name => 'foo', :initial_git_url => 'a_url', :cartridges => []}.to_json).
75
+ to_return(:status => 201, :body => {:type => 'application', :data => {:id => '1'}}.to_json)
76
+ end
77
+ it{ domain.add_application('foo', :initial_git_url => 'a_url').should be_true }
78
+ end
69
79
  end
70
80
  end
71
81
 
@@ -53,7 +53,7 @@ describe RHC::Wizard do
53
53
  mock_config
54
54
  FileUtils.mkdir_p(RHC::Config.ssh_dir)
55
55
  File.open(RHC::Config.ssh_priv_key_file_path, 'w'){}
56
- File.chmod(0666, RHC::Config.ssh_priv_key_file_path)
56
+ File.expect_mode(RHC::Config.ssh_priv_key_file_path, 0666)
57
57
  expect{ subject.send(:test_private_key_mode) }.to raise_error(StandardError)
58
58
  end
59
59
  end
@@ -97,13 +97,14 @@ describe RHC::Wizard do
97
97
  let(:password){ 'test pass' }
98
98
  let(:rest_client){ stub }
99
99
  let(:auth){ subject.send(:auth) }
100
+ let(:user_obj){ stub(:login => user) }
100
101
 
101
102
  subject{ described_class.new(config, options) }
102
103
 
103
104
  def expect_client_test(with_sessions=false)
104
105
  subject.should_receive(:new_client_for_options).ordered.and_return(rest_client)
105
106
  rest_client.should_receive(:api).ordered
106
- rest_client.should_receive(:user).ordered.and_return(true)
107
+ rest_client.should_receive(:user).ordered.and_return(user_obj)
107
108
  rest_client.should_receive(:supports_sessions?).ordered.and_return(with_sessions)
108
109
  end
109
110
  def expect_raise_from_api(error)
@@ -114,6 +115,7 @@ describe RHC::Wizard do
114
115
  it "should prompt for user and password" do
115
116
  expect_client_test
116
117
  subject.send(:login_stage).should be_true
118
+ subject.send(:options).rhlogin.should == user
117
119
  end
118
120
 
119
121
  context "with token" do
@@ -181,6 +183,7 @@ describe RHC::Wizard do
181
183
  before{ RHC::Auth::TokenStore.should_receive(:new).any_number_of_times.and_return(store) }
182
184
 
183
185
  it "should not generate a token if the user does not request it" do
186
+ store.should_receive(:get).and_return(nil)
184
187
  subject.should_receive(:info).with(/OpenShift can create and store a token on disk/).ordered
185
188
  subject.should_receive(:agree).with(/Generate a token now?/).ordered.and_return(false)
186
189
 
@@ -189,6 +192,7 @@ describe RHC::Wizard do
189
192
  end
190
193
 
191
194
  it "should generate a token if the user requests it" do
195
+ store.should_receive(:get).and_return(nil)
192
196
  subject.should_receive(:info).with(/OpenShift can create and store a token on disk/).ordered
193
197
  subject.should_receive(:agree).with(/Generate a token now?/).ordered.and_return(true)
194
198
  subject.should_receive(:say).with(/Generating an authorization token for this client /).ordered
@@ -278,7 +282,7 @@ describe RHC::Wizard do
278
282
 
279
283
  context "when the user enters a domain and uploads a key" do
280
284
  before do
281
- stub_create_default_key
285
+ stub_add_key
282
286
  stub_api_request(:post, 'broker/rest/domains', user_auth).
283
287
  with(:body => /(thisnamespaceistoobig|invalidnamespace)/).
284
288
  to_return({
@@ -340,6 +344,33 @@ describe RHC::Wizard do
340
344
  end
341
345
  end
342
346
 
347
+ context "when a multiple keys exist but is not the same" do
348
+ before{ setup_mock_ssh(true) }
349
+ before do
350
+ stub_one_key('a_key')
351
+ stub_add_key_error('invalid```--', 'Invalid key name')
352
+ stub_add_key('another_key')
353
+ end
354
+ it "should give the user a name the key" do
355
+ should_greet_user
356
+ should_challenge_for(username, password)
357
+ should_write_config
358
+ should_not_create_an_ssh_keypair
359
+
360
+ input_line 'yes'
361
+ input_line 'invalid```--'
362
+ input_line 'another_key'
363
+ next_stage
364
+
365
+ last_output do |s|
366
+ s.should match(/a_key \(type: ssh-rsa\)/)
367
+ s.should match("Fingerprint: #{rsa_key_fingerprint_public}")
368
+ s.should match(" name |a_key|")
369
+ s.should match("Invalid key name")
370
+ s.should match("Uploading key 'another_key'")
371
+ end
372
+ end
373
+ end
343
374
  context "when the default key already exists on the server" do
344
375
  before{ setup_mock_ssh(true) }
345
376
  before{ stub_mock_ssh_keys }
@@ -362,7 +393,7 @@ describe RHC::Wizard do
362
393
  stub_api(:user => username)
363
394
  stub_user
364
395
  stub_no_keys
365
- stub_create_default_key
396
+ stub_add_key
366
397
  stub_api_request(:post, 'broker/rest/domains', user_auth).
367
398
  with(:body => /(thisnamespaceistoobig|invalidnamespace)/).
368
399
  to_return({
@@ -414,7 +445,7 @@ describe RHC::Wizard do
414
445
 
415
446
  context "with no server keys" do
416
447
  before{ stub_no_keys }
417
- before{ stub_create_default_key }
448
+ before{ stub_add_key }
418
449
 
419
450
  it "should generate and upload keys since the user does not have them" do
420
451
  input_line "yes"
@@ -451,44 +482,45 @@ describe RHC::Wizard do
451
482
  let(:wizard){ RerunWizardDriver.new }
452
483
 
453
484
  it "should cause ssh_key_upload? to catch NoMethodError and call the fallback to get the fingerprint" do
454
- Net::SSH::KeyFactory.stub(:load_public_key) { raise NoMethodError }
455
- @fallback_run = false
456
- wizard.stub(:ssh_keygen_fallback) { @fallback_run = true }
457
- key_data = wizard.get_mock_key_data
458
- @rest_client.stub(:sshkeys) { key_data }
485
+ Net::SSH::KeyFactory.should_receive(:load_public_key).exactly(4).times.and_raise(NoMethodError)
486
+ wizard.should_receive(:ssh_keygen_fallback).exactly(4).times
487
+ wizard.should_receive(:ssh_keys).at_least(1).times.and_return(wizard.get_mock_key_data)
459
488
 
460
489
  wizard.send(:ssh_key_uploaded?)
461
-
462
- @fallback_run.should be_true
463
490
  end
464
491
 
465
492
  it "should cause upload_ssh_key to catch NoMethodError and call the fallback to get the fingerprint" do
466
- wizard.ssh_keys = wizard.get_mock_key_data
467
- @fallback_run = false
468
- wizard.stub(:ssh_keygen_fallback) do
469
- @fallback_run = true
470
- [OpenStruct.new( :name => 'default', :fingerprint => 'AA:BB:CC:DD:EE:FF', :type => 'ssh-rsa' )]
471
- end
472
- $?.stub(:exitstatus) { 255 }
473
- Net::SSH::KeyFactory.stub(:load_public_key) { raise NoMethodError }
493
+ Net::SSH::KeyFactory.should_receive(:load_public_key).exactly(5).times.and_raise(NoMethodError)
494
+ wizard.stub(:ssh_keys).at_least(1).times.and_return(wizard.get_mock_key_data)
495
+ wizard.should_receive(:ssh_keygen_fallback).exactly(5).times.and_return(stub(:name => 'default', :fingerprint => 'AA:BB:CC:DD:EE:FF', :type => 'ssh-rsa' ))
474
496
 
475
- wizard.send(:upload_ssh_key).should be_false
497
+ input_line 'y'
476
498
 
477
- output = last_output
478
- output.should match("Your ssh public key at .* is invalid or unreadable\.")
479
- @fallback_run.should be_true
499
+ wizard.send(:upload_ssh_key_stage).should be_false
500
+
501
+ last_output.should match("Your ssh public key at .* is invalid or unreadable\.")
480
502
  end
481
503
 
482
504
  it "should cause upload_ssh_key to catch NotImplementedError and return false" do
483
- wizard.ssh_keys = wizard.get_mock_key_data
484
- Net::SSH::KeyFactory.stub(:load_public_key) { raise NotImplementedError }
505
+ Net::SSH::KeyFactory.should_receive(:load_public_key).exactly(5).times.and_raise(NoMethodError)
506
+ wizard.should_receive(:ssh_keys).at_least(1).times.and_return(wizard.get_mock_key_data)
507
+
508
+ input_line 'y'
485
509
 
486
- wizard.send(:upload_ssh_key).should be_false
510
+ wizard.send(:upload_ssh_key_stage).should be_false
487
511
 
488
512
  output = last_output
489
513
  output.should match("Your ssh public key at .* is invalid or unreadable\.")
490
514
  end
491
515
 
516
+ it "should find a unique name" do
517
+ wizard.should_receive(:ssh_keys).at_least(1).times.and_return(wizard.get_mock_key_data)
518
+
519
+ wizard.send(:find_unique_key_name, 'cb490595').should == 'cb4905951'
520
+ wizard.send(:find_unique_key_name, 'default').should == 'default1'
521
+ wizard.send(:find_unique_key_name, 'abc').should == 'abc'
522
+ end
523
+
492
524
  it "should match ssh key fallback fingerprint to net::ssh fingerprint" do
493
525
  # we need to write to a live file system so ssh-keygen can find it
494
526
  FakeFS.deactivate!
@@ -521,12 +553,11 @@ describe RHC::Wizard do
521
553
  key_name = 'default'
522
554
  key_data = wizard.get_mock_key_data
523
555
  wizard.ssh_keys = key_data
524
- wizard.stub(:get_preferred_key_name) { key_name }
525
556
  wizard.stub(:ssh_key_triple_for_default_key) { pub_key.chomp.split }
526
557
  wizard.stub(:fingerprint_for_default_key) { "" } # this value is irrelevant
527
- wizard.rest_client.stub(:find_key) { key_data.detect { |k| k.name == key_name } }
558
+ wizard.rest_client = stub('RestClient').tap{ |o| o.stub(:find_key) { key_data.detect { |k| k.name == key_name } } }
528
559
 
529
- wizard.send(:upload_ssh_key)
560
+ wizard.send(:upload_ssh_key, key_name)
530
561
  output = last_output
531
562
  output.should match 'Updating'
532
563
  end
@@ -540,9 +571,9 @@ describe RHC::Wizard do
540
571
  wizard.ssh_keys = key_data
541
572
  wizard.stub(:ssh_key_triple_for_default_key) { pub_key.chomp.split }
542
573
  wizard.stub(:fingerprint_for_default_key) { "" } # this value is irrelevant
543
- wizard.rest_client.stub(:add_key) { true }
574
+ wizard.rest_client = stub('RestClient').tap{ |o| o.stub(:add_key) { true } }
544
575
 
545
- wizard.send(:upload_ssh_key)
576
+ wizard.send(:upload_ssh_key, "other")
546
577
  output = last_output
547
578
  # since the clashing key name is short, we expect to present
548
579
  # a key name with "1" attached to it.
@@ -689,3 +720,12 @@ EOF
689
720
  end
690
721
  end
691
722
  end
723
+
724
+ describe RHC::DomainWizard do
725
+ context "with a rest client" do
726
+ let(:rest_client){ stub }
727
+ it{ described_class.new(nil, nil, rest_client).rest_client.should == rest_client }
728
+ it{ subject.stages == [:config_namespace_stage] }
729
+ it{ expect{ described_class.new(nil, nil, rest_client).send(:config_namespace, '') }.to call(:add_domain).on(rest_client).and_stop }
730
+ end
731
+ end
@@ -75,6 +75,50 @@ end
75
75
 
76
76
  require 'rhc/cli'
77
77
 
78
+ class MockHighLineTerminal < HighLineExtension
79
+ def self.use_color?
80
+ true
81
+ end
82
+
83
+ def initialize(input=StringIO.new, output=StringIO.new)
84
+ super
85
+ @last_read_pos = 0
86
+ end
87
+
88
+ ##
89
+ # read
90
+ #
91
+ # seeks to the last read in the IO stream and reads
92
+ # the data from that position so we don't repeat
93
+ # reads or get empty data due to writes moving
94
+ # the caret to the end of the stream
95
+ def read
96
+ @output.seek(@last_read_pos)
97
+ result = @output.read
98
+ @last_read_pos = @output.pos
99
+ result
100
+ end
101
+
102
+ ##
103
+ # write_line
104
+ #
105
+ # writes a line of data to the end of the
106
+ # input stream appending a newline so
107
+ # highline knows to stop processing and then
108
+ # resets the caret position to the last read
109
+ def write_line(str)
110
+ reset_pos = @input.pos
111
+ # seek end so we don't overwrite anything
112
+ @input.seek(0, IO::SEEK_END)
113
+ result = @input.write "#{str}\n"
114
+ @input.seek(reset_pos)
115
+ result
116
+ end
117
+ def close_write
118
+ @input.close_write
119
+ end
120
+ end
121
+
78
122
  include WebMock::API
79
123
 
80
124
  def stderr
@@ -134,14 +178,14 @@ module CommandHelpers
134
178
  # let(:arguments){ [<arguments>] }
135
179
  #
136
180
 
137
- def run_command
181
+ def run_command(args=arguments)
138
182
  mock_terminal
139
183
  input.each { |i| $terminal.write_line(i) } if respond_to?(:input)
140
184
  $terminal.close_write
141
- run!(*arguments)
185
+ run!(*args)
142
186
  end
143
- def command_output
144
- run_command
187
+ def command_output(args=arguments)
188
+ run_command(args)
145
189
  rescue SystemExit => e
146
190
  "#{@output.string}\n#{$stderr.string}#{e}"
147
191
  else
@@ -178,7 +222,7 @@ module ClassSpecHelpers
178
222
  if obj
179
223
  Object.const_set(const_for, obj)
180
224
  else
181
- "#{description}".split(" ").map{|word| word.capitalize}.join.gsub(/[^\w]/, '')
225
+ "#{example.full_description}".split(" ").map{|word| word.capitalize}.join.gsub(/[^\w]/, '')
182
226
  end
183
227
  end
184
228
 
@@ -206,51 +250,6 @@ module ClassSpecHelpers
206
250
  Commander::Runner.instance
207
251
  end
208
252
 
209
- class MockHighLineTerminal < HighLine
210
-
211
- def self.use_color?
212
- true
213
- end
214
-
215
- def initialize(input, output)
216
- super
217
- @last_read_pos = 0
218
- end
219
-
220
- ##
221
- # read
222
- #
223
- # seeks to the last read in the IO stream and reads
224
- # the data from that position so we don't repeat
225
- # reads or get empty data due to writes moving
226
- # the caret to the end of the stream
227
- def read
228
- @output.seek(@last_read_pos)
229
- result = @output.read
230
- @last_read_pos = @output.pos
231
- result
232
- end
233
-
234
- ##
235
- # write_line
236
- #
237
- # writes a line of data to the end of the
238
- # input stream appending a newline so
239
- # highline knows to stop processing and then
240
- # resets the caret position to the last read
241
- def write_line(str)
242
- reset_pos = @input.pos
243
- # seek end so we don't overwrite anything
244
- @input.seek(0, IO::SEEK_END)
245
- result = @input.write "#{str}\n"
246
- @input.seek(reset_pos)
247
- result
248
- end
249
- def close_write
250
- @input.close_write
251
- end
252
- end
253
-
254
253
  def mock_terminal
255
254
  @input = StringIO.new
256
255
  @output = StringIO.new
@@ -342,7 +341,7 @@ module ClassSpecHelpers
342
341
  end
343
342
 
344
343
  module ExitCodeMatchers
345
- Spec::Matchers.define :exit_with_code do |code|
344
+ RSpec::Matchers.define :exit_with_code do |code|
346
345
  actual = nil
347
346
  match do |block|
348
347
  begin
@@ -366,20 +365,28 @@ module ExitCodeMatchers
366
365
  end
367
366
 
368
367
  module CommanderInvocationMatchers
369
- Spec::Matchers.define :call do |method|
368
+ InvocationMatch = Class.new(RuntimeError)
369
+
370
+ RSpec::Matchers.define :call do |method|
370
371
  chain :on do |object|
371
372
  @object = object
372
373
  end
373
- chain :with do |args|
374
+ chain :with do |*args|
374
375
  @args = args
375
376
  end
377
+ chain :and_stop do
378
+ @stop = true
379
+ end
376
380
 
377
381
  match do |block|
378
382
  e = @object.should_receive(method)
379
- e.with(@args) if @args
383
+ e.and_raise(InvocationMatch) if @stop
384
+ e.with(*@args) if @args
380
385
  begin
381
386
  block.call
382
387
  true
388
+ rescue InvocationMatch => e
389
+ true
383
390
  rescue SystemExit => e
384
391
  false
385
392
  end
@@ -388,6 +395,29 @@ module CommanderInvocationMatchers
388
395
  "expect block to invoke '#{method}' on #{@object} with #{@args}"
389
396
  end
390
397
  end
398
+
399
+ RSpec::Matchers.define :not_call do |method|
400
+ chain :on do |object|
401
+ @object = object
402
+ end
403
+ chain :with do |*args|
404
+ @args = args
405
+ end
406
+
407
+ match do |block|
408
+ e = @object.should_not_receive(method)
409
+ e.with(*@args) if @args
410
+ begin
411
+ block.call
412
+ true
413
+ rescue SystemExit => e
414
+ false
415
+ end
416
+ end
417
+ description do
418
+ "expect block to invoke '#{method}' on #{@object} with #{@args}"
419
+ end
420
+ end
391
421
  end
392
422
 
393
423
  module ColorMatchers
@@ -399,7 +429,7 @@ module ColorMatchers
399
429
  :clear => 0
400
430
  }
401
431
 
402
- Spec::Matchers.define :be_colorized do |msg,color|
432
+ RSpec::Matchers.define :be_colorized do |msg,color|
403
433
  match do |actual|
404
434
  actual == colorized_message(msg,color)
405
435
  end
@@ -436,7 +466,7 @@ def mac?
436
466
  RbConfig::CONFIG['host_os'] =~ /^darwin/
437
467
  end
438
468
 
439
- Spec::Runner.configure do |config|
469
+ RSpec.configure do |config|
440
470
  config.include(ExitCodeMatchers)
441
471
  config.include(CommanderInvocationMatchers)
442
472
  config.include(ColorMatchers)