rhc 0.92.11 → 0.93.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/README.md +1 -9
  2. data/Rakefile +1 -55
  3. data/bin/rhc +31 -1
  4. data/bin/rhc-app +62 -127
  5. data/bin/rhc-chk +6 -7
  6. data/bin/rhc-create-app +8 -8
  7. data/bin/rhc-create-domain +6 -86
  8. data/bin/rhc-ctl-app +3 -3
  9. data/bin/rhc-ctl-domain +4 -4
  10. data/bin/rhc-domain +16 -18
  11. data/bin/rhc-domain-info +3 -3
  12. data/bin/rhc-port-forward +127 -24
  13. data/bin/rhc-snapshot +7 -46
  14. data/bin/rhc-sshkey +13 -79
  15. data/bin/rhc-tail-files +16 -8
  16. data/lib/rhc-common.rb +406 -230
  17. data/lib/rhc-rest.rb +3 -3
  18. data/lib/rhc-rest/client.rb +1 -1
  19. data/lib/rhc-rest/domain.rb +1 -1
  20. data/lib/rhc.rb +20 -0
  21. data/lib/rhc/cli.rb +38 -0
  22. data/lib/rhc/client.rb +15 -0
  23. data/lib/rhc/commands.rb +32 -0
  24. data/lib/rhc/commands/base.rb +67 -0
  25. data/lib/rhc/commands/server.rb +24 -0
  26. data/lib/rhc/config.rb +141 -0
  27. data/lib/rhc/core_ext.rb +15 -0
  28. data/lib/rhc/helpers.rb +142 -0
  29. data/lib/rhc/json.rb +52 -0
  30. data/lib/rhc/targz.rb +46 -0
  31. data/lib/rhc/vendor/okjson.rb +600 -0
  32. data/lib/rhc/vendor/zliby.rb +628 -0
  33. data/lib/rhc/wizard.rb +579 -0
  34. data/spec/rhc/assets/foo.txt +1 -0
  35. data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
  36. data/spec/rhc/assets/targz_sample.tar.gz +0 -0
  37. data/spec/rhc/cli_spec.rb +24 -0
  38. data/spec/rhc/command_spec.rb +88 -0
  39. data/spec/rhc/commands/server_spec.rb +39 -0
  40. data/spec/rhc/helpers_spec.rb +171 -0
  41. data/spec/rhc/json_spec.rb +30 -0
  42. data/spec/rhc/targz_spec.rb +42 -0
  43. data/spec/rhc/wizard_spec.rb +426 -0
  44. data/spec/spec_helper.rb +192 -0
  45. data/test/functional/application_test.rb +71 -0
  46. data/test/functional/domain_test.rb +123 -0
  47. data/test/functional/test_credentials.rb +5 -0
  48. data/test/sample-usage.rb +122 -0
  49. data/test/support/server.rb +14 -0
  50. data/test/support/testcase.rb +3 -0
  51. data/test/test_helper.rb +4 -0
  52. data/test/unit/command_test.rb +19 -0
  53. metadata +181 -29
  54. data/ext/mkrf_conf.rb +0 -58
  55. data/lib/rhc +0 -115
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # OpenShift Command Line Tools (RHC)
1
+ # OpenShift Command Line Tools (RHC) [![Build Status](https://secure.travis-ci.org/openshift/os-client-tools.png)](http://travis-ci.org/openshift/os-client-tools)
2
2
 
3
3
  The OpenShift command line tools allow you to manage your OpenShift
4
4
  applications from the command line. The [Getting Started
@@ -19,7 +19,6 @@ DEPENDENCIES:
19
19
  * openssh-clients
20
20
  * ruby (1.8.7 or later)
21
21
  * rubygems
22
- * json_pure gem (native json is fine too)
23
22
  * parseconfig gem
24
23
 
25
24
  Step 1: Create a domain to under which your applications will live:
@@ -66,10 +65,3 @@ Installing git from MacPorts/HomeBrew/Fink/etc requires Xcode.
66
65
  Now obtain the client code, either via 'git clone' as above
67
66
  or via the rhc gem.
68
67
 
69
- json_pure gem:
70
- The client tools also make use of JSON as the data set for
71
- I/O, and therefore needs the json ruby gem. Unless you have
72
- Xcode installed, you will need to install json_pure, which
73
- is the 100% ruby version of the JSON gem. If you have Xcode,
74
- you can elect to install either json_pure or the native
75
- json gem.
data/Rakefile CHANGED
@@ -2,59 +2,5 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'rake'
5
- require 'rake/clean'
6
- require 'rake/testtask'
7
5
 
8
- begin
9
- require 'rubygems/package_task'
10
- rescue LoadError
11
- require 'rake/gempackagetask'
12
- rake_gempackage = true
13
- end
14
-
15
- task(:default).clear
16
- task :default => [:package]
17
-
18
- # Create the gem specification for packaging
19
- spec = Gem::Specification.new do |s|
20
- s.name = %q{rhc}
21
- s.version = /(Version: )(.*)/.match(File.read("client.spec"))[2]
22
- s.author = "Red Hat"
23
- s.email = %q{openshift@redhat.com}
24
- s.summary = %q{OpenShift Client Tools}
25
- s.homepage = %q{https://openshift.redhat.com/app/express}
26
- s.description = %q{The client tools for the OpenShift platform that allow for application management.}
27
- s.files = FileList['lib/**/*.rb', 'lib/rhc', 'bin/*', 'conf/*'].to_a
28
- s.files += %w(LICENSE COPYRIGHT README.md Rakefile)
29
- s.executables = ['rhc', 'rhc-domain', 'rhc-app', 'rhc-sshkey', 'rhc-chk', 'rhc-create-app', 'rhc-create-domain', 'rhc-ctl-domain', 'rhc-ctl-app', 'rhc-snapshot', 'rhc-domain-info', 'rhc-user-info', 'rhc-tail-files', 'rhc-port-forward']
30
- s.add_dependency('parseconfig')
31
- s.add_dependency("rest-client")
32
- # This does not need to be added as a dep for the RPM since it is only needed in extension installation
33
- s.add_dependency('rake')
34
-
35
- # Adding install time dependencies for
36
- # - test-unit (Ruby 1.9)
37
- # - json_pure (Ruby (Ruby 1.8.6, Windows, Mac) / json (everything else)
38
- # http://en.wikibooks.org/wiki/Ruby_Programming/RubyGems
39
- s.extensions << 'ext/mkrf_conf.rb'
40
- end
41
-
42
- # Define a :package task that bundles the gem
43
- if rake_gempackage
44
- Rake::GemPackageTask.new(spec) do |pkg, args|
45
- pkg.need_tar = false
46
- end
47
- else
48
- Gem::PackageTask.new(spec) do |pkg, args|
49
- pkg.need_tar = false
50
- end
51
- end
52
-
53
- # Add the 'pkg' directory to the clean task
54
- CLEAN.include("pkg")
55
-
56
- Rake::TestTask.new(:test) do |t|
57
- t.libs << 'test'
58
- t.test_files = FileList['test/**/*_test.rb']
59
- t.verbose = true
60
- end
6
+ Dir.glob('tasks/*.rake').each { |r| import r }
data/bin/rhc CHANGED
@@ -2,6 +2,10 @@
2
2
  #
3
3
  # print help
4
4
  #
5
+
6
+ # Require rhc-common for wizard invocation
7
+ require 'rhc-common'
8
+
5
9
  def p_usage(exit_code = 255)
6
10
  puts <<USAGE
7
11
 
@@ -13,10 +17,12 @@ List of resources
13
17
  app Manage applications within the rhcloud account.
14
18
  sshkey Manage multiple keys for the registered rhcloud user.
15
19
  port-forward Forward remote ports to the workstation
20
+ server Display information about the status of the service.
21
+ setup Run the setup wizard to configure your account.
16
22
 
17
23
  See 'rhc <resource> --help' for more applicable commands and argumments on a specific resource.
18
-
19
24
  USAGE
25
+
20
26
  exit exit_code
21
27
  end
22
28
 
@@ -31,6 +37,9 @@ def get_args
31
37
  args
32
38
  end
33
39
 
40
+
41
+ wizard_run = default_setup_wizard unless ARGV.include?('--noprompt')
42
+
34
43
  case ARGV[0]
35
44
  when "domain"
36
45
  system("rhc-domain #{get_args} 2>&1")
@@ -44,6 +53,20 @@ when "sshkey"
44
53
  when "port-forward"
45
54
  system("rhc-port-forward #{get_args} 2>&1")
46
55
  retcode = $?.exitstatus
56
+ when "server"
57
+ begin
58
+ require 'rhc/cli'
59
+ RHC::CLI.start(ARGV)
60
+ retcode = 0
61
+ rescue SystemExit => e
62
+ retcode = e.status
63
+ end
64
+ when "setup"
65
+ exit 0 if wizard_run
66
+ w = RHC::RerunWizard.new(RHC::Config.local_config_path)
67
+ success = w.run
68
+ retcode = 0
69
+ retcode = 1 unless success
47
70
  when "-h", "--help", "help", nil
48
71
  p_usage 0
49
72
  else
@@ -51,4 +74,11 @@ else
51
74
  p_usage
52
75
  end
53
76
 
77
+ if retcode == nil
78
+ retcode = 1
79
+
80
+ # return codes for uncaught signals are 128 + the signal code
81
+ retcode = 128 + $?.termsig if $?.signaled? and !$?.termsig.nil?
82
+ end
83
+
54
84
  exit retcode
data/bin/rhc-app CHANGED
@@ -10,7 +10,7 @@ $embed_mapper = { 'add' => 'configure', 'remove' => 'deconfigure' }
10
10
  def p_usage(exit_code = 255)
11
11
  libra_server = get_var('libra_server')
12
12
  rhlogin = get_var('default_rhlogin') ? "Default: #{get_var('default_rhlogin')}" : "required"
13
- type_keys = RHC::get_cartridge_listing(nil, ', ', libra_server, @http, 'standalone', false)
13
+ type_keys = RHC::get_cartridge_listing(nil, ', ', libra_server, RHC::Config.default_proxy, 'standalone', false)
14
14
  puts <<USAGE
15
15
 
16
16
  Usage: rhc app (<command> | cartridge <cartridge-action> | --help) [<args>]
@@ -29,7 +29,7 @@ List of commands
29
29
  tidy Garbage collects the git repo and empties log/tmp dirs
30
30
  add-alias Add a custom domain name for the application
31
31
  remove-alias Remove a custom domain name for the application
32
- threaddump Trigger a thread dump for jbossas applications
32
+ threaddump Trigger a thread dump for jbossas, jbosseap, and ruby applications
33
33
  tail Tail the logs of an application
34
34
  snapshot [save|restore] Saves/Restores an application snapshot to/from a tarball at the location specified using --filepath (default: ./$APPNAME.tar.gz)
35
35
  cartridge <action> Manage an embedded cartridge
@@ -70,8 +70,9 @@ end
70
70
 
71
71
 
72
72
  def validate_args(val_type=true, val_cartridge=false, val_timeout=true)
73
+
73
74
  # If provided a config path, check it
74
- check_cpath($opt)
75
+ RHC::Config.check_cpath($opt)
75
76
 
76
77
  # Pull in configs from files
77
78
  $libra_server = get_var('libra_server')
@@ -92,7 +93,7 @@ def validate_args(val_type=true, val_cartridge=false, val_timeout=true)
92
93
  p_usage
93
94
  end
94
95
 
95
- debug = $opt["debug"] ? true : false
96
+ debug = $opt.has_key? 'debug'
96
97
  RHC::debug(debug)
97
98
 
98
99
  RHC::timeout($opt["timeout"], get_var('timeout')) if val_timeout
@@ -104,7 +105,7 @@ end
104
105
  def create_app
105
106
  validate_args
106
107
 
107
- user_info = RHC::get_user_info($libra_server, $opt['rhlogin'], $password, @http, false)
108
+ user_info = RHC::get_user_info($libra_server, $opt['rhlogin'], $password, RHC::Config.default_proxy, false)
108
109
  app_info = user_info['app_info']
109
110
 
110
111
  if app_info[$opt['app']]
@@ -212,8 +213,8 @@ currently being created: '#{$opt['app']}'
212
213
  end
213
214
 
214
215
  if jenkins_app_name && !has_jenkins
215
- jenkins_app = RHC::create_app($libra_server, @http, user_info, jenkins_app_name, 'jenkins-1.4', $opt['rhlogin'], $password, nil, false, true, true)
216
- 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)
216
+ jenkins_app = RHC::create_app($libra_server, RHC::Config.default_proxy, user_info, jenkins_app_name, 'jenkins-1.4', $opt['rhlogin'], $password, nil, false, true, true)
217
+ available = RHC::check_app_available(RHC::Config.default_proxy, jenkins_app[:app_name], jenkins_app[:fqdn], jenkins_app[:health_check_path], jenkins_app[:result], jenkins_app[:git_url], nil, true)
217
218
  if !available
218
219
  puts "Unable to access your new Jenkins application."
219
220
  exit 1
@@ -223,10 +224,10 @@ currently being created: '#{$opt['app']}'
223
224
  #
224
225
  # Create remote application space
225
226
  #
226
- 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, $opt['gear-size'], $opt['scaling'])
227
+ main_app = RHC::create_app($libra_server, RHC::Config.default_proxy, user_info, $opt['app'], $opt['type'], $opt['rhlogin'], $password, $opt['repo'], $opt['no-dns'], $opt['nogit'], false, $opt['gear-size'], $opt['scaling'])
227
228
  if jenkins_app_name
228
229
  puts "Now embedding the jenkins client into '#{$opt['app']}'..."
229
- RHC::ctl_app($libra_server, @http, $opt['app'], $opt['rhlogin'], $password, 'configure', true, 'jenkins-client-1.4', nil, false)
230
+ RHC::ctl_app($libra_server, RHC::Config.default_proxy, $opt['app'], $opt['rhlogin'], $password, 'configure', true, 'jenkins-client-1.4', nil, false)
230
231
  end
231
232
 
232
233
  if $opt['no-dns']
@@ -238,7 +239,7 @@ currently being created: '#{$opt['app']}'
238
239
  puts "#{main_app[:result]}"
239
240
  end
240
241
  else
241
- available = RHC::check_app_available(@http, main_app[:app_name], main_app[:fqdn], main_app[:health_check_path], main_app[:result], main_app[:git_url], $opt['repo'], $opt['nogit'])
242
+ available = RHC::check_app_available(RHC::Config.default_proxy, main_app[:app_name], main_app[:fqdn], main_app[:health_check_path], main_app[:result], main_app[:git_url], $opt['repo'], $opt['nogit'])
242
243
  if !available
243
244
  puts "Unable to access your new application."
244
245
  exit 1
@@ -247,9 +248,19 @@ currently being created: '#{$opt['app']}'
247
248
 
248
249
  end
249
250
 
251
+ def get_args(l)
252
+ l.shift
253
+ args = ""
254
+ l.each do|a|
255
+ if (a.to_s.strip.length == 0 || a.to_s.strip.match(/\s/) ); a = "'#{a}'" end
256
+ args += " #{a}"
257
+ end
258
+ args
259
+ end
260
+
250
261
  def show_app
251
262
  validate_args(false)
252
- user_info = RHC::get_user_info($libra_server, $opt['rhlogin'], $password, @http, true)
263
+ user_info = RHC::get_user_info($libra_server, $opt['rhlogin'], $password, RHC::Config.default_proxy, true)
253
264
 
254
265
  app_found = false
255
266
  unless user_info['app_info'].empty?
@@ -333,7 +344,7 @@ WARNING
333
344
  end
334
345
  end
335
346
 
336
- RHC::ctl_app($libra_server, @http, $opt['app'], $opt['rhlogin'], $password, command, false, nil, $opt['alias'])
347
+ RHC::ctl_app($libra_server, RHC::Config.default_proxy, $opt['app'], $opt['rhlogin'], $password, command, false, nil, $opt['alias'])
337
348
  end
338
349
 
339
350
  def control_cartridge(command)
@@ -343,7 +354,7 @@ def control_cartridge(command)
343
354
  command = $embed_mapper[command] if $embed_mapper[command]
344
355
  framework = $opt['cartridge']
345
356
 
346
- RHC::ctl_app($libra_server, @http, $opt['app'], $opt['rhlogin'], $password, command, true, framework, $opt['alias'])
357
+ RHC::ctl_app($libra_server, RHC::Config.default_proxy, $opt['app'], $opt['rhlogin'], $password, command, true, framework, $opt['alias'])
347
358
  end
348
359
 
349
360
  def show_embedded_list
@@ -351,7 +362,7 @@ def show_embedded_list
351
362
  puts ""
352
363
  puts "List of supported embedded cartridges:"
353
364
  puts ""
354
- type_keys = RHC::get_cartridge_listing(nil, ', ', libra_server, @http, 'embedded', false)
365
+ type_keys = RHC::get_cartridge_listing(nil, ', ', libra_server, RHC::Config.default_proxy, 'embedded', false)
355
366
  puts type_keys
356
367
  puts ""
357
368
  exit 255
@@ -359,8 +370,8 @@ end
359
370
 
360
371
  def save_or_restore_snapshot(command)
361
372
  validate_args(false, false, true)
362
-
363
- user_info = RHC::get_user_info($libra_server, $opt['rhlogin'], $password, @http, @mydebug, false)
373
+
374
+ user_info = RHC::get_user_info($libra_server, $opt['rhlogin'], $password, RHC::Config.default_proxy, @mydebug, false)
364
375
 
365
376
  app = $opt['app']
366
377
  $opt['filepath'] = "#{$opt['app']}.tar.gz" unless $opt['filepath']
@@ -376,94 +387,17 @@ def save_or_restore_snapshot(command)
376
387
  app_uuid = user_info['app_info'][app]['uuid']
377
388
  namespace = user_info['user_info']['domains'][0]['namespace']
378
389
  rhc_domain = user_info['user_info']['rhc_domain']
390
+
379
391
  if command == 'save'
380
- ssh_cmd = "ssh #{app_uuid}@#{app}-#{namespace}.#{rhc_domain} 'snapshot' > #{$opt['filepath']}"
381
- puts "Pulling down a snapshot to #{$opt['filepath']}"
382
- else
383
- if File.exists? $opt['filepath']
384
- `tar -tf #{$opt['filepath']} './*/#{app}'`
385
- if $?.exitstatus != 0
386
- puts "Archive at #{$opt['filepath']} does not contain the target application: ./*/#{app}"
387
- puts "If you created this archive rather than exported with 'rhc app snapshot', be sure"
388
- puts "the directory structure inside the archive starts with ./<app_uuid>/"
389
- puts "i.e.: tar -czvf <app_name>.tar.gz ./<app_uuid>/"
390
- exit 255
391
- else
392
- `tar -tf #{$opt['filepath']} './*/git'`
393
- include_git = $?.exitstatus == 0
394
- ssh_cmd = "cat #{$opt['filepath']} | ssh #{app_uuid}@#{app}-#{namespace}.#{rhc_domain} 'restore#{include_git ? ' INCLUDE_GIT' : ''}'"
395
- puts "Restoring from snapshot #{$opt['filepath']}"
396
- end
397
- else
398
- puts "Archive not found: #{$opt['filepath']} - you may specify a path to the archive using the -f option"
399
- exit 255
400
- end
401
- end
402
-
403
- puts
404
- puts ssh_cmd if @mydebug
405
- output = `#{ssh_cmd}`
406
- puts
407
- if $?.exitstatus != 0
408
- puts output
409
- puts
410
- if command == 'save'
411
- puts "Error in trying to save snapshot. You can try to save manually by running:"
392
+ status = RHC.snapshot_create rhc_domain, namespace, app, app_uuid, $opt['filepath'], @mydebug
393
+ exit status if ! status
412
394
  else
413
- puts "Error in trying to restore application from snapshot. You can try to restore manually by running:"
395
+ status = RHC.snapshot_restore rhc_domain, namespace, app, app_uuid, $opt['filepath'], @mydebug
396
+ exit status if ! status
414
397
  end
415
- puts
416
- puts ssh_cmd
417
- puts
418
- exit 1
419
- end
420
- puts output if command == 'restore' && @mydebug
421
- end
422
-
423
- def show_logs
424
- validate_args(false, false, true)
425
398
 
426
- user_info = RHC::get_user_info($libra_server, $opt['rhlogin'], $password, @http, false)
427
- app = $opt['app']
428
-
429
- unless user_info['app_info'][app]
430
- puts
431
- puts "Could not find app '#{$opt['app']}'. Please run 'rhc domain show' to get a list"
432
- puts "of your current running applications"
433
- puts
434
- exit 101
435
- end
436
-
437
- $opt['filepath'] = "#{$opt['app']}/logs/*" unless $opt['filepath']
438
- file_glob = "#{$opt['filepath']}"
439
- app_uuid = user_info['app_info'][app]['uuid']
440
- namespace = user_info['user_info']['domains'][0]['namespace']
441
- rhc_domain = user_info['user_info']['rhc_domain']
442
-
443
- # -t to force PTY and avoid daemons
444
- # Red Hat OpenShift: https://bugzilla.redhat.com/show_bug.cgi?id=726646
445
- # OpenSSH https://bugzilla.mindrot.org/show_bug.cgi?id=396
446
- ssh_cmd = "ssh -t #{app_uuid}@#{app}-#{namespace}.#{rhc_domain} 'tail#{$opt['opts'] ? ' --opts ' + Base64::encode64($opt['opts']).chomp : ''} #{file_glob}'"
447
-
448
- puts "Attempting to tail files: #{file_glob}"
449
- puts "Use ctl + c to stop"
450
- puts
451
- puts ssh_cmd if @mydebug
452
- begin
453
- exec ssh_cmd
454
- rescue SystemCallError
455
- puts
456
- puts "Error in trying to tail files. You can tail manually by running:"
457
- puts
458
- puts ssh_cmd
459
- puts
460
- exit 1
461
- end
462
- # this should never happen
463
- exit 1
464
399
  end
465
400
 
466
-
467
401
  begin
468
402
  argv_c = ARGV.clone
469
403
 
@@ -561,37 +495,38 @@ end
561
495
  p_usage 0 if $opt["help"]
562
496
 
563
497
  case argv_c[0]
564
- when "create"
565
- create_app
566
- when "show"
567
- show_app
568
- when "start", "stop", "force-stop", "restart", "reload", "status", "tidy", "add-alias", "remove-alias", "threaddump", "destroy"
569
- control_app(argv_c[0])
570
- when "tail"
571
- show_logs
572
- when "snapshot"
573
- case argv_c[1]
574
- when "save", "restore"
575
- save_or_restore_snapshot(argv_c[1])
576
- else
577
- puts "Missing or invalid snapshot action!"
578
- p_usage
579
- end
580
- when "cartridge"
581
- case argv_c[1]
582
- when "add", "remove", "start", "stop", "restart", "status", "reload"
583
- control_cartridge(argv_c[1])
584
- when "list", nil
585
- show_embedded_list
498
+ when "create"
499
+ create_app
500
+ when "show"
501
+ show_app
502
+ when "start", "stop", "force-stop", "restart", "reload", "status", "tidy", "add-alias", "remove-alias", "threaddump", "destroy"
503
+ control_app(argv_c[0])
504
+ when "tail"
505
+ system("rhc-tail-files #{get_args argv_c} 2>&1")
506
+ exit $?.exitstatus
507
+ when "snapshot"
508
+ case argv_c[1]
509
+ when "save", "restore"
510
+ save_or_restore_snapshot(argv_c[1])
511
+ else
512
+ puts "Missing or invalid snapshot action!"
513
+ p_usage
514
+ end
515
+ when "cartridge"
516
+ case argv_c[1]
517
+ when "add", "remove", "start", "stop", "restart", "status", "reload"
518
+ control_cartridge(argv_c[1])
519
+ when "list", nil
520
+ show_embedded_list
521
+ else
522
+ puts "Missing or invalid cartridge action!"
523
+ p_usage
524
+ end
525
+ when "-h", "--help", "help", nil
526
+ p_usage 0
586
527
  else
587
- puts "Missing or invalid cartridge action!"
528
+ puts "Invalid command!"
588
529
  p_usage
589
- end
590
- when "-h", "--help", "help", nil
591
- p_usage 0
592
- else
593
- puts "Invalid command!"
594
- p_usage
595
530
  end
596
531
 
597
532
  exit 0