morpheus-cli 5.5.1.5 → 5.5.2

Sign up to get free protection for your applications and to get access to all the features.
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 +27 -8
  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