rhc 0.81.14 → 0.82.18

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 (6) hide show
  1. data/Rakefile +15 -3
  2. data/bin/rhc-chk +356 -124
  3. data/bin/rhc-create-app +21 -23
  4. data/bin/rhc-ctl-app +13 -8
  5. data/lib/rhc-common.rb +65 -47
  6. metadata +10 -10
data/Rakefile CHANGED
@@ -3,7 +3,13 @@
3
3
  require 'rubygems'
4
4
  require 'rake'
5
5
  require 'rake/clean'
6
- require 'rubygems/package_task'
6
+
7
+ begin
8
+ require 'rubygems/package_task'
9
+ rescue LoadError
10
+ require 'rake/gempackagetask'
11
+ rake_gempackage = true
12
+ end
7
13
 
8
14
  task :default => [:package]
9
15
 
@@ -31,8 +37,14 @@ spec = Gem::Specification.new do |s|
31
37
  end
32
38
 
33
39
  # Define a :package task that bundles the gem
34
- Gem::PackageTask.new(spec) do |pkg, args|
35
- pkg.need_tar = false
40
+ if rake_gempackage
41
+ Rake::GemPackageTask.new(spec) do |pkg, args|
42
+ pkg.need_tar = false
43
+ end
44
+ else
45
+ Gem::PackageTask.new(spec) do |pkg, args|
46
+ pkg.need_tar = false
47
+ end
36
48
  end
37
49
 
38
50
  # Add the 'pkg' directory to the clean task
@@ -25,14 +25,18 @@ require 'rhc-common'
25
25
  require 'net/http'
26
26
  require 'net/https'
27
27
  require 'rbconfig'
28
+ require 'yaml'
29
+ require 'tempfile'
28
30
 
31
+ require 'test/unit'
32
+ require 'test/unit/ui/console/testrunner'
29
33
 
30
34
  #
31
35
  # print help
32
36
  #
33
37
  def p_usage
34
- rhlogin = get_var('default_rhlogin') ? "Default: #{get_var('default_rhlogin')}" : "required"
35
- puts <<USAGE
38
+ rhlogin = get_var('default_rhlogin') ? "Default: #{get_var('default_rhlogin')}" : "required"
39
+ puts <<USAGE
36
40
 
37
41
  Usage: #{$0}
38
42
  Run a simple check on local configs and credentials to confirm tools are
@@ -50,177 +54,405 @@ exit 255
50
54
  end
51
55
 
52
56
  begin
53
- opts = GetoptLong.new(
54
- ["--debug", "-d", GetoptLong::NO_ARGUMENT],
55
- ["--help", "-h", GetoptLong::NO_ARGUMENT],
56
- ["--rhlogin", "-l", GetoptLong::REQUIRED_ARGUMENT],
57
- ["--password", "-p", GetoptLong::REQUIRED_ARGUMENT],
58
- ["--config", GetoptLong::REQUIRED_ARGUMENT],
59
- ["--timeout", GetoptLong::REQUIRED_ARGUMENT]
60
- )
61
- opt = {}
62
- opts.each do |o, a|
63
- opt[o[2..-1]] = a.to_s
64
- end
57
+ opts = GetoptLong.new(
58
+ ["--debug", "-d", GetoptLong::NO_ARGUMENT],
59
+ ["--help", "-h", GetoptLong::NO_ARGUMENT],
60
+ ["--rhlogin", "-l", GetoptLong::REQUIRED_ARGUMENT],
61
+ ["--password", "-p", GetoptLong::REQUIRED_ARGUMENT],
62
+ ["--config", GetoptLong::REQUIRED_ARGUMENT],
63
+ ["--timeout", GetoptLong::REQUIRED_ARGUMENT]
64
+ )
65
+ $opt = {}
66
+ opts.each do |o, a|
67
+ $opt[o[2..-1]] = a.to_s
68
+ end
65
69
  rescue Exception => e
66
70
  #puts e.message
67
- p_usage
71
+ p_usage
72
+ end
73
+
74
+ if $opt["help"]
75
+ p_usage
68
76
  end
69
77
 
78
+
70
79
  # If provided a config path, check it
71
- check_cpath(opt)
80
+ check_cpath($opt)
81
+
82
+ # Need to store the config information so tests can use it
83
+ # since they are technically new objects
84
+ $opts_config_path = @opts_config_path
85
+ $local_config_path = @local_config_path
86
+ $opts_config = @opts_config
87
+ $local_config = @local_config
88
+ $global_config = @global_config
72
89
 
73
90
  # Pull in configs from files
74
- @libra_server = get_var('libra_server')
75
- @debug = get_var('debug') == 'false' ? nil : get_var('debug')
91
+ $libra_server = get_var('libra_server')
92
+ $debug = get_var('debug') == 'false' ? nil : get_var('debug')
76
93
 
77
- if opt["help"]
78
- p_usage
79
- end
80
94
 
81
- if opt["debug"]
82
- @debug = true
95
+ if $opt["debug"]
96
+ $debug = true
83
97
  end
84
- RHC::debug(@debug)
98
+ RHC::debug($debug)
85
99
 
86
- RHC::timeout(opt["timeout"] ? opt["timeout"] : get_var('timeout'))
100
+ RHC::timeout($opt["timeout"] ? $opt["timeout"] : get_var('timeout'))
87
101
 
88
- opt["rhlogin"] = get_var('default_rhlogin') unless opt["rhlogin"]
89
- if !RHC::check_rhlogin(opt['rhlogin'])
90
- p_usage
102
+ $opt["rhlogin"] = get_var('default_rhlogin') unless $opt["rhlogin"]
103
+ if !RHC::check_rhlogin($opt['rhlogin'])
104
+ p_usage
91
105
  end
92
- @rhlogin = opt["rhlogin"]
106
+ $rhlogin = $opt["rhlogin"]
93
107
 
94
- @password = opt['password']
95
- if !@password
96
- @password = RHC::get_password
108
+ $password = $opt['password']
109
+ if !$password
110
+ $password = RHC::get_password
97
111
  end
98
112
 
99
113
  #
100
114
  # Generic Info
101
115
  #
102
- puts "Ruby Version: #{RUBY_VERSION}"
103
- puts "host_alias: #{Config::CONFIG['host_alias']}"
116
+ $debuginfo = {
117
+ 'environment' => {
118
+ 'Ruby Version' => RUBY_VERSION,
119
+ "host_alias" => Config::CONFIG['host_alias']
120
+ },
121
+ 'options' => {
122
+ "Command Line" => $opt,
123
+ "Opts" => $opts_config,
124
+ "Local" => $local_config,
125
+ "Global" => $global_config
126
+ }
127
+ }
128
+
129
+ # Don't actually log the password, but some information to help with troubleshooting
130
+ if $opt['password']
131
+ $debuginfo['options']['Command Line']['password'] = {
132
+ "Length" => $opt['password'].length,
133
+ "Starts with" => $opt['password'][0..0]
134
+ }
135
+ end
104
136
 
105
137
  #
106
138
  # Check for proxy environment
107
139
  #
108
140
  if ENV['http_proxy']
109
- host, port = ENV['http_proxy'].split(':')
110
- @http = Net::HTTP::Proxy(host, port)
111
- puts "Proxy being used: #{host}:#{port}"
141
+ if ENV['http_proxy']!~/^(\w+):\/\// then
142
+ ENV['http_proxy']="http://" + ENV['http_proxy']
143
+ end
144
+ proxy_uri=URI.parse(ENV['http_proxy'])
145
+ $http = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
146
+ $debuginfo['environment']['proxy'] = "#{proxy_uri.user}:#{proxy_uri.password}@#{proxy_uri.host}:#{proxy_uri.port}"
112
147
  else
113
- @http = Net::HTTP
114
- puts "Proxy being used: none"
148
+ $http = Net::HTTP
149
+ $debuginfo['environment']['proxy'] = "none"
115
150
  end
116
151
 
117
- def test_url_json(uri, data)
152
+ #####################################
153
+ # Done setting up environment #
154
+ #####################################
155
+
156
+ module TestBase
157
+ def initialize(*args)
158
+ super
159
+ $connectivity ||= false
160
+ # These need to be loaded for each test to be able to access them
161
+ @opts_config_path = $opts_config_path
162
+ @local_config_path = $local_config_path
163
+ @opts_config = $opts_config
164
+ @local_config = $local_config
165
+ @global_config = $global_config
166
+ end
167
+
168
+ def fetch_url_json(uri, data)
118
169
  json_data = RHC::generate_json(data)
119
- url = URI.parse("https://#{@libra_server}#{uri}")
120
- puts " Contacting URL: https://#{@libra_server}#{uri}" if @debug
121
- puts " json_data: #{json_data}" if @debug
122
- req = @http::Post.new(url.path)
123
- req.set_form_data({'json_data' => json_data, 'password' => @password})
124
- http = @http.new(url.host, url.port)
170
+ url = URI.parse("https://#{$libra_server}#{uri}")
171
+ req = $http::Post.new(url.path)
172
+ req.set_form_data({'json_data' => json_data, 'password' => $password})
173
+ http = $http.new(url.host, url.port)
125
174
  http.open_timeout = 10
126
175
  http.use_ssl = true
127
176
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
128
- response = nil
177
+
178
+ response = http.start {|http| http.request(req)}
179
+ return response
180
+ ensure
181
+ $debuginfo['fetches'] ||= []
182
+ body = JSON.parse(response.body)
183
+ body['data'] = body['data'] ? JSON.parse(body['data']) : ''
184
+ $debuginfo['fetches'] << {url.to_s => {
185
+ 'body' => body,
186
+ 'header' => response.instance_variable_get(:@header)
187
+ }}
188
+ end
189
+
190
+ def continue_test
129
191
  begin
130
- response = http.start {|http| http.request(req)}
131
- puts " Raw Response: #{response.body}" if @debug
132
- rescue Exception => e
133
- puts " ERROR: #{e.message}"
192
+ yield
193
+ rescue Test::Unit::AssertionFailedError => e
194
+ self.send(:add_failure,e.message,e.backtrace)
134
195
  end
135
- if response
136
- puts " Code: #{response.code}"
137
- puts " Message: #{response.message}"
138
- if response.code == '200'
139
- puts response.body
140
- resp_json = JSON.parse(response.body)
141
- return resp_json
142
- elsif response.code == '404' && data['rhlogin']
143
- puts "A user with rhlogin '#{data['rhlogin']}' does not have a registered domain."
144
- exit 99
145
- elsif response.code == '401'
146
- puts "Invalid user credentials"
147
- exit 97
148
- else
149
- puts "Exiting due to error!"
150
- exit 1
151
- end
196
+ end
197
+ end
198
+
199
+ #####################################################
200
+ # Tests start here #
201
+ #####################################################
202
+ # #
203
+ # Note: Tests and testcases are run alphabetically #
204
+ # #
205
+ #####################################################
206
+
207
+ def error_for(name,*args)
208
+ if name.kind_of? String
209
+ name = name.downcase.to_sym
210
+ end
211
+ sprintf($messages[name],*args)
212
+ end
213
+
214
+ class Test1_Connectivity < Test::Unit::TestCase
215
+ include TestBase
216
+ def teardown
217
+ # Set global variable in case we cannot connect to the server
218
+ if method_name == 'test_connectivity'
219
+ $connectivity = passed?
220
+ end
221
+ end
222
+
223
+ #
224
+ # Checking Connectivity / cart list
225
+ #
226
+ def test_connectivity
227
+ data = {'cart_type' => 'standalone'}
228
+
229
+ response = fetch_url_json("/broker/cartlist", data)
230
+ assert_equal 200, response.code.to_i, error_for(:no_connectivity, $libra_server)
231
+ end
232
+ end
233
+
234
+ class Test2_Authentication < Test::Unit::TestCase
235
+ include TestBase
236
+ #
237
+ # Checking Authentication
238
+ #
239
+ def test_authentication
240
+ assert $connectivity, error_for(:cant_connect)
241
+
242
+ data = {'rhlogin' => $rhlogin}
243
+ response = fetch_url_json("/broker/userinfo", data)
244
+ resp_json = JSON.parse(response.body)
245
+
246
+ case response.code.to_i
247
+ when 404
248
+ assert false, error_for(:_404, $rhlogin)
249
+ when 401
250
+ assert false, error_for(:_401, $rhlogin)
251
+ when 200
252
+ assert true
152
253
  else
153
- puts "Unable to connect to: https://#{@libra_server}"
154
- exit 1
254
+ assert false, error_for(:_other_http, resp_json['result'])
155
255
  end
256
+
257
+ $user_info = JSON.parse(resp_json['data'].to_s)
258
+ end
156
259
  end
157
260
 
158
261
  #
159
- # Checking Connectivity / cart list
262
+ # Checking ssh key
160
263
  #
161
- puts
162
- puts "TEST1: Confirming connection to OpenShift"
163
- data = {'cart_type' => 'standalone'}
264
+ class Test3_SSH < Test::Unit::TestCase
164
265
 
165
- resp_json = test_url_json("/broker/cartlist", data)
166
- puts " Cart Info: #{resp_json["data"]}"
266
+ @@local_derived_ssh_pubkey = nil
267
+ @@local_ssh_pubkey = nil
167
268
 
269
+ include TestBase
168
270
 
169
- #
170
- # Checking Authentication
171
- #
172
- puts
173
- puts "TEST2: Authentication (RHN account) / user info"
174
- data = {'rhlogin' => @rhlogin}
271
+ def setup
272
+ @libra_kfile = get_kfile(false)
273
+ if @libra_kfile
274
+ @libra_kpfile = get_kpfile(@libra_kfile, false)
275
+ end
276
+ end
175
277
 
176
- resp_json = test_url_json("/broker/userinfo", data)
177
- @user_info = JSON.parse(resp_json['data'].to_s)
178
- puts " rhlogin: #{@user_info["user_info"]["rhlogin"]}"
179
- puts " namespace: #{@user_info["user_info"]["namespace"]}"
278
+ def test_01_ssh_private_key
279
+ check_permissions(@libra_kfile, /[4-7]00/) # Needs to at least be readable by user and nobody else
180
280
 
181
- #
182
- # Checking ssh key
183
- #
184
- puts
185
- puts "TEST3: SSH Key check"
186
- remote_ssh_pubkey = @user_info["user_info"]["ssh_key"]
187
- libra_kfile = get_kfile()
188
- libra_kpfile = get_kpfile(libra_kfile, false)
189
-
190
- if File.exists?(libra_kfile)
191
- puts " OK: #{libra_kfile} - Found"
192
- key_dump = `ssh-keygen -f #{libra_kfile} -y`
193
- local_derived_ssh_pubkey = key_dump.to_s.strip.split(' ')[1]
194
- else
195
- puts " ERROR: #{libra_kfile} - Not Found!"
196
- end
281
+ # Derive the public key from the private key
282
+ key_dump = `ssh-keygen -f #{@libra_kfile} -y`
283
+ @@local_derived_ssh_pubkey = key_dump.to_s.strip.split(' ')[1]
197
284
 
198
- if File.exists?(libra_kpfile)
199
- puts " OK: #{libra_kpfile} Found"
200
- fp = File.open(libra_kpfile)
201
- local_ssh_pubkey = fp.gets.split(' ')[1]
202
- fp.close
203
- else
204
- puts " WARNING: #{libra_kpfile} Not Found! (non fatal error)"
205
- end
285
+ assert_not_nil @@local_derived_ssh_pubkey, error_for(:no_derive)
206
286
 
207
- if local_ssh_pubkey.to_s.strip == remote_ssh_pubkey.to_s.strip
208
- puts " OK: Remote and #{libra_kpfile} - match"
209
- else
210
- puts " WARNING: Remote and #{libra_kpfile} key do not match. (have you changed machines or ssh keys?)"
287
+ assert_not_nil $user_info, error_for(:no_account)
288
+ remote_ssh_pubkey = $user_info["user_info"]["ssh_key"]
289
+
290
+ assert_match @@local_derived_ssh_pubkey, remote_ssh_pubkey, error_for(:no_match_pub, @libra_kfile)
291
+ end
292
+
293
+ def test_02_ssh_public_key
294
+ check_permissions(@libra_kpfile, /.../) # Any permissions are OK
295
+
296
+ # Store the public key
297
+ fp = File.open(@libra_kpfile)
298
+ @@local_ssh_pubkey = fp.gets.split(' ')[1]
299
+
300
+ assert_not_nil @@local_ssh_pubkey, error_for(:no_pubkey, 'the remote key')
301
+
302
+ assert_not_nil $user_info, error_for(:no_account)
303
+ remote_ssh_pubkey = $user_info["user_info"]["ssh_key"]
304
+
305
+ # Test public key and remote key
306
+ assert_match @@local_ssh_pubkey, remote_ssh_pubkey, error_for(:no_match_pub,@libra_kpfile)
307
+ ensure
308
+ fp.close if fp
309
+ end
310
+
311
+ def test_05_ssh_config
312
+ check_permissions('~/.ssh/config',/600/)
313
+ end
314
+
315
+ def test_06_ssh_agent
316
+ loaded_keys = `ssh-add -L`.to_a
317
+ # Make sure we can load keys from ssh-agent
318
+ assert !loaded_keys.empty?, error_for(:no_keys_loaded)
319
+ loaded_keys.map!{|key| key.split(' ')[1]}
320
+
321
+ assert_not_nil @@local_ssh_pubkey, error_for(:no_pubkey, 'the keys in ssh-agent')
322
+ assert loaded_keys.include?(@@local_ssh_pubkey),error_for(:pubkey_not_loaded)
323
+ end
324
+
325
+ def test_07_ssh_connect
326
+ assert_not_nil $user_info, error_for(:no_account)
327
+ host_template = "%s@%s-%s.%s"
328
+ $user_info['app_info'].each do |k,v|
329
+ uuid = v['uuid']
330
+ host = sprintf("%s-%s",k,$user_info['user_info']['namespace'])
331
+ domain = $user_info['user_info']['rhc_domain']
332
+ ssh_command = sprintf("ssh %s@%s.%s true &> /dev/null", uuid, host, domain)
333
+ system(ssh_command)
334
+ continue_test{ assert_equal $?, 0, error_for(:cant_ssh, host) }
335
+ end
336
+ end
337
+
338
+ private
339
+ def check_permissions(file,permission)
340
+ file = File.expand_path(file)
341
+
342
+ assert File.exists?(file), error_for(:file_not_found,file)
343
+
344
+ perms = sprintf('%o',File.stat(file).mode)[-3..-1]
345
+
346
+ assert_match permission, perms, error_for(:bad_permissions,file,perms,permission.source)
347
+ end
211
348
  end
212
349
 
213
- if local_derived_ssh_pubkey.to_s.strip == remote_ssh_pubkey.to_s.strip
214
- puts " OK: local #{libra_kfile} should auth with openshift"
215
- else
216
- puts " WARNING: local #{libra_kpfile} DOES NOT match remote pub key, ssh auth cannot continue"
217
- puts " FIX: Perhaps you should regenerate your public key, or run rhc-create-domain with -a to alter the remote key"
350
+ ############################################################
351
+ # Below this line is the custom Test::Runner code #
352
+ # Modification should not be necessary to add/modify tests #
353
+ ############################################################
354
+
355
+ class CheckRunner < Test::Unit::UI::Console::TestRunner
356
+ def initialize(*args)
357
+ super
358
+ @output_level = 1
359
+ puts $messages[:started]
360
+ end
361
+
362
+ def add_fault(fault)
363
+ @faults << fault
364
+ print(fault.single_character_display)
365
+ @already_outputted = true
366
+ end
367
+
368
+ def print_underlined(string)
369
+ string = "|| #{string} ||"
370
+ line = "=" * string.length
371
+ puts
372
+ puts line
373
+ puts string
374
+ puts line
375
+ end
376
+
377
+ def render_message(message)
378
+ lines = message.to_a
379
+ message = []
380
+ @num ||= 0
381
+ message << "#{@num+=1}) #{lines.shift.strip}"
382
+ lines.each do |line|
383
+ # Break if we get the standard assert error information or a blank line
384
+ break if line.match(/^\<.*?> /) or line.match(/^\s*$/)
385
+ message << "\t#{line.strip}"
386
+ end
387
+ message.join("\n")
388
+ end
389
+
390
+ def finished(*args)
391
+ super
392
+ $debuginfo['errors'] = @faults
393
+
394
+ if @faults.empty?
395
+ print_underlined $messages[:passed]
396
+ else
397
+ print_underlined $messages[:failed]
398
+ @errors = []
399
+ # Need to separate the failures from the errors
400
+
401
+ @faults.each do |f|
402
+ case f
403
+ when Test::Unit::Failure
404
+ puts render_message(f.message)
405
+ when Test::Unit::Error
406
+ @errors << f
407
+ end
408
+ end
409
+
410
+ # Errors mean something in the test is broken, not just failed
411
+ unless @errors.empty?
412
+ @num = 0
413
+ print_underlined $messages[:error]
414
+ @errors.each do |e|
415
+ lines = e.long_display.to_a[1..-1]
416
+ puts "#{@num+=1}) #{lines.shift}"
417
+ lines.each{|l| puts "\t#{l}"}
418
+ end
419
+ end
420
+
421
+ end
422
+
423
+ if $debug
424
+ Tempfile.open(%w(rhc-chk. .log))do |file|
425
+ ObjectSpace.undefine_finalizer(file) # persist tempfile
426
+ file.write $debuginfo.to_yaml
427
+ puts
428
+ puts "Debugging information dumped to #{file.path}"
429
+ end
430
+ end
431
+ end
218
432
  end
219
433
 
220
- if @debug
221
- puts "remote_ssh_pubkey: #{remote_ssh_pubkey}"
222
- puts "local_ssh_pubkey: #{local_ssh_pubkey}"
223
- puts "local_derived_ssh_pubkey: #{local_derived_ssh_pubkey}"
434
+ Test::Unit::AutoRunner::RUNNERS[:console] = proc do |r|
435
+ CheckRunner
224
436
  end
225
437
 
226
- exit 0
438
+ $messages = YAML.load <<-EOF
439
+ ---
440
+ :started: Analyzing system
441
+ :passed: Congratulations, your system has passed all tests
442
+ :failed: Your system did not pass all of the tests
443
+ :error: Something went wrong, and not all tests completed
444
+ :no_derive: "We were unable to derive your public SSH key and compare it to the remote\n FIX: ???"
445
+ :no_connectivity: "Cannot connect to server, therefore most tests will not work\n FIX: Ensure that you are able to connect to %s"
446
+ :no_account: You must have an account on the server in order to test SSH key matches
447
+ :cant_connect: You need to be able to connect to the server in order to test authentication
448
+ :no_match_pub: "Local %s does not match remote pub key, SSH auth will not work\n FIX: Perhaps you should regenerate your public key, or run rhc-create-domain with -a to alter the remote key"
449
+ :_404: "The user %s does not have an account on this server\n FIX: Please ensure that you've entered the correct username"
450
+ :no_pubkey: We were unable to read your public SSH key to compare to %s
451
+ :_401: "Invalid user credentials for %s\n FIX: Please ensure you used the correct password"
452
+ :file_not_found: File %s does not exist, cannot check permissions
453
+ :_other_http: "There was an error communicating with the server: %s"
454
+ :bad_permissions: "File %s has incorrect permissions %s\n FIX: Permissions should match %s"
455
+ :no_keys_loaded: Either ssh-agent is not running or you do not have any keys loaded
456
+ :pubkey_not_loaded: Your public key is not loaded into a running ssh-agent
457
+ :cant_ssh: "Cannot SSH into your app: %s"
458
+ EOF
@@ -40,7 +40,7 @@ Create an OpenShift Express app.
40
40
  -n|--nogit Only create remote space, don't pull it locally
41
41
  -d|--debug Print Debug info
42
42
  -h|--help Show Usage info
43
- --no-dns Skip DNS check
43
+ --no-dns Skip DNS check. Must be used in combination with --nogit
44
44
  --config path Path of alternate config file
45
45
  --timeout # Timeout, in seconds, for connection
46
46
  --enable-jenkins [name] Indicates to create a Jenkins application (if not already available)
@@ -119,10 +119,16 @@ if !password
119
119
  end
120
120
 
121
121
  user_info = RHC::get_user_info(libra_server, opt['rhlogin'], password, @http, false)
122
+ app_info = user_info['app_info']
123
+
124
+ if app_info[opt['app']]
125
+ puts "An application named '#{opt['app']}' in namespace '#{user_info['user_info']['namespace']}' already exists"
126
+ exit 255
127
+ end
128
+
122
129
  jenkins_app_name = nil
123
130
  has_jenkins = false
124
131
  if opt['enable-jenkins']
125
- app_info = user_info['app_info']
126
132
  app_info.each do |app_name, app|
127
133
  if app['framework'] == 'jenkins-1.4'
128
134
  jenkins_app_name = app_name
@@ -181,12 +187,14 @@ end
181
187
 
182
188
  opt['repo'] = opt['app'] unless opt['repo']
183
189
 
184
- puts "
185
- Found a bug? Post to the forum and we'll get right on it.
186
- IRC: #openshift on freenode
187
- Forums: https://www.redhat.com/openshift/forums
188
-
189
- "
190
+ if @mydebug
191
+ puts "
192
+ Found a bug? Post to the forum and we'll get right on it.
193
+ IRC: #openshift on freenode
194
+ Forums: https://www.redhat.com/openshift/forums
195
+
196
+ "
197
+ end
190
198
 
191
199
  #
192
200
  # Confirm local git repo exists
@@ -216,14 +224,7 @@ unless opt['nogit']
216
224
  end
217
225
 
218
226
  if jenkins_app_name && !has_jenkins
219
- jenkins_no_git_message = "
220
-
221
- Note: There is a git repo for your Jenkins application '#{jenkins_app_name}'
222
- but it isn't being downloaded as part of this process. In most cases
223
- it isn't needed but you can always clone it later.
224
-
225
- "
226
- jenkins_app = RHC::create_app(libra_server, @http, user_info, jenkins_app_name, 'jenkins-1.4', opt['rhlogin'], password, nil, false, true, jenkins_no_git_message)
227
+ jenkins_app = RHC::create_app(libra_server, @http, user_info, jenkins_app_name, 'jenkins-1.4', opt['rhlogin'], password, nil, false, true, true)
227
228
  available = RHC::check_app_available(@http, jenkins_app[:app_name], jenkins_app[:fqdn], jenkins_app[:health_check_path], jenkins_app[:result], jenkins_app[:git_url], nil, true)
228
229
  if !available
229
230
  puts "Unable to access your new Jenkins application."
@@ -234,13 +235,10 @@ end
234
235
  #
235
236
  # Create remote application space
236
237
  #
237
- main_app = RHC::create_app(libra_server, @http, user_info, opt['app'], opt['type'], opt['rhlogin'], password, opt['repo'], opt['no-dns'], opt['nogit'])
238
+ main_app = RHC::create_app(libra_server, @http, user_info, opt['app'], opt['type'], opt['rhlogin'], password, opt['repo'], opt['no-dns'], opt['nogit'], false)
238
239
  if jenkins_app_name
239
- puts "
240
- Now embedding the jenkins client into '#{opt['app']}'...
241
-
242
- "
243
- RHC::ctl_app(libra_server, @http, opt['app'], opt['rhlogin'], password, 'configure', true, 'jenkins-client-1.4')
240
+ puts "Now embedding the jenkins client into '#{opt['app']}'..."
241
+ RHC::ctl_app(libra_server, @http, opt['app'], opt['rhlogin'], password, 'configure', true, 'jenkins-client-1.4', nil, false)
244
242
  end
245
243
 
246
244
  unless opt['no-dns']
@@ -249,4 +247,4 @@ unless opt['no-dns']
249
247
  puts "Unable to access your new application."
250
248
  exit 1
251
249
  end
252
- end
250
+ end
@@ -35,7 +35,7 @@ Control an OpenShift express app
35
35
  -a|--app application Application name (alphanumeric) (required)
36
36
  -l|--rhlogin rhlogin Red Hat login (RHN or OpenShift login with OpenShift Express access) (#{rhlogin})
37
37
  -p|--password password RHLogin password (optional, will prompt)
38
- -c|--command command (start|stop|force-stop|restart|reload|status|destroy|add-alias|remove-alias)
38
+ -c|--command command (start|stop|force-stop|restart|reload|status|destroy|tidy|add-alias|remove-alias)
39
39
  -L|--embedded-list List supported embedded cartridges
40
40
  -e|--embed (add|remove|stop|start|restart|status|reload)-$cartridge eg: add-mysql-5.1
41
41
  -b|--bypass Bypass warnings
@@ -123,14 +123,14 @@ unless opt["embed"] or opt["command"]
123
123
  end
124
124
 
125
125
  if opt["command"]
126
- unless opt["command"] =~ /^(start|stop|force-stop|restart|reload|status|destroy|add-alias|remove-alias)$/
127
- puts "Invalid command '#{opt["command"]}' specified. Valid commands are (start|stop|force-stop|restart|reload|status|destroy|add-alias|remove-alias)"
126
+ unless opt["command"] =~ /^(start|stop|force-stop|restart|reload|status|destroy|tidy|add-alias|remove-alias)$/
127
+ puts "Invalid command '#{opt["command"]}' specified. Valid commands are (start|stop|force-stop|restart|reload|status|destroy|tidy|add-alias|remove-alias)"
128
128
  p_usage
129
129
  end
130
130
  elsif opt["embed"]
131
131
  action = opt['embed'].split('-')[0]
132
132
  unless action =~ /^(add|remove|start|stop|restart|status|reload)$/
133
- puts "Invalid embed action '#{action}' specified. Valid embed actions are (add|remove|start|stop|restart|status|reload|add-alias|remove-alias)"
133
+ puts "Invalid embed action '#{action}' specified. Valid embed actions are (add|remove|start|stop|restart|status|reload)"
134
134
  p_usage
135
135
  end
136
136
  end
@@ -165,10 +165,15 @@ This is NOT reversible, all remote data for this application will be removed.
165
165
  WARNING
166
166
 
167
167
  print "Do you want to destroy this application (y/n): "
168
- agree = gets.chomp
169
- if agree != 'y'
170
- puts "Destroy aborted"
171
- exit 217
168
+ begin
169
+ agree = gets.chomp
170
+ if agree != 'y'
171
+ puts "\n"
172
+ exit 217
173
+ end
174
+ rescue Interrupt
175
+ puts "\n"
176
+ exit 217
172
177
  end
173
178
  end
174
179
 
@@ -42,6 +42,13 @@ module RHC
42
42
  @mydebug = false
43
43
  broker_version = "?.?.?"
44
44
  api_version = "?.?.?"
45
+
46
+ # reset lines
47
+ # \r moves the cursor to the beginning of line
48
+ # ANSI escape code to clear line from cursor to end of line
49
+ # "\e" is an alternative to "\033"
50
+ # cf. http://en.wikipedia.org/wiki/ANSI_escape_code
51
+ CLEAR_LINE = "\r" + "\e[0K"
45
52
 
46
53
  DEBUG_INGORE_KEYS = {
47
54
  'result' => nil,
@@ -276,7 +283,8 @@ module RHC
276
283
  end
277
284
  exit_code = 1
278
285
  if response.content_type == 'application/json'
279
- puts "JSON response:"
286
+ print "JSON response:"
287
+ $stdout.flush
280
288
  begin
281
289
  json_resp = JSON.parse(response.body)
282
290
  exit_code = print_json_body(json_resp)
@@ -301,7 +309,8 @@ module RHC
301
309
 
302
310
  def self.print_response_success(json_resp, print_result=false)
303
311
  if @mydebug
304
- puts "Response from server:"
312
+ print "Response from server:"
313
+ $stdout.flush
305
314
  print_json_body(json_resp, print_result)
306
315
  elsif print_result
307
316
  print_json_body(json_resp)
@@ -353,8 +362,8 @@ module RHC
353
362
  return resp.any?
354
363
  end
355
364
 
356
- def self.create_app(libra_server, net_http, user_info, app_name, app_type, rhlogin, password, repo_dir=nil, no_dns=false, no_git=false, no_git_message=nil)
357
- puts "Attempting to create remote application space: #{app_name}"
365
+ def self.create_app(libra_server, net_http, user_info, app_name, app_type, rhlogin, password, repo_dir=nil, no_dns=false, no_git=false, is_embedded_jenkins=false)
366
+ puts "Creating application: #{app_name}"
358
367
 
359
368
  data = {:cartridge => app_type,
360
369
  :action => 'configure',
@@ -412,11 +421,17 @@ module RHC
412
421
  while loop < MAX_RETRIES && !hostexist?(fqdn)
413
422
  sleep sleep_time
414
423
  loop+=1
415
- puts " retry # #{loop} - Waiting for DNS: #{fqdn}"
424
+ print CLEAR_LINE + " retry # #{loop} - Waiting for DNS: #{fqdn}"
425
+ $stdout.flush
416
426
  sleep_time = delay(sleep_time)
417
427
  end
418
428
  end
419
429
 
430
+ # if we have executed print statements, then move to the next line
431
+ if loop > 0
432
+ puts
433
+ end
434
+
420
435
  # If the hostname couldn't be resolved, print out the git URL
421
436
  # and exit cleanly. This will help solve issues where DNS times
422
437
  # out in APAC, etc on resolution.
@@ -461,7 +476,7 @@ WARNING
461
476
  git_url = "ssh://#{app_uuid}@#{app_name}-#{namespace}.#{rhc_domain}/~/git/#{app_name}.git/"
462
477
 
463
478
  unless no_git
464
- puts "Pulling new repo down"
479
+ puts "Pulling new repo down" if @mydebug
465
480
 
466
481
  puts "git clone --quiet #{git_url} #{repo_dir}" if @mydebug
467
482
  quiet = (@mydebug ? ' ' : '--quiet ')
@@ -472,8 +487,17 @@ WARNING
472
487
  exit 216
473
488
  end
474
489
  else
475
- if no_git_message
476
- puts no_git_message
490
+ if is_embedded_jenkins
491
+ # if this is a jenkins client application to be embedded,
492
+ # then print this message only in debug mode
493
+ if @mydebug
494
+ puts "
495
+ Note: There is a git repo for your Jenkins application '#{app_name}'
496
+ but it isn't being downloaded as part of this process. In most cases
497
+ it isn't needed but you can always clone it later.
498
+
499
+ "
500
+ end
477
501
  else
478
502
  puts <<IMPORTANT
479
503
 
@@ -514,51 +538,43 @@ IMPORTANT
514
538
  #
515
539
  sleep_time = 2
516
540
  attempt = 0
517
- puts "Confirming application '#{app_name}' is available"
541
+ puts "Confirming application '#{app_name}' is available" if @mydebug
518
542
  while attempt < MAX_RETRIES
519
543
  attempt += 1
520
- puts " Attempt # #{attempt}"
544
+ if @mydebug
545
+ puts " Attempt # #{attempt}"
546
+ else
547
+ print CLEAR_LINE + "Confirming application '#{app_name}' is available: Attempt # #{attempt}"
548
+ end
549
+ $stdout.flush
521
550
  url = URI.parse("http://#{fqdn}/#{health_check_path}")
551
+
552
+ sleep(2.0)
522
553
  begin
523
554
  response = net_http.get_response(url)
524
555
  rescue Exception => e
525
556
  response = nil
526
557
  end
527
558
  if !response.nil? && response.code == "200" && response.body[0,1] == "1"
528
- puts <<LOOKSGOOD
529
-
530
- Success! Your application '#{app_name}' is now published here:
531
-
532
- http://#{fqdn}/
533
-
534
- The remote repository is located here:
535
-
536
- #{git_url}
537
-
538
- LOOKSGOOD
539
- unless no_git
540
- puts <<LOOKSGOOD
541
- To make changes to '#{app_name}', commit to #{repo_dir}/.
542
- LOOKSGOOD
543
- else
544
- puts <<LOOKSGOOD
559
+ puts CLEAR_LINE + "Confirming application '#{app_name}' is available: Success!"
560
+ puts ""
561
+ puts "#{app_name} published: http://#{fqdn}/"
562
+ puts "git url: #{git_url}"
563
+
564
+ if @mydebug
565
+ unless no_git
566
+ puts "To make changes to '#{app_name}', commit to #{repo_dir}/."
567
+ else
568
+ puts <<LOOKSGOOD
545
569
  To make changes to '#{app_name}', you must first clone it with:
546
-
547
- git clone #{git_url}
548
-
549
- LOOKSGOOD
550
- puts <<LOOKSGOOD
551
- Then run 'git push' to update your OpenShift Express space.
570
+ git clone #{git_url}
552
571
 
553
572
  LOOKSGOOD
573
+ puts "Then run 'git push' to update your OpenShift Express space."
574
+ end
554
575
  end
555
576
  if result && !result.empty?
556
-
557
- puts <<LOOKSGOOD
558
-
559
- #{result}
560
-
561
- LOOKSGOOD
577
+ puts "#{result}"
562
578
  end
563
579
  return true
564
580
  end
@@ -566,8 +582,7 @@ LOOKSGOOD
566
582
  puts "Server responded with #{response.code}"
567
583
  puts response.body unless response.code == '503'
568
584
  end
569
- puts
570
- puts " sleeping #{sleep_time} seconds"
585
+ puts " sleeping #{sleep_time} seconds" if @mydebug
571
586
  sleep sleep_time
572
587
  sleep_time = delay(sleep_time)
573
588
  end
@@ -584,7 +599,7 @@ LOOKSGOOD
584
599
  http_post(net_http, url, json_data, password)
585
600
  end
586
601
 
587
- def self.ctl_app(libra_server, net_http, app_name, rhlogin, password, action, embedded=false, framework=nil, server_alias=nil)
602
+ def self.ctl_app(libra_server, net_http, app_name, rhlogin, password, action, embedded=false, framework=nil, server_alias=nil, print_result=true)
588
603
  data = {:action => action,
589
604
  :app_name => app_name,
590
605
  :rhlogin => rhlogin
@@ -610,8 +625,8 @@ LOOKSGOOD
610
625
  response = http_post(net_http, url, json_data, password)
611
626
 
612
627
  if response.code == '200'
613
- json_resp = JSON.parse(response.body)
614
- print_response_success(json_resp, true)
628
+ json_resp = JSON.parse(response.body)
629
+ print_response_success(json_resp, print_result || @mydebug)
615
630
  else
616
631
  print_response_err(response)
617
632
  end
@@ -662,8 +677,11 @@ end
662
677
  # Check for proxy environment
663
678
  #
664
679
  if ENV['http_proxy']
665
- host, port = ENV['http_proxy'].split(':')
666
- @http = Net::HTTP::Proxy(host, port)
680
+ if ENV['http_proxy']!~/^(\w+):\/\// then
681
+ ENV['http_proxy']="http://" + ENV['http_proxy']
682
+ end
683
+ proxy_uri=URI.parse(ENV['http_proxy'])
684
+ @http = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
667
685
  else
668
686
  @http = Net::HTTP
669
687
  end
@@ -761,4 +779,4 @@ def get_kpfile(kfile, check_exists=true)
761
779
  kfile_not_found
762
780
  end
763
781
  return kpfile
764
- end
782
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rhc
3
3
  version: !ruby/object:Gem::Version
4
- hash: 327
4
+ hash: 371
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 81
9
- - 14
10
- version: 0.81.14
8
+ - 82
9
+ - 18
10
+ version: 0.82.18
11
11
  platform: ruby
12
12
  authors:
13
13
  - Red Hat
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-11-10 00:00:00 Z
18
+ date: 2011-12-01 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: json_pure
@@ -61,13 +61,13 @@ extra_rdoc_files: []
61
61
 
62
62
  files:
63
63
  - lib/rhc-common.rb
64
- - bin/rhc-ctl-app
65
- - bin/rhc-tail-files
66
64
  - bin/rhc-create-app
67
65
  - bin/rhc-chk
68
- - bin/rhc-snapshot
69
- - bin/rhc-create-domain
70
66
  - bin/rhc-user-info
67
+ - bin/rhc-create-domain
68
+ - bin/rhc-snapshot
69
+ - bin/rhc-ctl-app
70
+ - bin/rhc-tail-files
71
71
  - conf/express.conf
72
72
  - LICENSE
73
73
  - README
@@ -101,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
101
101
  requirements: []
102
102
 
103
103
  rubyforge_project:
104
- rubygems_version: 1.7.2
104
+ rubygems_version: 1.8.11
105
105
  signing_key:
106
106
  specification_version: 3
107
107
  summary: OpenShift Express Client Tools