morpheus-cli 2.10.3 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/bin/morpheus +5 -96
  3. data/lib/morpheus/api/api_client.rb +23 -1
  4. data/lib/morpheus/api/checks_interface.rb +106 -0
  5. data/lib/morpheus/api/incidents_interface.rb +102 -0
  6. data/lib/morpheus/api/monitoring_apps_interface.rb +47 -0
  7. data/lib/morpheus/api/monitoring_contacts_interface.rb +47 -0
  8. data/lib/morpheus/api/monitoring_groups_interface.rb +47 -0
  9. data/lib/morpheus/api/monitoring_interface.rb +36 -0
  10. data/lib/morpheus/api/option_type_lists_interface.rb +47 -0
  11. data/lib/morpheus/api/option_types_interface.rb +47 -0
  12. data/lib/morpheus/api/roles_interface.rb +0 -1
  13. data/lib/morpheus/api/setup_interface.rb +19 -9
  14. data/lib/morpheus/cli.rb +20 -1
  15. data/lib/morpheus/cli/accounts.rb +8 -3
  16. data/lib/morpheus/cli/app_templates.rb +19 -11
  17. data/lib/morpheus/cli/apps.rb +52 -37
  18. data/lib/morpheus/cli/cli_command.rb +229 -53
  19. data/lib/morpheus/cli/cli_registry.rb +48 -40
  20. data/lib/morpheus/cli/clouds.rb +55 -26
  21. data/lib/morpheus/cli/command_error.rb +12 -0
  22. data/lib/morpheus/cli/credentials.rb +68 -26
  23. data/lib/morpheus/cli/curl_command.rb +98 -0
  24. data/lib/morpheus/cli/dashboard_command.rb +2 -7
  25. data/lib/morpheus/cli/deployments.rb +4 -4
  26. data/lib/morpheus/cli/deploys.rb +1 -2
  27. data/lib/morpheus/cli/dot_file.rb +5 -8
  28. data/lib/morpheus/cli/error_handler.rb +179 -15
  29. data/lib/morpheus/cli/groups.rb +21 -13
  30. data/lib/morpheus/cli/hosts.rb +220 -110
  31. data/lib/morpheus/cli/instance_types.rb +2 -2
  32. data/lib/morpheus/cli/instances.rb +257 -167
  33. data/lib/morpheus/cli/key_pairs.rb +15 -9
  34. data/lib/morpheus/cli/library.rb +673 -27
  35. data/lib/morpheus/cli/license.rb +2 -2
  36. data/lib/morpheus/cli/load_balancers.rb +4 -4
  37. data/lib/morpheus/cli/log_level_command.rb +6 -4
  38. data/lib/morpheus/cli/login.rb +17 -3
  39. data/lib/morpheus/cli/logout.rb +25 -11
  40. data/lib/morpheus/cli/man_command.rb +388 -0
  41. data/lib/morpheus/cli/mixins/accounts_helper.rb +1 -1
  42. data/lib/morpheus/cli/mixins/monitoring_helper.rb +434 -0
  43. data/lib/morpheus/cli/mixins/print_helper.rb +620 -112
  44. data/lib/morpheus/cli/mixins/provisioning_helper.rb +1 -1
  45. data/lib/morpheus/cli/monitoring_apps_command.rb +29 -0
  46. data/lib/morpheus/cli/monitoring_checks_command.rb +427 -0
  47. data/lib/morpheus/cli/monitoring_contacts_command.rb +373 -0
  48. data/lib/morpheus/cli/monitoring_groups_command.rb +29 -0
  49. data/lib/morpheus/cli/monitoring_incidents_command.rb +711 -0
  50. data/lib/morpheus/cli/option_types.rb +10 -1
  51. data/lib/morpheus/cli/recent_activity_command.rb +2 -5
  52. data/lib/morpheus/cli/remote.rb +874 -134
  53. data/lib/morpheus/cli/roles.rb +54 -27
  54. data/lib/morpheus/cli/security_group_rules.rb +2 -2
  55. data/lib/morpheus/cli/security_groups.rb +23 -19
  56. data/lib/morpheus/cli/set_prompt_command.rb +50 -0
  57. data/lib/morpheus/cli/shell.rb +222 -157
  58. data/lib/morpheus/cli/tasks.rb +19 -15
  59. data/lib/morpheus/cli/users.rb +27 -17
  60. data/lib/morpheus/cli/version.rb +1 -1
  61. data/lib/morpheus/cli/virtual_images.rb +28 -13
  62. data/lib/morpheus/cli/whoami.rb +131 -52
  63. data/lib/morpheus/cli/workflows.rb +24 -9
  64. data/lib/morpheus/formatters.rb +195 -3
  65. data/lib/morpheus/logging.rb +86 -0
  66. data/lib/morpheus/terminal.rb +371 -0
  67. data/scripts/generate_morpheus_commands_help.morpheus +60 -0
  68. metadata +21 -2
@@ -50,7 +50,7 @@ class Morpheus::Cli::KeyPairs
50
50
  print JSON.pretty_generate(json_response)
51
51
  print "\n"
52
52
  else
53
- title = "Morpheus Hosts"
53
+ title = "Morpheus Key Pairs"
54
54
  subtitles = []
55
55
  if account
56
56
  subtitles << "Account: #{account['name']}".strip
@@ -58,8 +58,7 @@ class Morpheus::Cli::KeyPairs
58
58
  if params[:phrase]
59
59
  subtitles << "Search: #{params[:phrase]}".strip
60
60
  end
61
- subtitle = subtitles.join(', ')
62
- print "\n" ,cyan, bold, title, (subtitle.empty? ? "" : " - #{subtitle}"), "\n", "==================", reset, "\n\n"
61
+ print_h1 title, subtitles
63
62
  if key_pairs.empty?
64
63
  puts yellow,"No key pairs found.",reset
65
64
  else
@@ -100,13 +99,20 @@ class Morpheus::Cli::KeyPairs
100
99
  print JSON.pretty_generate({keyPair: key_pair})
101
100
  print "\n"
102
101
  else
103
- print "\n" ,cyan, bold, "Key Pair Details\n","==================", reset, "\n\n"
102
+ print_h1 "Key Pair Details"
104
103
  print cyan
105
- puts "ID: #{key_pair['id']}"
106
- puts "Name: #{key_pair['name']}"
107
- puts "MD5: #{key_pair['md5']}"
108
- puts "Date Created: #{format_local_dt(key_pair['dateCreated'])}"
109
- #puts "Last Updated: #{format_local_dt(key_pair['lastUpdated'])}"
104
+ if account
105
+ # print_description_list({"Account" => lambda {|it| it['account'] ? it['account']['name'] : '' } }, key_pair)
106
+ print_description_list({"Account" => lambda {|it| account['name'] } }, key_pair)
107
+ end
108
+ print_description_list({
109
+ "ID" => 'id',
110
+ "Name" => 'name',
111
+ "MD5" => 'md5',
112
+ # "Account" => lambda {|it| it['account'] ? it['account']['name'] : '' },
113
+ "Created" => lambda {|it| format_local_dt(it['dateCreated']) }
114
+ #"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
115
+ }, key_pair)
110
116
  print reset,"\n"
111
117
 
112
118
  # todo: show public key
@@ -8,6 +8,8 @@ class Morpheus::Cli::Library
8
8
 
9
9
  register_subcommands :list, :get, :add, :update, :remove, :'add-version'
10
10
  alias_subcommand :details, :get
11
+ register_subcommands({:'option-types' => :option_types_list}, :option_types_get, :option_types_add, :option_types_update, :option_types_remove)
12
+ register_subcommands({:'option-lists' => :option_lists_list}, :option_lists_get, :option_lists_add, :option_lists_update, :option_lists_remove)
11
13
 
12
14
  def initialize()
13
15
  # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
@@ -17,6 +19,8 @@ class Morpheus::Cli::Library
17
19
  @api_client = establish_remote_appliance_connection(opts)
18
20
  @custom_instance_types_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).custom_instance_types
19
21
  @provision_types_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).provision_types
22
+ @option_types_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).option_types
23
+ @option_type_lists_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).option_type_lists
20
24
  end
21
25
 
22
26
  def handle(args)
@@ -51,7 +55,7 @@ class Morpheus::Cli::Library
51
55
  end
52
56
 
53
57
  instance_types = json_response['instanceTypes']
54
- print "\n" ,cyan, bold, "Morpheus Custom Instance Types\n","==================", reset, "\n\n"
58
+ print_h1 "Morpheus Custom Instance Types"
55
59
  if instance_types.empty?
56
60
  puts yellow,"No instance types currently configured.",reset
57
61
  else
@@ -99,18 +103,13 @@ class Morpheus::Cli::Library
99
103
  print JSON.pretty_generate({instanceType: instance_type}), "\n"
100
104
  return
101
105
  end
102
-
103
- if instance_type.nil?
104
- puts yellow,"No custom instance type found by name #{name}.",reset
105
- else
106
- print "\n" ,cyan, bold, "Custom Instance Type Details\n","==================", reset, "\n\n"
107
- versions = instance_type['versions'].join(', ')
108
- print cyan, "= #{instance_type['name']} (#{instance_type['code']}) - #{versions}\n"
109
- instance_type['instanceTypeLayouts'].each do |layout|
110
- print green, " - #{layout['name']}\n",reset
111
- end
112
- print reset,"\n"
106
+ print_h1 "Custom Instance Type Details"
107
+ versions = instance_type['versions'].join(', ')
108
+ print cyan, "= #{instance_type['name']} (#{instance_type['code']}) - #{versions}\n"
109
+ instance_type['instanceTypeLayouts'].each do |layout|
110
+ print green, " - #{layout['name']}\n",reset
113
111
  end
112
+ print reset,"\n"
114
113
 
115
114
  rescue RestClient::Exception => e
116
115
  print_rest_exception(e, options)
@@ -402,6 +401,521 @@ class Morpheus::Cli::Library
402
401
  end
403
402
 
404
403
 
404
+ #### Option Type actions
405
+
406
+ def option_types_list(args)
407
+ options = {}
408
+ optparse = OptionParser.new do|opts|
409
+ opts.banner = subcommand_usage()
410
+ build_common_options(opts, options, [:list, :dry_run, :json])
411
+ end
412
+ optparse.parse!(args)
413
+ connect(options)
414
+ begin
415
+ params = {}
416
+ [:phrase, :offset, :max, :sort, :direction].each do |k|
417
+ params[k] = options[k] unless options[k].nil?
418
+ end
419
+
420
+ if options[:dry_run]
421
+ print_dry_run @option_types_interface.dry.list(params)
422
+ return
423
+ end
424
+
425
+ json_response = @option_types_interface.list(params)
426
+
427
+ if options[:json]
428
+ print JSON.pretty_generate(json_response), "\n"
429
+ return
430
+ end
431
+
432
+ option_types = json_response['optionTypes']
433
+ print_h1 "Morpheus Option Types"
434
+ if option_types.empty?
435
+ print cyan,"No option types found.",reset,"\n"
436
+ else
437
+ rows = option_types.collect do |option_type|
438
+ {
439
+ id: option_type['id'],
440
+ name: option_type['name'],
441
+ type: option_type['type'],
442
+ fieldLabel: option_type['fieldLabel'],
443
+ fieldName: option_type['fieldName'],
444
+ default: option_type['defaultValue'],
445
+ required: option_type['required'] ? 'yes' : 'no'
446
+ }
447
+ end
448
+ print cyan
449
+ tp rows, [
450
+ :id,
451
+ :name,
452
+ :type,
453
+ {:fieldLabel => {:display_name => "Field Label"} },
454
+ {:fieldName => {:display_name => "Field Name"} },
455
+ :default,
456
+ :required
457
+ ]
458
+ print reset
459
+ print_results_pagination(json_response)
460
+ end
461
+ print reset,"\n"
462
+ rescue RestClient::Exception => e
463
+ print_rest_exception(e, options)
464
+ exit 1
465
+ end
466
+ end
467
+
468
+ def option_types_get(args)
469
+ options = {}
470
+ optparse = OptionParser.new do|opts|
471
+ opts.banner = subcommand_usage("[name]")
472
+ build_common_options(opts, options, [:json, :dry_run])
473
+ end
474
+ optparse.parse!(args)
475
+ if args.count < 1
476
+ puts optparse
477
+ exit 1
478
+ end
479
+
480
+ connect(options)
481
+ begin
482
+ if options[:dry_run]
483
+ if args[0].to_s =~ /\A\d{1,}\Z/
484
+ print_dry_run @option_types_interface.dry.get(args[0].to_i)
485
+ else
486
+ print_dry_run @option_types_interface.dry.list({name: args[0]})
487
+ end
488
+ return
489
+ end
490
+ option_type = find_option_type_by_name_or_id(args[0])
491
+ exit 1 if option_type.nil?
492
+
493
+ if options[:json]
494
+ print JSON.pretty_generate({optionType: option_type}), "\n"
495
+ return
496
+ end
497
+
498
+ print_h1 "Option Type Details"
499
+ print cyan
500
+ print_description_list({
501
+ "ID" => 'id',
502
+ "Name" => 'name',
503
+ "Description" => 'description',
504
+ "Field Name" => 'fieldName',
505
+ "Type" => lambda {|it| it['type'].to_s.capitalize },
506
+ "Label" => 'fieldLabel',
507
+ "Placeholder" => 'placeHolder',
508
+ "Default Value" => 'defaultValue'
509
+ }, option_type)
510
+ print reset,"\n"
511
+
512
+ rescue RestClient::Exception => e
513
+ print_rest_exception(e, options)
514
+ exit 1
515
+ end
516
+ end
517
+
518
+ def option_types_add(args)
519
+ # JD: this is annoying because our option_types (for prompting and help)
520
+ # are the same type of object being managed here.., options options options
521
+ options = {}
522
+ optparse = OptionParser.new do|opts|
523
+ opts.banner = subcommand_usage("[options]")
524
+ build_option_type_options(opts, options, new_option_type_option_types)
525
+ build_common_options(opts, options, [:options, :json, :dry_run])
526
+ end
527
+ optparse.parse!(args)
528
+ connect(options)
529
+ begin
530
+ params = Morpheus::Cli::OptionTypes.prompt(new_option_type_option_types, options[:options], @api_client, options[:params])
531
+ if params.key?('required')
532
+ params['required'] = ['on','true'].include?(params['required'].to_s)
533
+ end
534
+ option_type_payload = params
535
+ payload = {optionType: option_type_payload}
536
+ if options[:dry_run]
537
+ print_dry_run @option_types_interface.dry.create(payload)
538
+ return
539
+ end
540
+ json_response = @option_types_interface.create(payload)
541
+ if options[:json]
542
+ print JSON.pretty_generate(json_response), "\n"
543
+ return
544
+ end
545
+ print_green_success "Added Option Type #{option_type_payload['name']}"
546
+ #option_types_list([])
547
+ option_types_get([option_type['id']])
548
+ rescue RestClient::Exception => e
549
+ print_rest_exception(e, options)
550
+ exit 1
551
+ end
552
+ end
553
+
554
+ def option_types_update(args)
555
+ # JD: this is annoying because our option_types (for prompting and help)
556
+ # are the same type of object being managed here.., options options options
557
+ options = {}
558
+ optparse = OptionParser.new do|opts|
559
+ opts.banner = subcommand_usage("[name] [options]")
560
+ build_option_type_options(opts, options, update_option_type_option_types)
561
+ build_common_options(opts, options, [:options, :json, :dry_run])
562
+ end
563
+ optparse.parse!(args)
564
+ connect(options)
565
+ begin
566
+ option_type = find_option_type_by_name_or_id(args[0])
567
+ exit 1 if option_type.nil?
568
+
569
+ #params = options[:options] || {}
570
+ params = Morpheus::Cli::OptionTypes.no_prompt(update_option_type_option_types, options[:options], @api_client, options[:params])
571
+ if params.empty?
572
+ print_red_alert "Specify atleast one option to update"
573
+ puts optparse
574
+ exit 1
575
+ end
576
+ if params.key?('required')
577
+ params['required'] = ['on','true'].include?(params['required'].to_s)
578
+ end
579
+ option_type_payload = params
580
+ payload = {optionType: option_type_payload}
581
+ if options[:dry_run]
582
+ print_dry_run @option_types_interface.dry.update(option_type['id'], payload)
583
+ return
584
+ end
585
+ json_response = @option_types_interface.update(option_type['id'], payload)
586
+ if options[:json]
587
+ print JSON.pretty_generate(json_response), "\n"
588
+ return
589
+ end
590
+ print_green_success "Updated Option Type #{option_type_payload['name']}"
591
+ #option_types_list([])
592
+ option_types_get([option_type['id']])
593
+ rescue RestClient::Exception => e
594
+ print_rest_exception(e, options)
595
+ exit 1
596
+ end
597
+ end
598
+
599
+ def option_types_remove(args)
600
+ options = {}
601
+ optparse = OptionParser.new do|opts|
602
+ opts.banner = subcommand_usage("[name]")
603
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run])
604
+ end
605
+ optparse.parse!(args)
606
+ if args.count < 1
607
+ puts optparse
608
+ exit 1
609
+ end
610
+ connect(options)
611
+
612
+ begin
613
+ option_type = find_option_type_by_name_or_id(args[0])
614
+ exit 1 if option_type.nil?
615
+
616
+ unless Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the option type #{option_type['name']}?", options)
617
+ exit
618
+ end
619
+ if options[:dry_run]
620
+ print_dry_run @option_types_interface.dry.destroy(option_type['id'])
621
+ return
622
+ end
623
+ json_response = @option_types_interface.destroy(option_type['id'])
624
+
625
+ if options[:json]
626
+ print JSON.pretty_generate(json_response), "\n"
627
+ return
628
+ end
629
+
630
+ print_green_success "Removed Option Type #{option_type['name']}"
631
+ #list([])
632
+ rescue RestClient::Exception => e
633
+ print_rest_exception(e, options)
634
+ exit 1
635
+ end
636
+ end
637
+
638
+ #### Option Type List actions
639
+
640
+ def option_lists_list(args)
641
+ options = {}
642
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
643
+ opts.banner = subcommand_usage()
644
+ build_common_options(opts, options, [:list, :dry_run, :json])
645
+ opts.footer = "This outputs a list of custom Option List records."
646
+ end
647
+ optparse.parse!(args)
648
+ connect(options)
649
+ begin
650
+ params = {}
651
+ [:phrase, :offset, :max, :sort, :direction].each do |k|
652
+ params[k] = options[k] unless options[k].nil?
653
+ end
654
+
655
+ if options[:dry_run]
656
+ print_dry_run @option_type_lists_interface.dry.list(params)
657
+ return
658
+ end
659
+
660
+ json_response = @option_type_lists_interface.list(params)
661
+
662
+ if options[:json]
663
+ print JSON.pretty_generate(json_response), "\n"
664
+ return
665
+ end
666
+
667
+ option_type_lists = json_response['optionTypeLists']
668
+ print_h1 "Morpheus Option Lists"
669
+ if option_type_lists.empty?
670
+ print cyan,"No option lists found.",reset,"\n"
671
+ else
672
+ rows = option_type_lists.collect do |option_type_list|
673
+ {
674
+ id: option_type_list['id'],
675
+ name: option_type_list['name'],
676
+ description: option_type_list['description'],
677
+ type: option_type_list['type'],
678
+ size: option_type_list['listItems'] ? option_type_list['listItems'].size : ''
679
+ }
680
+ end
681
+ print cyan
682
+ tp rows, [
683
+ :id,
684
+ :name,
685
+ :description,
686
+ :type,
687
+ :size
688
+ ]
689
+ print reset
690
+ print_results_pagination(json_response)
691
+ end
692
+ print reset,"\n"
693
+ rescue RestClient::Exception => e
694
+ print_rest_exception(e, options)
695
+ exit 1
696
+ end
697
+ end
698
+
699
+ def option_lists_get(args)
700
+ options = {}
701
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
702
+ opts.banner = subcommand_usage("[name]")
703
+ build_common_options(opts, options, [:json, :dry_run])
704
+ opts.footer = "This outputs details about a particular Option List."
705
+ end
706
+ optparse.parse!(args)
707
+ if args.count < 1
708
+ puts optparse
709
+ exit 1
710
+ end
711
+
712
+ connect(options)
713
+ begin
714
+ if options[:dry_run]
715
+ if args[0].to_s =~ /\A\d{1,}\Z/
716
+ print_dry_run @option_type_lists_interface.dry.get(args[0].to_i)
717
+ else
718
+ print_dry_run @option_type_lists_interface.dry.list({name: args[0]})
719
+ end
720
+ return
721
+ end
722
+ option_type_list = find_option_type_list_by_name_or_id(args[0])
723
+ exit 1 if option_type_list.nil?
724
+
725
+ if options[:json]
726
+ print JSON.pretty_generate({optionTypeList: option_type_list}), "\n"
727
+ return
728
+ end
729
+
730
+ print_h1 "Option List Details"
731
+ print cyan
732
+ if option_type_list['type'] == 'manual'
733
+ print_description_list({
734
+ "ID" => 'id',
735
+ "Name" => 'name',
736
+ "Description" => 'description',
737
+ "Type" => lambda {|it| it['type'].to_s.capitalize },
738
+ }, option_type_list)
739
+ print_h2 "Initial Dataset"
740
+ print bright_black," #{option_type_list['initialDataset']}","\n",reset
741
+ else
742
+ print_description_list({
743
+ "ID" => 'id',
744
+ "Name" => 'name',
745
+ "Description" => 'description',
746
+ "Type" => lambda {|it| it['type'].to_s.capitalize },
747
+ "Source URL" => 'sourceUrl',
748
+ "Ignore SSL Errors" => lambda {|it| format_boolean it['ignoreSSLErrors'] },
749
+ "Source Method" => lambda {|it| it['sourceMethod'].to_s.upcase },
750
+ }, option_type_list)
751
+ if !option_type_list['initialDataset'].empty?
752
+ print_h2 "Initial Dataset"
753
+ print bright_black," #{option_type_list['initialDataset']}","\n",reset
754
+ end
755
+ if !option_type_list['translationScript'].empty?
756
+ print_h2 "Translation Script"
757
+ print bright_black," #{option_type_list['translationScript']}","\n",reset
758
+ end
759
+ end
760
+
761
+ print_h2 "List Items"
762
+ if option_type_list['listItems']
763
+ # puts "\tNAME\tVALUE"
764
+ # option_type_list['listItems'].each do |list_item|
765
+ # puts "\t#{list_item['name']}\t#{list_item['value']}"
766
+ # end
767
+ print cyan
768
+ tp option_type_list['listItems'], ['name', 'value']
769
+ else
770
+ puts "No data"
771
+ end
772
+ print reset,"\n"
773
+
774
+ rescue RestClient::Exception => e
775
+ print_rest_exception(e, options)
776
+ exit 1
777
+ end
778
+ end
779
+
780
+ def option_lists_add(args)
781
+ # JD: this is annoying because our option_types (for prompting and help)
782
+ # are the same type of object being managed here.., options options options
783
+ options = {}
784
+ my_option_types = nil
785
+ list_type = nil
786
+ optparse = OptionParser.new do|opts|
787
+ opts.banner = subcommand_usage("[type] [options]")
788
+ opts.on( '-t', '--type TYPE', "Option List Type. (rest, manual)" ) do |val|
789
+ list_type = val
790
+ # options[:options] ||= {}
791
+ # options[:options]['type'] = val
792
+ end
793
+ build_option_type_options(opts, options, new_option_type_list_option_types())
794
+ build_common_options(opts, options, [:options, :json, :dry_run])
795
+ end
796
+ optparse.parse!(args)
797
+
798
+ if !list_type
799
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => get_available_option_list_types, 'defaultValue' => 'rest', 'required' => true}], options[:options], @api_client, {})
800
+ list_type = v_prompt['type']
801
+ end
802
+
803
+ connect(options)
804
+ begin
805
+ params = Morpheus::Cli::OptionTypes.prompt(new_option_type_list_option_types(list_type), options[:options], @api_client, options[:params])
806
+ if params.key?('required')
807
+ params['required'] = ['on','true'].include?(params['required'].to_s)
808
+ end
809
+ params['type'] = list_type
810
+ list_payload = params
811
+ payload = {'optionTypeList' => list_payload}
812
+ if options[:dry_run]
813
+ print_dry_run @option_type_lists_interface.dry.create(payload)
814
+ return
815
+ end
816
+ json_response = @option_type_lists_interface.create(payload)
817
+ if options[:json]
818
+ print JSON.pretty_generate(json_response), "\n"
819
+ return
820
+ end
821
+ print_green_success "Added Option List #{list_payload['name']}"
822
+ #option_lists_list([])
823
+ option_type_list = json_response['optionTypeList']
824
+ if option_type_list
825
+ option_lists_get([option_type_list['id']])
826
+ end
827
+ rescue RestClient::Exception => e
828
+ print_rest_exception(e, options)
829
+ exit 1
830
+ end
831
+ end
832
+
833
+ def option_lists_update(args)
834
+ # JD: this is annoying because our option_types (for prompting and help)
835
+ # are the same type of object being managed here.., options options options
836
+ options = {}
837
+ optparse = OptionParser.new do|opts|
838
+ opts.banner = subcommand_usage("[name] [options]")
839
+ build_option_type_options(opts, options, update_option_type_list_option_types())
840
+ build_common_options(opts, options, [:options, :json, :dry_run])
841
+ end
842
+ optparse.parse!(args)
843
+ connect(options)
844
+ begin
845
+ option_type_list = find_option_type_list_by_name_or_id(args[0])
846
+ exit 1 if option_type_list.nil?
847
+
848
+ list_type = option_type_list['type']
849
+ prompt_options = update_option_type_list_option_types(list_type)
850
+ #params = options[:options] || {}
851
+ params = Morpheus::Cli::OptionTypes.no_prompt(prompt_options, options[:options], @api_client, options[:params])
852
+ if params.empty?
853
+ print_red_alert "Specify atleast one option to update"
854
+ puts optparse
855
+ exit 1
856
+ end
857
+ if params.key?('required')
858
+ params['required'] = ['on','true'].include?(params['required'].to_s)
859
+ end
860
+ list_payload = params
861
+ payload = {optionTypeList: list_payload}
862
+ if options[:dry_run]
863
+ print_dry_run @option_type_lists_interface.dry.update(option_type_list['id'], payload)
864
+ return
865
+ end
866
+ json_response = @option_type_lists_interface.update(option_type_list['id'], payload)
867
+ if options[:json]
868
+ print JSON.pretty_generate(json_response), "\n"
869
+ return
870
+ end
871
+ print_green_success "Updated Option List #{list_payload['name']}"
872
+ #option_lists_list([])
873
+ option_lists_get([option_type_list['id']])
874
+ rescue RestClient::Exception => e
875
+ print_rest_exception(e, options)
876
+ exit 1
877
+ end
878
+ end
879
+
880
+ def option_lists_remove(args)
881
+ options = {}
882
+ optparse = OptionParser.new do|opts|
883
+ opts.banner = subcommand_usage("[name]")
884
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run])
885
+ end
886
+ optparse.parse!(args)
887
+ if args.count < 1
888
+ puts optparse
889
+ exit 1
890
+ end
891
+ connect(options)
892
+
893
+ begin
894
+ option_type_list = find_option_type_list_by_name_or_id(args[0])
895
+ exit 1 if option_type_list.nil?
896
+
897
+ unless Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the option type #{option_type_list['name']}?", options)
898
+ exit
899
+ end
900
+ if options[:dry_run]
901
+ print_dry_run @option_type_lists_interface.dry.destroy(option_type_list['id'])
902
+ return
903
+ end
904
+ json_response = @option_type_lists_interface.destroy(option_type_list['id'])
905
+
906
+ if options[:json]
907
+ print JSON.pretty_generate(json_response), "\n"
908
+ return
909
+ end
910
+
911
+ print_green_success "Removed Option List #{option_type_list['name']}"
912
+ #option_lists_list([])
913
+ rescue RestClient::Exception => e
914
+ print_rest_exception(e, options)
915
+ exit 1
916
+ end
917
+ end
918
+
405
919
  private
406
920
 
407
921
  def find_custom_instance_type_by_code(code)
@@ -509,30 +1023,162 @@ class Morpheus::Cli::Library
509
1023
  has_another_port = options[:options] && options[:options]["exposedPort#{port_index}"]
510
1024
  add_another_port = has_another_port || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add an exposed port?"))
511
1025
  while add_another_port do
512
- field_context = "exposedPort#{port_index}"
1026
+ field_context = "exposedPort#{port_index}"
513
1027
 
514
- port = {}
515
- #port['name'] ||= "Port #{port_index}"
516
- port_label = port_index == 0 ? "Port" : "Port [#{port_index+1}]"
517
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => "#{port_label} Name", 'required' => false, 'description' => 'Choose a name for this port.', 'defaultValue' => port['name']}], options[:options])
518
- port['name'] = v_prompt[field_context]['name']
1028
+ port = {}
1029
+ #port['name'] ||= "Port #{port_index}"
1030
+ port_label = port_index == 0 ? "Port" : "Port [#{port_index+1}]"
1031
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => "#{port_label} Name", 'required' => false, 'description' => 'Choose a name for this port.', 'defaultValue' => port['name']}], options[:options])
1032
+ port['name'] = v_prompt[field_context]['name']
519
1033
 
520
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'port', 'type' => 'number', 'fieldLabel' => "#{port_label} Number", 'required' => true, 'description' => 'A port number. eg. 8001', 'defaultValue' => (port['port'] ? port['port'].to_i : nil)}], options[:options])
521
- port['port'] = v_prompt[field_context]['port']
1034
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'port', 'type' => 'number', 'fieldLabel' => "#{port_label} Number", 'required' => true, 'description' => 'A port number. eg. 8001', 'defaultValue' => (port['port'] ? port['port'].to_i : nil)}], options[:options])
1035
+ port['port'] = v_prompt[field_context]['port']
522
1036
 
523
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'loadBalanceProtocol', 'type' => 'select', 'fieldLabel' => "#{port_label} LB", 'selectOptions' => load_balance_protocols, 'required' => false, 'skipSingleOption' => true, 'description' => 'Choose a load balance protocol.', 'defaultValue' => port['loadBalanceProtocol']}], options[:options])
524
- port['loadBalanceProtocol'] = v_prompt[field_context]['loadBalanceProtocol']
1037
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'loadBalanceProtocol', 'type' => 'select', 'fieldLabel' => "#{port_label} LB", 'selectOptions' => load_balance_protocols, 'required' => false, 'skipSingleOption' => true, 'description' => 'Choose a load balance protocol.', 'defaultValue' => port['loadBalanceProtocol']}], options[:options])
1038
+ port['loadBalanceProtocol'] = v_prompt[field_context]['loadBalanceProtocol']
1039
+
1040
+ ports << port
1041
+ port_index += 1
1042
+ has_another_port = options[:options] && options[:options]["exposedPort#{port_index}"]
1043
+ add_another_port = has_another_port || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another exposed port?"))
1044
+
1045
+ end
525
1046
 
526
- ports << port
527
- port_index += 1
528
- has_another_port = options[:options] && options[:options]["exposedPort#{port_index}"]
529
- add_another_port = has_another_port || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another exposed port?"))
530
1047
 
1048
+ return ports
1049
+ end
1050
+
1051
+ def find_option_type_by_name_or_id(val)
1052
+ if val.to_s =~ /\A\d{1,}\Z/
1053
+ return find_option_type_by_id(val)
1054
+ else
1055
+ return find_option_type_by_name(val)
1056
+ end
1057
+ end
1058
+
1059
+ def find_option_type_by_id(id)
1060
+ begin
1061
+ json_response = @option_types_interface.get(id.to_i)
1062
+ return json_response['optionType']
1063
+ rescue RestClient::Exception => e
1064
+ if e.response && e.response.code == 404
1065
+ print_red_alert "Option Type not found by id #{id}"
1066
+ exit 1
1067
+ else
1068
+ raise e
531
1069
  end
1070
+ end
1071
+ end
1072
+
1073
+ def find_option_type_by_name(name)
1074
+ json_results = @option_types_interface.list({name: name.to_s})
1075
+ if json_results['optionTypes'].empty?
1076
+ print_red_alert "Option Type not found by name #{name}"
1077
+ exit 1
1078
+ end
1079
+ option_type = json_results['optionTypes'][0]
1080
+ return option_type
1081
+ end
532
1082
 
1083
+ def new_option_type_option_types
1084
+ [
1085
+ {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
1086
+ {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 2},
1087
+ {'fieldName' => 'fieldName', 'fieldLabel' => 'Field Name', 'type' => 'text', 'required' => true, 'description' => 'This is the input fieldName property that the value gets assigned to.', 'displayOrder' => 3},
1088
+ {'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => [{'name' => 'Text', 'value' => 'text'}, {'name' => 'Password', 'value' => 'password'}, {'name' => 'Number', 'value' => 'number'}, {'name' => 'Checkbox', 'value' => 'checkbox'}, {'name' => 'Select', 'value' => 'select'}, {'name' => 'Hidden', 'value' => 'hidden'}], 'defaultValue' => 'text', 'required' => true, 'displayOrder' => 4},
1089
+ {'fieldName' => 'fieldLabel', 'fieldLabel' => 'Field Label', 'type' => 'text', 'required' => true, 'description' => 'This is the input label that shows typically to the left of a custom option.', 'displayOrder' => 5},
1090
+ {'fieldName' => 'placeHolder', 'fieldLabel' => 'Placeholder', 'type' => 'text', 'displayOrder' => 6},
1091
+ {'fieldName' => 'defaultValue', 'fieldLabel' => 'Default Value', 'type' => 'text', 'displayOrder' => 7},
1092
+ {'fieldName' => 'required', 'fieldLabel' => 'Required', 'type' => 'checkbox', 'defaultValue' => 'off', 'displayOrder' => 8},
1093
+ ]
1094
+ end
533
1095
 
534
- return ports
1096
+ def update_option_type_option_types
1097
+ list = new_option_type_option_types
1098
+ list.each {|it|
1099
+ it.delete('required')
1100
+ it.delete('defaultValue')
1101
+ it.delete('skipSingleOption')
1102
+ }
1103
+ list
1104
+ end
1105
+
1106
+ def find_option_type_list_by_name_or_id(val)
1107
+ if val.to_s =~ /\A\d{1,}\Z/
1108
+ return find_option_type_list_by_id(val)
1109
+ else
1110
+ return find_option_type_list_by_name(val)
535
1111
  end
1112
+ end
536
1113
 
1114
+ def find_option_type_list_by_id(id)
1115
+ begin
1116
+ json_response = @option_type_lists_interface.get(id.to_i)
1117
+ return json_response['optionTypeList']
1118
+ rescue RestClient::Exception => e
1119
+ if e.response && e.response.code == 404
1120
+ print_red_alert "Option List not found by id #{id}"
1121
+ exit 1
1122
+ else
1123
+ raise e
1124
+ end
1125
+ end
1126
+ end
537
1127
 
1128
+ def find_option_type_list_by_name(name)
1129
+ json_results = @option_type_lists_interface.list({name: name.to_s})
1130
+ if json_results['optionTypeLists'].empty?
1131
+ print_red_alert "Option List not found by name #{name}"
1132
+ exit 1
1133
+ end
1134
+ option_type_list = json_results['optionTypeLists'][0]
1135
+ return option_type_list
1136
+ end
1137
+
1138
+ def get_available_option_list_types
1139
+ [
1140
+ {'name' => 'Rest', 'value' => 'rest'},
1141
+ {'name' => 'Manual', 'value' => 'manual'}
1142
+ ]
538
1143
  end
1144
+
1145
+ def find_option_list_type(code)
1146
+ get_available_option_list_types.find {|it| code == it['value'] || code == it['name'] }
1147
+ end
1148
+
1149
+ def new_option_type_list_option_types(list_type='rest')
1150
+ if list_type.to_s.downcase == 'rest'
1151
+ [
1152
+ {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
1153
+ {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 2},
1154
+ #{'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => get_available_option_list_types, 'defaultValue' => 'rest', 'required' => true, 'displayOrder' => 3},
1155
+ {'fieldName' => 'sourceUrl', 'fieldLabel' => 'Source Url', 'type' => 'text', 'required' => true, 'description' => "A REST URL can be used to fetch list data and is cached in the appliance database.", 'displayOrder' => 4},
1156
+ {'fieldName' => 'ignoreSSLErrors', 'fieldLabel' => 'Ignore SSL Errors', 'type' => 'checkbox', 'defaultValue' => 'off', 'displayOrder' => 5},
1157
+ {'fieldName' => 'sourceMethod', 'fieldLabel' => 'Source Method', 'type' => 'select', 'selectOptions' => [{'name' => 'GET', 'value' => 'GET'}, {'name' => 'POST', 'value' => 'POST'}], 'defaultValue' => 'GET', 'required' => true, 'displayOrder' => 6},
1158
+ {'fieldName' => 'initialDataset', 'fieldLabel' => 'Initial Dataset', 'type' => 'code-editor', 'description' => "Create an initial json dataset to be used as the collection for this option list. It should be a list containing objects with properties 'name', and 'value'. However, if there is a translation script, that will also be passed through.", 'displayOrder' => 7},
1159
+ {'fieldName' => 'translationScript', 'fieldLabel' => 'Translation Script', 'type' => 'code-editor', 'description' => "Create a js script to translate the result data object into an Array containing objects with properties name, and value. The input data is provided as data and the result should be put on the global variable results.", 'displayOrder' => 8},
1160
+ ]
1161
+ elsif list_type.to_s.downcase == 'manual'
1162
+ [
1163
+ {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
1164
+ {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 2},
1165
+ #{'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => [{'name' => 'Rest', 'value' => 'rest'}, {'name' => 'Manual', 'value' => 'manual'}], 'defaultValue' => 'rest', 'required' => true, 'displayOrder' => 3},
1166
+ {'fieldName' => 'initialDataset', 'fieldLabel' => 'Dataset', 'type' => 'code-editor', 'required' => true, 'description' => "Create an initial JSON or CSV dataset to be used as the collection for this option list. It should be a list containing objects with properties 'name', and 'value'.", 'displayOrder' => 4},
1167
+ ]
1168
+ else
1169
+ print_red_alert "Unknown Option List type '#{list_type}'"
1170
+ exit 1
1171
+ end
1172
+ end
1173
+
1174
+ def update_option_type_list_option_types(list_type='rest')
1175
+ list = new_option_type_list_option_types(list_type)
1176
+ list.each {|it|
1177
+ it.delete('required')
1178
+ it.delete('defaultValue')
1179
+ it.delete('skipSingleOption')
1180
+ }
1181
+ list
1182
+ end
1183
+
1184
+ end