morpheus-cli 5.5.1.4 → 5.5.2

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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +25 -0
  4. data/lib/morpheus/api/archive_buckets_interface.rb +1 -1
  5. data/lib/morpheus/api/body_io.rb +22 -0
  6. data/lib/morpheus/api/catalog_item_types_interface.rb +5 -1
  7. data/lib/morpheus/api/clients_interface.rb +41 -0
  8. data/lib/morpheus/api/clouds_interface.rb +21 -0
  9. data/lib/morpheus/api/instances_interface.rb +8 -1
  10. data/lib/morpheus/api/integrations_interface.rb +30 -0
  11. data/lib/morpheus/api/library_instance_types_interface.rb +15 -3
  12. data/lib/morpheus/api/network_pool_server_types_interface.rb +9 -0
  13. data/lib/morpheus/api/plugins_interface.rb +22 -0
  14. data/lib/morpheus/api/roles_interface.rb +20 -1
  15. data/lib/morpheus/api/security_package_types_interface.rb +9 -0
  16. data/lib/morpheus/api/security_packages_interface.rb +9 -0
  17. data/lib/morpheus/api/security_scans_interface.rb +9 -0
  18. data/lib/morpheus/api/servers_interface.rb +17 -17
  19. data/lib/morpheus/api/storage_providers_interface.rb +1 -1
  20. data/lib/morpheus/api/virtual_images_interface.rb +1 -23
  21. data/lib/morpheus/cli/cli_command.rb +81 -7
  22. data/lib/morpheus/cli/commands/apps.rb +28 -2
  23. data/lib/morpheus/cli/commands/archives_command.rb +2 -2
  24. data/lib/morpheus/cli/commands/blueprints_command.rb +16 -0
  25. data/lib/morpheus/cli/commands/catalog_item_types_command.rb +34 -2
  26. data/lib/morpheus/cli/commands/clients_command.rb +338 -0
  27. data/lib/morpheus/cli/commands/clouds.rb +127 -1
  28. data/lib/morpheus/cli/commands/clusters.rb +42 -12
  29. data/lib/morpheus/cli/commands/curl_command.rb +114 -135
  30. data/lib/morpheus/cli/commands/hosts.rb +108 -11
  31. data/lib/morpheus/cli/commands/instances.rb +115 -14
  32. data/lib/morpheus/cli/commands/integrations_command.rb +215 -4
  33. data/lib/morpheus/cli/commands/invoices_command.rb +20 -11
  34. data/lib/morpheus/cli/commands/jobs_command.rb +299 -190
  35. data/lib/morpheus/cli/commands/library_cluster_layouts_command.rb +16 -2
  36. data/lib/morpheus/cli/commands/library_container_scripts_command.rb +14 -0
  37. data/lib/morpheus/cli/commands/library_container_templates_command.rb +131 -48
  38. data/lib/morpheus/cli/commands/library_container_types_command.rb +17 -4
  39. data/lib/morpheus/cli/commands/library_instance_types_command.rb +85 -7
  40. data/lib/morpheus/cli/commands/library_layouts_command.rb +32 -1
  41. data/lib/morpheus/cli/commands/library_option_lists_command.rb +30 -18
  42. data/lib/morpheus/cli/commands/library_option_types_command.rb +31 -14
  43. data/lib/morpheus/cli/commands/library_spec_templates_command.rb +14 -0
  44. data/lib/morpheus/cli/commands/library_upgrades_command.rb +2 -2
  45. data/lib/morpheus/cli/commands/network_pool_server_types.rb +20 -0
  46. data/lib/morpheus/cli/commands/network_pool_servers_command.rb +55 -158
  47. data/lib/morpheus/cli/commands/network_pools_command.rb +49 -23
  48. data/lib/morpheus/cli/commands/networks_command.rb +262 -45
  49. data/lib/morpheus/cli/commands/plugins.rb +213 -0
  50. data/lib/morpheus/cli/commands/price_sets_command.rb +40 -10
  51. data/lib/morpheus/cli/commands/prices_command.rb +17 -5
  52. data/lib/morpheus/cli/commands/processes_command.rb +2 -1
  53. data/lib/morpheus/cli/commands/remote.rb +7 -10
  54. data/lib/morpheus/cli/commands/roles.rb +924 -335
  55. data/lib/morpheus/cli/commands/search_command.rb +2 -0
  56. data/lib/morpheus/cli/commands/security_groups.rb +72 -84
  57. data/lib/morpheus/cli/commands/security_package_types.rb +32 -0
  58. data/lib/morpheus/cli/commands/security_packages.rb +84 -0
  59. data/lib/morpheus/cli/commands/security_scans.rb +107 -0
  60. data/lib/morpheus/cli/commands/service_plans_command.rb +16 -14
  61. data/lib/morpheus/cli/commands/subnets_command.rb +15 -1
  62. data/lib/morpheus/cli/commands/tasks.rb +34 -1
  63. data/lib/morpheus/cli/commands/tenants_command.rb +1 -1
  64. data/lib/morpheus/cli/commands/user_settings_command.rb +11 -2
  65. data/lib/morpheus/cli/commands/users.rb +50 -9
  66. data/lib/morpheus/cli/commands/virtual_images.rb +14 -0
  67. data/lib/morpheus/cli/commands/workflows.rb +14 -0
  68. data/lib/morpheus/cli/mixins/accounts_helper.rb +6 -5
  69. data/lib/morpheus/cli/mixins/infrastructure_helper.rb +79 -0
  70. data/lib/morpheus/cli/mixins/jobs_helper.rb +4 -5
  71. data/lib/morpheus/cli/mixins/library_helper.rb +2 -0
  72. data/lib/morpheus/cli/mixins/logs_helper.rb +3 -0
  73. data/lib/morpheus/cli/mixins/monitoring_helper.rb +1 -1
  74. data/lib/morpheus/cli/mixins/print_helper.rb +29 -4
  75. data/lib/morpheus/cli/mixins/provisioning_helper.rb +38 -9
  76. data/lib/morpheus/cli/mixins/rest_command.rb +106 -8
  77. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +6 -2
  78. data/lib/morpheus/cli/option_types.rb +94 -25
  79. data/lib/morpheus/cli/version.rb +1 -1
  80. data/lib/morpheus/formatters.rb +10 -1
  81. metadata +15 -2
@@ -79,6 +79,12 @@ class Morpheus::Cli::Apps
79
79
  opts.on('--status STATUS', "Filter by status.") do |val|
80
80
  params['status'] = (params['status'] || []) + val.to_s.split(',').collect {|s| s.strip }.select {|s| s != "" }
81
81
  end
82
+ opts.on('-l', '--labels LABEL', String, "Filter by labels, can match any of the values") do |val|
83
+ add_query_parameter(params, 'labels', parse_labels(val))
84
+ end
85
+ opts.on('--all-labels LABEL', String, "Filter by labels, must match all of the values") do |val|
86
+ add_query_parameter(params, 'allLabels', parse_labels(val))
87
+ end
82
88
  opts.on('-a', '--details', "Display all details: memory and storage usage used / max values." ) do
83
89
  options[:details] = true
84
90
  end
@@ -221,6 +227,9 @@ class Morpheus::Cli::Apps
221
227
  opts.on( '--name VALUE', String, "Name" ) do |val|
222
228
  options[:name] = val
223
229
  end
230
+ opts.on('-l', '--labels [LIST]', String, "Labels") do |val|
231
+ options[:options]['labels'] = parse_labels(val)
232
+ end
224
233
  opts.on( '--description VALUE', String, "Description" ) do |val|
225
234
  options[:description] = val
226
235
  end
@@ -303,7 +312,6 @@ class Morpheus::Cli::Apps
303
312
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Enter a name for this app'}], options[:options])
304
313
  payload['name'] = v_prompt['name']
305
314
 
306
-
307
315
  # Description
308
316
  options[:options]['description'] = options[:description] if options.key?(:description)
309
317
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false}], options[:options])
@@ -332,7 +340,7 @@ class Morpheus::Cli::Apps
332
340
  end
333
341
  if cloud_id
334
342
  cloud = find_cloud_by_name_or_id_for_provisioning(group['id'], cloud_id)
335
- #payload['cloud'] = {'id' => cloud['id'], 'name' => cloud['name']}
343
+ payload['defaultCloud'] = {'id' => cloud ? cloud['id'] : cloud_id}
336
344
  end
337
345
 
338
346
  # Environment
@@ -354,6 +362,11 @@ class Morpheus::Cli::Apps
354
362
  end
355
363
  # payload['appContext'] = payload['environment'] if payload['environment']
356
364
 
365
+ # Labels
366
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text'}], options[:options])
367
+ payload['labels'] = parse_labels(v_prompt['labels']) unless v_prompt['labels'].to_s.empty?
368
+
369
+ # Configure (Tiers and their instances)
357
370
  if !payload['tiers']
358
371
  if payload['blueprintId'] != 'existing'
359
372
 
@@ -371,6 +384,7 @@ class Morpheus::Cli::Apps
371
384
  # tiers are a map, heh, sort them by tierIndex
372
385
  tiers = blueprint["config"]["tiers"] ? blueprint["config"]["tiers"] : (blueprint["tiers"] || {})
373
386
  sorted_tiers = tiers.collect {|k,v| [k,v] }.sort {|a,b| a[1]['tierIndex'] <=> b[1]['tierIndex'] }
387
+ payload.delete('defaultCloud')
374
388
  sorted_tiers.each do |tier_obj|
375
389
  tier_name = tier_obj[0]
376
390
  tier_config = tier_obj[1]
@@ -453,6 +467,8 @@ class Morpheus::Cli::Apps
453
467
  instance_prompt_options[:options][:help_field_prefix] = help_field_prefix
454
468
  instance_prompt_options[:locked_fields] = scoped_instance_config['lockedFields']
455
469
  instance_prompt_options[:for_app] = true
470
+ instance_prompt_options[:skip_labels_prompt] = true
471
+ # or could do this: instance_prompt_options[:labels] = default_labels
456
472
  # this provisioning helper method handles all (most) of the parsing and prompting
457
473
  scoped_instance_config = Marshal.load( Marshal.dump(scoped_instance_config) )
458
474
  instance_config_payload = prompt_new_instance(instance_prompt_options)
@@ -467,6 +483,10 @@ class Morpheus::Cli::Apps
467
483
  final_config.delete('groups')
468
484
  final_config.delete('clouds')
469
485
  final_config.delete('lockedFields')
486
+ final_config.delete('userRemovedFields')
487
+ # should not need this...
488
+ final_config.delete(:no_prompt)
489
+ final_config.delete(:help_field_prefix)
470
490
  # add config to payload
471
491
  payload['tiers'][tier_name]['instances'] ||= []
472
492
  payload['tiers'][tier_name]['instances'] << final_config
@@ -682,6 +702,7 @@ class Morpheus::Cli::Apps
682
702
  description_cols = {
683
703
  "ID" => 'id',
684
704
  "Name" => 'name',
705
+ "Labels" => lambda {|it| format_list(it['labels']) rescue '' },
685
706
  "Description" => 'description',
686
707
  "Type" => lambda {|it|
687
708
  if it['type']
@@ -810,6 +831,9 @@ class Morpheus::Cli::Apps
810
831
  opts.on( '--name VALUE', String, "Name" ) do |val|
811
832
  options[:name] = val
812
833
  end
834
+ opts.on('-l', '--labels [LIST]', String, "Labels") do |val|
835
+ options[:options]['labels'] = parse_labels(val)
836
+ end
813
837
  opts.on( '--description VALUE', String, "Description" ) do |val|
814
838
  options[:description] = val
815
839
  end
@@ -2367,6 +2391,7 @@ EOT
2367
2391
  {
2368
2392
  id: app['id'],
2369
2393
  name: app['name'],
2394
+ labels: format_list(app['labels'], '', 3),
2370
2395
  description: app['description'],
2371
2396
  blueprint: app['blueprint'] ? app['blueprint']['name'] : '',
2372
2397
  type: app['type'] ? format_blueprint_type(app['type']) : (format_blueprint_type(app['blueprint'] ? app['blueprint']['type'] : nil)),
@@ -2389,6 +2414,7 @@ EOT
2389
2414
  columns = [
2390
2415
  :id,
2391
2416
  :name,
2417
+ :labels,
2392
2418
  # :description,
2393
2419
  :type,
2394
2420
  :blueprint,
@@ -973,10 +973,10 @@ class Morpheus::Cli::ArchivesCommand
973
973
 
974
974
 
975
975
  print_h2 "Download URLs"
976
- private_download_url = "#{@appliance_url}/api/archives/download/#{CGI::escape(bucket_id)}" + "/#{CGI::escape(archive_file['filePath'])}".squeeze('/')
976
+ private_download_url = "#{@appliance_url}/api/archives/download/#{CGI::escape(bucket_id)}" + "/#{escape_filepath(archive_file['filePath'])}".squeeze('/')
977
977
  public_download_url = nil
978
978
  if archive_file['archiveBucket'] && archive_file['archiveBucket']['isPublic']
979
- public_download_url = "#{@appliance_url}/public-archives/download/#{CGI::escape(bucket_id)}" + "/#{CGI::escape(archive_file['filePath'])}".squeeze('/')
979
+ public_download_url = "#{@appliance_url}/public-archives/download/#{CGI::escape(bucket_id)}" + "/#{escape_filepath(archive_file['filePath'])}".squeeze('/')
980
980
  end
981
981
  print cyan
982
982
  puts "Private URL: #{private_download_url}"
@@ -62,6 +62,12 @@ class Morpheus::Cli::BlueprintsCommand
62
62
  params['ownerId'] << val
63
63
  end
64
64
  opts.add_hidden_option('--created-by')
65
+ opts.on('-l', '--labels LABEL', String, "Filter by labels, can match any of the values") do |val|
66
+ add_query_parameter(params, 'labels', parse_labels(val))
67
+ end
68
+ opts.on('--all-labels LABEL', String, "Filter by labels, must match all of the values") do |val|
69
+ add_query_parameter(params, 'allLabels', parse_labels(val))
70
+ end
65
71
  build_standard_list_options(opts, options)
66
72
  opts.footer = "List blueprints."
67
73
  end
@@ -191,6 +197,9 @@ class Morpheus::Cli::BlueprintsCommand
191
197
  opts.on('-t', '--type TYPE', String, "Blueprint Type. Default is morpheus.") do |val|
192
198
  options[:blueprint_type] = parse_blueprint_type(val.to_s)
193
199
  end
200
+ opts.on('-l', '--labels [LIST]', String, "Labels") do |val|
201
+ options[:options]['labels'] = parse_labels(val)
202
+ end
194
203
  build_standard_add_options(opts, options)
195
204
  opts.footer = "Create a new blueprint.\n" +
196
205
  "[name] is required. This is the name of the new blueprint."
@@ -258,6 +267,9 @@ class Morpheus::Cli::BlueprintsCommand
258
267
  opts.on( '--owner USER', "Owner Username or ID" ) do |val|
259
268
  options[:owner] = val == 'null' ? nil : val
260
269
  end
270
+ opts.on('-l', '--labels [LIST]', String, "Labels") do |val|
271
+ options[:options]['labels'] = parse_labels(val)
272
+ end
261
273
  build_standard_update_options(opts, options)
262
274
  opts.footer = "Update a blueprint.\n" +
263
275
  "[blueprint] is required. This is the name or id of a blueprint."
@@ -817,6 +829,7 @@ class Morpheus::Cli::BlueprintsCommand
817
829
  options[:name_required] = false
818
830
  options[:instance_type_code] = instance_config['instance']['type'] #instance_type["code"]
819
831
  options[:for_app] = true
832
+ options[:skip_labels_prompt] = true
820
833
  #options[:options].deep_merge!(specific_config)
821
834
  # this provisioning helper method handles all (most) of the parsing and prompting
822
835
  instance_config_payload = prompt_new_instance(options)
@@ -1929,6 +1942,7 @@ class Morpheus::Cli::BlueprintsCommand
1929
1942
  {
1930
1943
  id: blueprint['id'],
1931
1944
  name: blueprint['name'],
1945
+ labels: format_list(blueprint['labels'], '', 3),
1932
1946
  type: blueprint['type'].kind_of?(Hash) ? blueprint['type']['name'] : format_blueprint_type(blueprint['type']),
1933
1947
  description: blueprint['description'],
1934
1948
  category: blueprint['category'],
@@ -1947,6 +1961,7 @@ class Morpheus::Cli::BlueprintsCommand
1947
1961
  columns = [
1948
1962
  :id,
1949
1963
  :name,
1964
+ :labels,
1950
1965
  :type,
1951
1966
  :description,
1952
1967
  :category,
@@ -2026,6 +2041,7 @@ class Morpheus::Cli::BlueprintsCommand
2026
2041
  description_cols = {
2027
2042
  "ID" => 'id',
2028
2043
  "Name" => 'name',
2044
+ "Labels" => lambda {|it| format_list(it['labels'], '') rescue '' },
2029
2045
  "Type" => lambda {|it| it['type'].kind_of?(Hash) ? it['type']['name'] : it['type'] },
2030
2046
  "Description" => 'description',
2031
2047
  "Category" => 'category',
@@ -37,6 +37,12 @@ class Morpheus::Cli::CatalogItemTypesCommand
37
37
  opts.on( '--featured [on|off]', String, "Filter by featured" ) do |val|
38
38
  params['featured'] = (val.to_s != 'false' && val.to_s != 'off')
39
39
  end
40
+ opts.on('-l', '--labels LABEL', String, "Filter by labels, can match any of the values") do |val|
41
+ add_query_parameter(params, 'labels', parse_labels(val))
42
+ end
43
+ opts.on('--all-labels LABEL', String, "Filter by labels, must match all of the values") do |val|
44
+ add_query_parameter(params, 'allLabels', parse_labels(val))
45
+ end
40
46
  build_standard_list_options(opts, options)
41
47
  opts.footer = "List catalog item types."
42
48
  end
@@ -59,7 +65,7 @@ class Morpheus::Cli::CatalogItemTypesCommand
59
65
  if catalog_item_types.empty?
60
66
  print cyan,"No catalog item types found.",reset,"\n"
61
67
  else
62
- list_columns = catalog_item_type_column_definitions.upcase_keys!
68
+ list_columns = catalog_item_type_list_column_definitions.upcase_keys!
63
69
  list_columns.delete("Blueprint")
64
70
  list_columns.delete("Workflow")
65
71
  list_columns.delete("Context")
@@ -232,6 +238,9 @@ EOT
232
238
  # options[:options]['type'] = val.to_s.downcase
233
239
  # end
234
240
  build_option_type_options(opts, options, add_catalog_item_type_option_types)
241
+ opts.on('-l', '--labels [LIST]', String, "Labels") do |val|
242
+ options[:options]['labels'] = parse_labels(val)
243
+ end
235
244
  opts.on('--logo FILE', String, "Upload a custom logo icon") do |val|
236
245
  filename = val
237
246
  logo_file = nil
@@ -386,6 +395,9 @@ EOT
386
395
  optparse = Morpheus::Cli::OptionParser.new do |opts|
387
396
  opts.banner = subcommand_usage("[type] [options]")
388
397
  build_option_type_options(opts, options, update_catalog_item_type_option_types)
398
+ opts.on('-l', '--labels [LIST]', String, "Labels") do |val|
399
+ options[:options]['labels'] = parse_labels(val)
400
+ end
389
401
  opts.on('--logo FILE', String, "Upload a custom logo icon") do |val|
390
402
  filename = val
391
403
  logo_file = nil
@@ -549,7 +561,7 @@ EOT
549
561
  filename = args[1]
550
562
  logo_file = nil
551
563
  if filename == 'null'
552
- filename = 'null' # clear it
564
+ logo_file = 'null' # clear it
553
565
  else
554
566
  filename = File.expand_path(filename)
555
567
  if !File.exists?(filename)
@@ -641,10 +653,30 @@ EOT
641
653
 
642
654
  private
643
655
 
656
+ def catalog_item_type_list_column_definitions()
657
+ {
658
+ "ID" => 'id',
659
+ "Name" => 'name',
660
+ "Labels" => lambda {|it| format_list(it['labels'], '', 3) },
661
+ "Description" => 'description',
662
+ "Type" => lambda {|it| format_catalog_type(it) },
663
+ "Blueprint" => lambda {|it| it['blueprint'] ? it['blueprint']['name'] : nil },
664
+ "Workflow" => lambda {|it| it['workflow'] ? it['workflow']['name'] : nil },
665
+ "Context" => lambda {|it| it['context'] },
666
+ # "Content" => lambda {|it| it['content'] },
667
+ "Enabled" => lambda {|it| format_boolean(it['enabled']) },
668
+ "Featured" => lambda {|it| format_boolean(it['featured']) },
669
+ #"Config" => lambda {|it| it['config'] },
670
+ "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
671
+ "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
672
+ }
673
+ end
674
+
644
675
  def catalog_item_type_column_definitions()
645
676
  {
646
677
  "ID" => 'id',
647
678
  "Name" => 'name',
679
+ "Labels" => lambda {|it| format_list(it['labels']) },
648
680
  "Description" => 'description',
649
681
  "Type" => lambda {|it| format_catalog_type(it) },
650
682
  "Blueprint" => lambda {|it| it['blueprint'] ? it['blueprint']['name'] : nil },
@@ -0,0 +1,338 @@
1
+ require 'morpheus/cli/cli_command'
2
+
3
+ class Morpheus::Cli::ClientsCommand
4
+ include Morpheus::Cli::CliCommand
5
+
6
+ set_command_name :clients
7
+ set_command_description "View and manage Oath Clients"
8
+ register_subcommands :list, :get, :add, :update, :remove
9
+
10
+ def initialize()
11
+ #@appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
12
+ end
13
+
14
+ def connect(opts)
15
+ @api_client = establish_remote_appliance_connection(opts)
16
+ @clients_interface = @api_client.clients
17
+ end
18
+
19
+ def handle(args)
20
+ handle_subcommand(args)
21
+ end
22
+
23
+ def list(args)
24
+ options = {}
25
+ params = {}
26
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
27
+ opts.banner = subcommand_usage()
28
+ build_standard_list_options(opts, options)
29
+ opts.footer = "List Oauth Clients."
30
+ end
31
+ optparse.parse!(args)
32
+ connect(options)
33
+
34
+ params.merge!(parse_list_options(options))
35
+ @clients_interface.setopts(options)
36
+ if options[:dry_run]
37
+ print_dry_run @clients_interface.dry.list(params)
38
+ return 0
39
+ end
40
+
41
+ json_response = @clients_interface.list(params)
42
+ render_response(json_response, options, "clients") do
43
+ clients = json_response["clients"]
44
+ if clients.empty?
45
+ print cyan,"No clients found",reset,"\n"
46
+ else
47
+ rows = clients.collect {|client|
48
+ row = {
49
+ id: client['id'],
50
+ client_id: client['clientId'],
51
+ access_token_seconds: client['accessTokenValiditySeconds'],
52
+ refresh_token_seconds: client['refreshTokenValiditySeconds']
53
+ }
54
+ row
55
+ }
56
+ columns = [:id, {:client_id => {:max_width => 50}}, :access_token_seconds, :refresh_token_seconds]
57
+ print_h1 "Morpheus Clients", [], options
58
+ print as_pretty_table(rows, columns, options)
59
+ print reset
60
+ print_results_pagination(json_response)
61
+ end
62
+ print reset,"\n"
63
+ end
64
+ return 0, nil
65
+ end
66
+
67
+ def get(args)
68
+ options = {}
69
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
70
+ opts.banner = subcommand_usage("[client]")
71
+ build_standard_get_options(opts, options)
72
+ opts.footer = "Get details about an oath client.\n" +
73
+ "[client] is required. This is the name or id of a client."
74
+
75
+ end
76
+ optparse.parse!(args)
77
+ if args.count < 1
78
+ puts optparse
79
+ exit 1
80
+ end
81
+ connect(options)
82
+ begin
83
+ @clients_interface.setopts(options)
84
+ if options[:dry_run]
85
+ if args[0].to_s =~ /\A\d{1,}\Z/
86
+ print_dry_run @clients_interface.dry.get(args[0])
87
+ else
88
+ print_dry_run @clients_interface.dry.list({name: args[0].to_s})
89
+ end
90
+ return 0
91
+ end
92
+ client = find_client_by_name_or_id(args[0])
93
+ return 1 if client.nil?
94
+ json_response = {'client' => client}
95
+ render_result = render_with_format(json_response, options, 'client')
96
+ return 0 if render_result
97
+
98
+ unless options[:quiet]
99
+ print_h1 "Client Details"
100
+ print cyan
101
+ client_columns = {
102
+ "ID" => 'id',
103
+ "Client ID" => 'clientId',
104
+ "Access Token Validity Seconds" => 'accessTokenValiditySeconds',
105
+ "Refresh Token Validity Seconds" => 'refreshTokenValiditySeconds'
106
+ }
107
+
108
+ print_description_list(client_columns, client)
109
+ print reset,"\n"
110
+
111
+ end
112
+ print reset,"\n"
113
+ return 0
114
+ rescue RestClient::Exception => e
115
+ print_rest_exception(e, options)
116
+ exit 1
117
+ end
118
+ end
119
+
120
+ def add(args)
121
+ options = {}
122
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
123
+ opts.banner = subcommand_usage("[clientId] [options]")
124
+ build_option_type_options(opts, options, add_client_option_types)
125
+ build_common_options(opts, options, [:payload, :options, :json, :dry_run, :remote])
126
+ opts.footer = "Add New Oauth Client Record."
127
+ end
128
+ optparse.parse!(args)
129
+ if args.count > 1
130
+ raise_command_error "wrong number of arguments, expected 0-1 and got (#{args.count}) #{args}\n#{optparse}"
131
+ end
132
+ if args[0]
133
+ options[:options] ||= {}
134
+ options[:options]['clientId'] ||= args[0]
135
+ end
136
+ connect(options)
137
+ begin
138
+ # construct payload
139
+ passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
140
+ payload = nil
141
+ if options[:payload]
142
+ payload = options[:payload]
143
+ payload.deep_merge!({'client' => passed_options}) unless passed_options.empty?
144
+ else
145
+ payload = {
146
+ 'client' => {
147
+ }
148
+ }
149
+ # allow arbitrary -O options
150
+ payload.deep_merge!({'client' => passed_options}) unless passed_options.empty?
151
+ # prompt for options
152
+ params = Morpheus::Cli::OptionTypes.prompt(add_client_option_types, options[:options], @api_client, options[:params])
153
+ payload.deep_merge!({'client' => params}) unless params.empty?
154
+ end
155
+
156
+ @clients_interface.setopts(options)
157
+ if options[:dry_run]
158
+ print_dry_run @clients_interface.dry.create(payload)
159
+ return
160
+ end
161
+ json_response = @clients_interface.create(payload)
162
+ if options[:json]
163
+ print JSON.pretty_generate(json_response)
164
+ print "\n"
165
+ else
166
+ display_name = json_response['client'] ? json_response['client']['clientId'] : ''
167
+ print_green_success "Client #{display_name} added"
168
+ get([json_response['client']['id']] + (options[:remote] ? ["-r",options[:remote]] : []))
169
+ end
170
+ return 0
171
+ rescue RestClient::Exception => e
172
+ print_rest_exception(e, options)
173
+ exit 1
174
+ end
175
+ end
176
+
177
+ def update(args)
178
+ options = {}
179
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
180
+ opts.banner = subcommand_usage("[clientId] [options]")
181
+ build_option_type_options(opts, options, client_option_types)
182
+ build_common_options(opts, options, [:payload, :options, :json, :dry_run, :remote])
183
+ opts.footer = "Update Oauth Client Record."
184
+ end
185
+ optparse.parse!(args)
186
+
187
+ if args.count != 1
188
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args}\n#{optparse}"
189
+ end
190
+
191
+ connect(options)
192
+ begin
193
+
194
+ client = find_client_by_name_or_id(args[0])
195
+ return 1 if client.nil?
196
+
197
+ # construct payload
198
+ passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
199
+ payload = nil
200
+ if options[:payload]
201
+ payload = options[:payload]
202
+ payload.deep_merge!({'client' => passed_options}) unless passed_options.empty?
203
+ else
204
+ payload = {
205
+ 'client' => {
206
+ }
207
+ }
208
+ # allow arbitrary -O options
209
+ payload.deep_merge!({'page' => passed_options}) unless passed_options.empty?
210
+ # prompt for options
211
+ #params = Morpheus::Cli::OptionTypes.prompt(update_wiki_page_option_types, options[:options], @api_client, options[:params])
212
+ params = passed_options
213
+
214
+ if params.empty?
215
+ raise_command_error "Specify at least one option to update.\n#{optparse}"
216
+ end
217
+
218
+ payload.deep_merge!({'client' => params}) unless params.empty?
219
+ end
220
+ @clients_interface.setopts(options)
221
+ if options[:dry_run]
222
+ print_dry_run @clients_interface.dry.update(client['id'], payload)
223
+ return
224
+ end
225
+ json_response = @clients_interface.update(client['id'], payload)
226
+ if options[:json]
227
+ print JSON.pretty_generate(json_response)
228
+ print "\n"
229
+ else
230
+ display_name = json_response['client'] ? json_response['client']['clientId'] : ''
231
+ print_green_success "Client #{display_name} updated"
232
+ get([json_response['client']['id']] + (options[:remote] ? ["-r",options[:remote]] : []))
233
+ end
234
+ return 0
235
+ rescue RestClient::Exception => e
236
+ print_rest_exception(e, options)
237
+ exit 1
238
+ end
239
+ end
240
+
241
+ def remove(args)
242
+ options = {}
243
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
244
+ opts.banner = subcommand_usage("[clientId]")
245
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
246
+ opts.footer = "Deletes Oauth Client."
247
+ end
248
+ optparse.parse!(args)
249
+
250
+ if args.count != 1
251
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args}\n#{optparse}"
252
+ end
253
+
254
+ connect(options)
255
+ begin
256
+ client = find_client_by_name_or_id(args[0])
257
+ return 1 if client.nil?
258
+
259
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the client #{client['clientId']}?")
260
+ return 9, "aborted command"
261
+ end
262
+ @clients_interface.setopts(options)
263
+ if options[:dry_run]
264
+ print_dry_run @clients_interface.dry.destroy(client['id'])
265
+ return
266
+ end
267
+ json_response = @clients_interface.destroy(client['id'])
268
+ if options[:json]
269
+ print JSON.pretty_generate(json_response)
270
+ print "\n"
271
+ else
272
+ print_green_success "Client #{client['clientId']} removed"
273
+ # list([] + (options[:remote] ? ["-r",options[:remote]] : []))
274
+ end
275
+ return 0
276
+ rescue RestClient::Exception => e
277
+ print_rest_exception(e, options)
278
+ exit 1
279
+ end
280
+ end
281
+
282
+
283
+ private
284
+ def find_client_by_name_or_id(val)
285
+ if val.to_s =~ /\A\d{1,}\Z/
286
+ return find_client_by_id(val)
287
+ else
288
+ return find_client_by_client_id(val)
289
+ end
290
+ end
291
+
292
+ def find_client_by_id(id)
293
+ raise "#{self.class} has not defined @client_interface" if @clients_interface.nil?
294
+ begin
295
+ json_response = @clients_interface.get(id)
296
+ return json_response['client']
297
+ rescue RestClient::Exception => e
298
+ if e.response && e.response.code == 404
299
+ print_red_alert "Client not found by id #{id}"
300
+ else
301
+ raise e
302
+ end
303
+ end
304
+ end
305
+
306
+ def find_client_by_client_id(clientId)
307
+ raise "#{self.class} has not defined @client_interface" if @clients_interface.nil?
308
+ clients = @clients_interface.list()['clients'].select { |client| client['clientId'] == clientId }
309
+ if clients.empty?
310
+ print_red_alert "Client not found by clientId #{clientId}"
311
+ return nil
312
+ elsif clients.size > 1
313
+ print_red_alert "#{clients.size} Clients found by clientId #{clientId}"
314
+ print as_pretty_table(clients, [:id,:clientId], {color:red})
315
+ print reset,"\n"
316
+ return nil
317
+ else
318
+ return clients[0]
319
+ end
320
+ end
321
+
322
+ def client_option_types
323
+ [
324
+ {'fieldName' => 'clientId', 'fieldLabel' => 'Client Id', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
325
+ {'fieldName' => 'accessTokenValiditySeconds', 'fieldLabel' => 'Access Token Validity Length (Seconds)', 'type' => 'number', 'required' => true, 'defaultValue' => 43200,'displayOrder' => 2},
326
+ {'fieldName' => 'refreshTokenValiditySeconds', 'fieldLabel' => 'Refresh Token Validity Length (Seconds)', 'type' => 'number', 'required' => true, 'defaultValue' => 43200,'displayOrder' => 3}
327
+ ]
328
+ end
329
+
330
+ def add_client_option_types
331
+ [
332
+ {'fieldName' => 'clientId', 'fieldLabel' => 'Client Id', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
333
+ {'fieldName' => 'clientSecret', 'fieldLabel' => 'Client Secret', 'type' => 'text', 'displayOrder' => 2},
334
+ {'fieldName' => 'accessTokenValiditySeconds', 'fieldLabel' => 'Access Token Validity Length (Seconds)', 'type' => 'number', 'required' => true,'defaultValue' => 43200, 'displayOrder' => 3},
335
+ {'fieldName' => 'refreshTokenValiditySeconds', 'fieldLabel' => 'Refresh Token Validity Length (Seconds)', 'type' => 'number', 'required' => true,'defaultValue' => 43200, 'displayOrder' => 4}
336
+ ]
337
+ end
338
+ end