rhc 1.0.4 → 1.1.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -174,6 +174,8 @@ module RHC
174
174
  date(value)
175
175
  when :scales_from,:scales_to
176
176
  (value == -1 ? "available gears" : value)
177
+ when :aliases
178
+ value.join ' '
177
179
  else
178
180
  value
179
181
  end
@@ -16,7 +16,7 @@ module RHC
16
16
  attr_reader :code
17
17
  def initialize(message=nil, code=nil)
18
18
  super(message)
19
- @code = code
19
+ @code = (Integer(code) rescue code)
20
20
  end
21
21
  end
22
22
 
@@ -150,11 +150,12 @@ module RHC
150
150
  def new_request(options)
151
151
  # user specified timeout takes presidence
152
152
  options[:timeout] = $rest_timeout || options[:timeout]
153
+ options[:open_timeout] ||= 4
153
154
 
154
155
  RestClient::Request.new options
155
156
  end
156
157
 
157
- def request(request)
158
+ def request(request, &block)
158
159
  begin
159
160
  response = request.execute
160
161
  #set cookie
@@ -162,25 +163,44 @@ module RHC
162
163
  if not rh_sso.nil?
163
164
  @@headers["cookie"] = "rh_sso=#{rh_sso}"
164
165
  end
165
- return parse_response(response) unless response.nil? or response.code == 204
166
+ if block_given?
167
+ yield response
168
+ else
169
+ parse_response(response) unless response.nil? or response.code == 204
170
+ end
166
171
  rescue RestClient::RequestTimeout => e
167
172
  raise TimeoutException.new("Connection to server timed out. It is possible the operation finished without being able to report success. Use 'rhc domain show' or 'rhc app status' to check the status of your applications.")
168
173
  rescue RestClient::ServerBrokeConnection => e
169
174
  raise ConnectionException.new("Connection to server got interrupted: #{e.message}")
170
175
  rescue RestClient::ExceptionWithResponse => e
171
- process_error_response(e.response)
176
+ process_error_response(e.response, request.url)
177
+ rescue SocketError => e
178
+ raise ConnectionException.new("Unable to connect to the server (#{e.message})."\
179
+ "#{RestClient.proxy.present? ? " Check that you have correctly specified your proxy server '#{RestClient.proxy}' as well as your OpenShift server '#{request.url}'." : " Check that you have correctly specified your OpenShift server '#{request.url}'."}")
172
180
  rescue => e
181
+ logger.debug e.backtrace.join("\n ") if @debug
173
182
  raise ResourceAccessException.new("Failed to access resource: #{e.message}")
174
183
  end
175
184
  end
176
185
 
177
- def process_error_response(response)
178
- messages = Array.new
186
+ def generic_error(url)
187
+ ServerErrorException.new(
188
+ "The server did not respond correctly. This may be an issue "\
189
+ "with the server configuration or with your connection to the "\
190
+ "server (such as a Web proxy or firewall)."\
191
+ "#{RestClient.proxy.present? ? " Please verify that your proxy server is working correctly (#{RestClient.proxy}) and that you can access the OpenShift server #{url}" : "Please verify that you can access the OpenShift server #{url}"}",
192
+ 129)
193
+ end
194
+
195
+ def process_error_response(response, url=nil)
196
+ messages = []
197
+ parse_error = nil
179
198
  begin
180
199
  result = RHC::Json.decode(response)
181
- messages = result['messages']
200
+ messages = Array(result['messages'])
182
201
  rescue => e
183
- logger.debug "Response did not include a message from server" if @mydebug
202
+ logger.debug "Response did not include a message from server: #{e.message}" if @debug
203
+ parse_error = generic_error(url)
184
204
  end
185
205
  case response.code
186
206
  when 401
@@ -191,29 +211,30 @@ module RHC
191
211
  raise RequestDeniedException, message['text']
192
212
  end
193
213
  end
214
+ raise RequestDeniedException.new("Forbidden")
194
215
  when 404
195
216
  messages.each do |message|
196
217
  if message['severity'].upcase == "ERROR"
197
218
  raise ResourceNotFoundException, message['text']
198
219
  end
199
220
  end
221
+ raise ResourceNotFoundException.new(url)
200
222
  when 409
201
223
  messages.each do |message|
202
224
  if message['severity'] and message['severity'].upcase == "ERROR"
203
- raise ValidationException, message['text']
225
+ raise ValidationException.new(message['text'], message['field'], message['exit_code'])
204
226
  end
205
227
  end
206
228
  when 422
207
- #puts response
208
229
  e = nil
209
230
  messages.each do |message|
210
231
  if e and e.field == message["field"]
211
232
  e.message << " #{message["text"]}"
212
233
  else
213
- e = ValidationException.new(message["text"], message["field"], message["code"])
234
+ e = ValidationException.new(message["text"], message["field"], message["exit_code"])
214
235
  end
215
236
  end
216
- raise e
237
+ raise e || parse_error || ValidationException.new('Not valid')
217
238
  when 400
218
239
  messages.each do |message|
219
240
  if message['severity'].upcase == "ERROR"
@@ -232,9 +253,11 @@ module RHC
232
253
  raise ServiceUnavailableException, message['text']
233
254
  end
234
255
  end
256
+ raise ServiceUnavailableException
235
257
  else
236
- raise ResourceAccessException, "Server returned error code with no output: #{response.code}"
258
+ raise ServerErrorException, "Server returned an unexpected error code: #{response.code}"
237
259
  end
260
+ raise parse_error || generic_error(url)
238
261
  end
239
262
  end
240
263
  end
@@ -3,7 +3,7 @@ require 'rhc/rest/base'
3
3
  module RHC
4
4
  module Rest
5
5
  class Cartridge < Base
6
- attr_reader :type, :name, :properties, :status_messages, :scales_to, :scales_from, :scales_with, :current_scale
6
+ attr_reader :type, :name, :display_name, :properties, :status_messages, :scales_to, :scales_from, :scales_with, :current_scale
7
7
  def initialize(args, use_debug=false)
8
8
  @properties = {}
9
9
  props = args[:properties] || args["properties"] || []
@@ -14,7 +14,7 @@ module RHC
14
14
  # The list may not necessarily be sorted; we will select the last
15
15
  # matching one supported by the server.
16
16
  # See #api_version_negotiated
17
- CLIENT_API_VERSIONS = [1.0, 1.1, 1.2]
17
+ CLIENT_API_VERSIONS = [1.1, 1.2, 1.3]
18
18
 
19
19
  def initialize(end_point, username, password, use_debug=false, preferred_api_versions = CLIENT_API_VERSIONS)
20
20
  @debug = use_debug
@@ -33,8 +33,8 @@ module RHC
33
33
  # :nocov:
34
34
  @@headers["Authorization"] = "Basic #{credentials}"
35
35
  @@headers["User-Agent"] = RHC::Helpers.user_agent rescue nil
36
- RestClient.proxy = ENV['http_proxy']
37
-
36
+ RestClient.proxy = URI.parse(ENV['http_proxy']).to_s if ENV['http_proxy']
37
+
38
38
  # API version negotiation
39
39
  begin
40
40
  debug "Client supports API versions #{preferred_api_versions.join(', ')}"
@@ -42,7 +42,7 @@ module RHC
42
42
  default_request = new_request(:url => @end_point, :method => :get, :headers => @@headers)
43
43
  @server_api_versions, links = api_info(default_request)
44
44
  debug "Server supports API versions #{@server_api_versions.join(', ')}"
45
-
45
+
46
46
  if api_version_negotiated
47
47
  unless server_api_version_current?
48
48
  debug "Client API version #{api_version_negotiated} is not current. Refetching API"
@@ -54,8 +54,6 @@ module RHC
54
54
  else
55
55
  warn_about_api_versions
56
56
  end
57
- rescue Exception => e
58
- raise ResourceAccessException.new("Failed to access resource: #{e.message}")
59
57
  end
60
58
 
61
59
  super({:links => links}, use_debug)
@@ -73,7 +71,7 @@ module RHC
73
71
 
74
72
  def cartridges
75
73
  debug "Getting all cartridges"
76
- rest_method "LIST_CARTRIDGES"
74
+ rest_method("LIST_CARTRIDGES")
77
75
  end
78
76
 
79
77
  def user
@@ -192,8 +190,10 @@ server at #{URI.parse(@end_point).host} supports #{@server_api_versions.join(',
192
190
  private
193
191
  # execute +req+ with RestClient, and return [server_api_versions, links]
194
192
  def api_info(req)
195
- json_response = ::RHC::Json.decode(req.execute)
196
- [ json_response['supported_api_versions'], json_response['data'] ]
193
+ request(req) do |response|
194
+ json_response = ::RHC::Json.decode(response)
195
+ [ json_response['supported_api_versions'], json_response['data'] ]
196
+ end
197
197
  end
198
198
  end
199
199
  end
@@ -8,7 +8,7 @@ List of Actions
8
8
  <%= "%-18s %s\n" % [action[:name], action[:summary]] -%>
9
9
  <% end -%>
10
10
  <% end -%>
11
- <% unless @command.options.nil? or @command.options.empty? or @command.options.all?{ |o| o[:hide] } -%>
11
+ <% unless @command.options.blank? or @command.options.all?{ |o| o[:hide] } -%>
12
12
 
13
13
  Options for <%= @command.name %>
14
14
  <% for option in @command.options -%><% next if option[:hide] -%>
@@ -0,0 +1,11 @@
1
+ Usage: rhc <%= @command.name %> <%= @command.syntax %>
2
+ <% unless @command.options.blank? or @command.options.all?{ |o| o[:hide] } -%>
3
+ Pass '--help' to see the full list of options
4
+ <% end -%>
5
+ <% unless @actions.nil? or @actions.empty? -%>
6
+
7
+ List of Actions
8
+ <% for action in @actions -%>
9
+ <%= "%-18s %s\n" % [action[:name], action[:summary]] -%>
10
+ <% end -%>
11
+ <% end -%>
@@ -1,8 +1,8 @@
1
1
  module RHC
2
2
  module VERSION #:nocov:
3
3
  MAJOR = 1
4
- MINOR = 0
5
- MICRO = 4
4
+ MINOR = 1
5
+ MICRO = 11
6
6
  #PRE = ''
7
7
  STRING = [MAJOR,MINOR,MICRO].compact.join('.')
8
8
  end
@@ -34,7 +34,7 @@ module RHC
34
34
  @libra_server = @libra_server ? @libra_server : "openshift.redhat.com"
35
35
  end
36
36
  @config.config_user opts.rhlogin if opts && opts.rhlogin
37
- @debug = opts.debug if opts.respond_to? :debug
37
+ @debug = opts.debug if opts
38
38
  end
39
39
 
40
40
  # Public: Runs the setup wizard to make sure ~/.openshift and ~/.ssh are correct
@@ -157,11 +157,11 @@ module RestSpecHelper
157
157
  end
158
158
 
159
159
  def cartridges
160
- [MockRestCartridge.new("mock_standalone_cart-1", "standalone"),
160
+ [MockRestCartridge.new("mock_cart-1", "embedded"), # code should sort this to be after standalone
161
+ MockRestCartridge.new("mock_standalone_cart-1", "standalone"),
161
162
  MockRestCartridge.new("mock_standalone_cart-2", "standalone"),
162
163
  MockRestCartridge.new("mock_unique_standalone_cart-1", "standalone"),
163
164
  MockRestCartridge.new("jenkins-1.4", "standalone"),
164
- MockRestCartridge.new("mock_cart-1", "embedded"),
165
165
  MockRestCartridge.new("mock_cart-2", "embedded"),
166
166
  MockRestCartridge.new("unique_mock_cart-1", "embedded"),
167
167
  MockRestCartridge.new("jenkins-client-1.4", "embedded")]
@@ -324,7 +324,7 @@ module RestSpecHelper
324
324
  end
325
325
 
326
326
  class MockRestCartridge < RHC::Rest::Cartridge
327
- attr_accessor :scales_to, :scales_from, :current_scale, :scales_with
327
+ attr_accessor :scales_to, :scales_from, :current_scale, :scales_with, :display_name
328
328
  def initialize(name, type, app=nil, properties={:cart_data => {:connection_url => {'name' => 'connection_url', 'value' => "http://fake.url" }}})
329
329
  @name = name
330
330
  @type = type
@@ -379,3 +379,7 @@ module RestSpecHelper
379
379
  end
380
380
  end
381
381
  end
382
+
383
+ Spec::Runner.configure do |configuration|
384
+ include(RestSpecHelper)
385
+ end
@@ -78,7 +78,11 @@ describe RHC::CLI do
78
78
 
79
79
  describe '#set_terminal' do
80
80
  before(:each) { mock_terminal }
81
- it('should update $terminal.wrap_at') { expect { RHC::CLI.set_terminal }.to change($terminal, :wrap_at) }
81
+ it('should update $terminal.wrap_at') do
82
+ $stdin.should_receive(:tty?).and_return(true)
83
+ HighLine::SystemExtensions.should_receive(:terminal_size).and_return([5])
84
+ expect { RHC::CLI.set_terminal }.to change($terminal, :wrap_at)
85
+ end
82
86
  end
83
87
 
84
88
  end
@@ -55,7 +55,9 @@ describe RHC::Commands::Base do
55
55
  end
56
56
 
57
57
  expects_running('test').should call(:run).on(instance).with(no_args)
58
- wizard_run.should be_true
58
+ wizard_run.should be_false
59
+
60
+ stderr.should match("You have not yet configured the OpenShift client tools")
59
61
  end
60
62
  end
61
63
  end
@@ -151,10 +153,7 @@ describe RHC::Commands::Base do
151
153
  context 'and when deprecated alias is called' do
152
154
  it do
153
155
  expects_running('static', 'exe', "arg").should call(:execute).on(instance).with('arg')
154
- $stderr.seek(0)
155
- # some systems might redirect warnings to stderr
156
- output = "#{$stderr.read} #{$terminal.read}"
157
- output.should match("Warning: This command is deprecated. Please use 'rhc static execute' instead.")
156
+ stderr.should match("Warning: This command is deprecated. Please use 'rhc static execute' instead.")
158
157
  end
159
158
  end
160
159
 
@@ -18,7 +18,7 @@ describe RHC::Commands::App do
18
18
  raise RHC::GitException, "Error in git clone" if repo_dir == "giterrorapp"
19
19
  Dir::mkdir(repo_dir)
20
20
  end
21
- @instance.stub(:host_exist?) do |host|
21
+ @instance.stub(:host_exists?) do |host|
22
22
  host.match("dnserror") ? false : true
23
23
  end
24
24
  @instance
@@ -42,28 +42,37 @@ describe RHC::Commands::App do
42
42
  end
43
43
 
44
44
  describe 'app create' do
45
- let(:arguments) { ['app', 'create', 'app1', 'mock_standalone_cart-1', '--noprompt', '--timeout', '10', '--config', 'test.conf', '-l', 'test@test.foo', '-p', 'password'] }
45
+ before(:each) do
46
+ @rc = MockRestClient.new
47
+ domain = @rc.add_domain("mockdomain")
48
+ end
46
49
 
47
- context 'when run' do
48
- before(:each) do
49
- @rc = MockRestClient.new
50
- domain = @rc.add_domain("mockdomain")
51
- end
50
+ context 'when run without a cart' do
51
+ before{ FakeFS.deactivate! }
52
+ let(:arguments) { ['app', 'create', 'app1', '--noprompt', '--timeout', '10', '--config', 'test.conf', '-l', 'test@test.foo', '-p', 'password'] }
53
+ it { run_output.should match(/mock_standalone_cart-1.*Every application needs a web cartridge/m) }
54
+ end
55
+
56
+ context 'when run with a valid cart' do
57
+ let(:arguments) { ['app', 'create', 'app1', 'mock_standalone_cart-1', '--noprompt', '--timeout', '10', '--config', 'test.conf', '-l', 'test@test.foo', '-p', 'password'] }
52
58
  it { expect { run }.should exit_with_code(0) }
53
59
  it { run_output.should match("Success") }
54
60
  end
55
- end
56
-
57
- describe 'app create no cart found error' do
58
- let(:arguments) { ['app', 'create', 'app1', 'nomatch_cart', '--trace', '--noprompt', '--config', 'test.conf', '-l', 'test@test.foo', '-p', 'password'] }
59
61
 
60
- context 'when run' do
62
+ context 'when no cartridges are returned' do
61
63
  before(:each) do
62
- @rc = MockRestClient.new
63
- domain = @rc.add_domain("mockdomain")
64
+ domain = @rc.domains.first
64
65
  @rc.stub(:cartridges) { [] }
66
+ domain.stub(:add_application).and_raise(RHC::Rest::ValidationException.new('Each application needs a web cartridge', '', '109'))
67
+ end
68
+ context 'without trace' do
69
+ let(:arguments) { ['app', 'create', 'app1', 'nomatch_cart', '--noprompt', '--config', 'test.conf', '-l', 'test@test.foo', '-p', 'password'] }
70
+ it { run_output.should match(/Valid cartridge types:.*Each application needs a web cartridge/m) }
71
+ end
72
+ context 'with trace' do
73
+ let(:arguments) { ['app', 'create', 'app1', 'nomatch_cart', '--noprompt', '--config', 'test.conf', '-l', 'test@test.foo', '-p', 'password', '--trace'] }
74
+ it { expect { run }.should raise_error(RHC::Rest::ValidationException) }
65
75
  end
66
- it { expect { run }.should raise_error(RHC::CartridgeNotFoundException) }
67
76
  end
68
77
  end
69
78
 
@@ -188,10 +197,10 @@ describe RHC::Commands::App do
188
197
  @instance.stub(:setup_jenkins_client) { raise RHC::Rest::ServerErrorException.new("Server error", 157) }
189
198
  end
190
199
  it "should fail embedding jenkins cartridge" do
200
+ Kernel.should_receive(:sleep).and_return(true)
191
201
  run_output.should match("Jenkins client failed to install")
192
202
  end
193
203
  end
194
-
195
204
  end
196
205
 
197
206
  describe 'dns app create warnings' do
@@ -34,9 +34,18 @@ describe RHC::Commands::Cartridge do
34
34
  before(:each) do
35
35
  @rc = MockRestClient.new
36
36
  end
37
- it {
38
- succeed_with_message "mock_cart-1, mock_cart-2, unique_mock_cart-1"
39
- }
37
+ it { succeed_with_message /mock_cart-1.*mock_cart-2.*unique_mock_cart-1/m }
38
+ end
39
+ end
40
+
41
+ describe 'run without password' do
42
+ let(:arguments) { ['cartridge', '--trace', '--noprompt', '--config', 'test.conf'] }
43
+
44
+ context 'when run' do
45
+ before(:each) do
46
+ @rc = MockRestClient.new
47
+ end
48
+ it { succeed_with_message /mock_cart-1.*mock_cart-2.*unique_mock_cart-1/m }
40
49
  end
41
50
  end
42
51
 
@@ -47,9 +56,7 @@ describe RHC::Commands::Cartridge do
47
56
  before(:each) do
48
57
  @rc = MockRestClient.new
49
58
  end
50
- it {
51
- succeed_with_message "mock_cart-1, mock_cart-2, unique_mock_cart-1"
52
- }
59
+ it { succeed_with_message /mock_cart-1.*mock_cart-2.*unique_mock_cart-1/m }
53
60
  end
54
61
  end
55
62
 
@@ -32,6 +32,19 @@ describe RHC::Commands::Setup do
32
32
  end
33
33
  end
34
34
 
35
+ context 'when -d is passed' do
36
+ let(:arguments) { ['setup', '-d', '-l', 'test@test.foo'] }
37
+ # 'y' for the password prompt
38
+ let(:input) { ['', 'y', '', ''] }
39
+
40
+ before(:each){ @rc = MockRestClient.new }
41
+
42
+ it("succeeds"){ FakeFS{ expect { run input }.should exit_with_code 0 } }
43
+ it("the output includes debug output") do
44
+ FakeFS{ run_output( input ).should match 'DEBUG' }
45
+ end
46
+ end
47
+
35
48
  context 'when -l is used to specify the user name' do
36
49
  let(:arguments) { ['setup', '-l', 'test@test.foo'] }
37
50
  # 'y' for the password prompt
@@ -112,17 +112,18 @@ describe RHC::Commands::Sshkey do
112
112
  context "when attempting to add an existing but inaccessible key" do
113
113
  let(:arguments) { %w[sshkey add --noprompt --config test.conf -l test@test.foo -p password foobar inaccessible_key.pub] }
114
114
 
115
- before :all do
116
- @inaccessible_key = 'inaccessible_key.pub'
117
- File.new(@inaccessible_key, 'w+')
118
- File.chmod(0000, @inaccessible_key)
119
- end
115
+ #before :all do
116
+ # @inaccessible_key = 'inaccessible_key.pub'
117
+ # File.new(@inaccessible_key, 'w+')
118
+ # File.chmod(0000, @inaccessible_key)
119
+ #end
120
120
 
121
- after :all do
122
- File.delete @inaccessible_key
123
- end
121
+ #after :all do
122
+ # File.delete @inaccessible_key
123
+ #end
124
124
 
125
125
  it "exits with status code Errno::EACCES::Errno" do
126
+ File.should_receive(:open).and_raise(Errno::EACCES)
126
127
  expect { run }.should exit_with_code(128)
127
128
  end
128
129