morpheus-cli 5.5.2.1 → 5.5.3

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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/Dockerfile +1 -1
  4. data/README.md +57 -4
  5. data/Rakefile +9 -0
  6. data/bin/morpheus +4 -4
  7. data/lib/morpheus/api/api_client.rb +8 -2
  8. data/lib/morpheus/api/archive_buckets_interface.rb +1 -1
  9. data/lib/morpheus/api/archive_files_interface.rb +3 -3
  10. data/lib/morpheus/api/clients_interface.rb +2 -2
  11. data/lib/morpheus/api/clusters_interface.rb +8 -1
  12. data/lib/morpheus/api/containers_interface.rb +29 -16
  13. data/lib/morpheus/api/custom_instance_types_interface.rb +0 -2
  14. data/lib/morpheus/api/doc_interface.rb +8 -6
  15. data/lib/morpheus/api/file_copy_request_interface.rb +1 -1
  16. data/lib/morpheus/api/health_interface.rb +1 -1
  17. data/lib/morpheus/api/image_builder_interface.rb +3 -3
  18. data/lib/morpheus/api/instances_interface.rb +25 -0
  19. data/lib/morpheus/api/logs_interface.rb +2 -4
  20. data/lib/morpheus/api/monitoring_interface.rb +6 -6
  21. data/lib/morpheus/api/packages_interface.rb +1 -1
  22. data/lib/morpheus/api/reports_interface.rb +1 -1
  23. data/lib/morpheus/api/servers_interface.rb +9 -1
  24. data/lib/morpheus/api/storage_providers_interface.rb +2 -2
  25. data/lib/morpheus/api/virtual_images_interface.rb +1 -1
  26. data/lib/morpheus/api.rb +2 -0
  27. data/lib/morpheus/benchmarking.rb +1 -1
  28. data/lib/morpheus/cli/cli_command.rb +69 -36
  29. data/lib/morpheus/cli/cli_registry.rb +19 -10
  30. data/lib/morpheus/cli/commands/access_token_command.rb +1 -1
  31. data/lib/morpheus/cli/commands/apps.rb +1 -1
  32. data/lib/morpheus/cli/commands/archives_command.rb +25 -33
  33. data/lib/morpheus/cli/commands/blueprints_command.rb +10 -21
  34. data/lib/morpheus/cli/commands/boot_scripts_command.rb +2 -2
  35. data/lib/morpheus/cli/commands/cat_command.rb +1 -1
  36. data/lib/morpheus/cli/commands/catalog_item_types_command.rb +12 -12
  37. data/lib/morpheus/cli/commands/clouds.rb +3 -3
  38. data/lib/morpheus/cli/commands/clusters.rb +154 -3
  39. data/lib/morpheus/cli/commands/containers_command.rb +398 -253
  40. data/lib/morpheus/cli/commands/deployments.rb +1 -1
  41. data/lib/morpheus/cli/commands/deploys.rb +9 -9
  42. data/lib/morpheus/cli/commands/doc.rb +15 -16
  43. data/lib/morpheus/cli/commands/execution_request_command.rb +2 -2
  44. data/lib/morpheus/cli/commands/file_copy_request_command.rb +5 -5
  45. data/lib/morpheus/cli/commands/groups.rb +2 -2
  46. data/lib/morpheus/cli/commands/health_command.rb +4 -4
  47. data/lib/morpheus/cli/commands/hosts.rb +43 -5
  48. data/lib/morpheus/cli/commands/image_builder_command.rb +1 -1
  49. data/lib/morpheus/cli/commands/instances.rb +419 -148
  50. data/lib/morpheus/cli/commands/integrations_command.rb +22 -20
  51. data/lib/morpheus/cli/commands/key_pairs.rb +2 -2
  52. data/lib/morpheus/cli/commands/library_container_scripts_command.rb +2 -2
  53. data/lib/morpheus/cli/commands/library_container_templates_command.rb +2 -2
  54. data/lib/morpheus/cli/commands/library_instance_types_command.rb +3 -3
  55. data/lib/morpheus/cli/commands/library_spec_templates_command.rb +2 -2
  56. data/lib/morpheus/cli/commands/login.rb +1 -1
  57. data/lib/morpheus/cli/commands/man_command.rb +32 -18
  58. data/lib/morpheus/cli/commands/packages_command.rb +11 -11
  59. data/lib/morpheus/cli/commands/plugins.rb +1 -1
  60. data/lib/morpheus/cli/commands/policies_command.rb +4 -4
  61. data/lib/morpheus/cli/commands/preseed_scripts_command.rb +2 -2
  62. data/lib/morpheus/cli/commands/remote.rb +1 -1
  63. data/lib/morpheus/cli/commands/reports_command.rb +3 -3
  64. data/lib/morpheus/cli/commands/roles.rb +6 -3
  65. data/lib/morpheus/cli/commands/security_groups.rb +1 -1
  66. data/lib/morpheus/cli/commands/shell.rb +40 -62
  67. data/lib/morpheus/cli/commands/snapshots.rb +3 -5
  68. data/lib/morpheus/cli/commands/source_command.rb +8 -16
  69. data/lib/morpheus/cli/commands/storage_providers_command.rb +7 -7
  70. data/lib/morpheus/cli/commands/tasks.rb +2 -2
  71. data/lib/morpheus/cli/commands/vdi_pools_command.rb +6 -6
  72. data/lib/morpheus/cli/commands/view.rb +5 -1
  73. data/lib/morpheus/cli/commands/whitelabel_settings_command.rb +4 -4
  74. data/lib/morpheus/cli/commands/whoami.rb +2 -2
  75. data/lib/morpheus/cli/credentials.rb +30 -8
  76. data/lib/morpheus/cli/dot_file.rb +8 -15
  77. data/lib/morpheus/cli/error_handler.rb +16 -0
  78. data/lib/morpheus/cli/errors.rb +8 -1
  79. data/lib/morpheus/cli/mixins/print_helper.rb +17 -13
  80. data/lib/morpheus/cli/mixins/rest_command.rb +18 -18
  81. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +12 -12
  82. data/lib/morpheus/cli/option_parser.rb +5 -1
  83. data/lib/morpheus/cli/option_types.rb +59 -12
  84. data/lib/morpheus/cli/version.rb +1 -1
  85. data/lib/morpheus/cli.rb +26 -16
  86. data/lib/morpheus/ext/rest_client.rb +3 -2
  87. data/lib/morpheus/formatters.rb +1 -1
  88. data/lib/morpheus/logging.rb +4 -4
  89. data/lib/morpheus/morpkg.rb +4 -4
  90. data/lib/morpheus/rest_client.rb +2 -2
  91. data/lib/morpheus/routes.rb +2 -2
  92. data/lib/morpheus/terminal.rb +65 -16
  93. data/lib/morpheus.rb +1 -1
  94. data/morpheus-cli.gemspec +1 -0
  95. data/test/api/containers_interface_test.rb +68 -0
  96. data/test/api/doc_interface_test.rb +35 -0
  97. data/test/api/instances_interface_test.rb +22 -0
  98. data/test/api/whoami_interface_test.rb +14 -0
  99. data/test/cli/access_token_test.rb +36 -0
  100. data/test/cli/auth_test.rb +82 -0
  101. data/test/cli/cli_test.rb +48 -0
  102. data/test/cli/containers_test.rb +92 -0
  103. data/test/cli/doc_test.rb +35 -0
  104. data/test/cli/help_test.rb +25 -0
  105. data/test/cli/instances_test.rb +36 -0
  106. data/test/cli/man_test.rb +14 -0
  107. data/test/cli/remote_test.rb +89 -0
  108. data/test/cli/roles_test.rb +34 -0
  109. data/test/cli/shell_test.rb +81 -0
  110. data/test/cli/version_test.rb +23 -0
  111. data/test/cli/view_test.rb +55 -0
  112. data/test/cli/whoami_test.rb +17 -0
  113. data/test/morpheus_test.rb +16 -0
  114. data/test/test_case.rb +338 -0
  115. data/test/test_config.rb +137 -0
  116. data/test/test_data_helper.rb +97 -0
  117. metadata +61 -3
@@ -21,7 +21,8 @@ class Morpheus::Cli::Instances
21
21
  :security_groups, :apply_security_groups, :run_workflow,
22
22
  :import_snapshot, :snapshot, :snapshots, :revert_to_snapshot, :remove_all_snapshots, :remove_all_container_snapshots, :create_linked_clone,
23
23
  :console, :status_check, {:containers => :list_containers},
24
- :scaling, {:'scaling-update' => :scaling_update},
24
+ :scaling, :update_scaling, {:'scaling-update' => :scaling_update},
25
+ {:'schedules' => :list_schedules}, :get_schedule, :add_schedule, :update_schedule, :remove_schedule, # these are scaling schedules..
25
26
  :wiki, :update_wiki,
26
27
  :update_network_label,
27
28
  {:exec => :execution_request},
@@ -34,6 +35,7 @@ class Morpheus::Cli::Instances
34
35
 
35
36
  # hide these for now
36
37
  set_subcommands_hidden :prepare_apply
38
+ set_subcommands_hidden :'scaling-update' # renamed to upate-scaling
37
39
 
38
40
  def initialize()
39
41
  #@appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
@@ -832,7 +834,7 @@ class Morpheus::Cli::Instances
832
834
  build_option_type_options(opts, options, update_wiki_page_option_types)
833
835
  opts.on('--file FILE', "File containing the wiki content. This can be used instead of --content") do |filename|
834
836
  full_filename = File.expand_path(filename)
835
- if File.exists?(full_filename)
837
+ if File.exist?(full_filename)
836
838
  params['content'] = File.read(full_filename)
837
839
  else
838
840
  print_red_alert "File not found: #{full_filename}"
@@ -3767,7 +3769,7 @@ EOT
3767
3769
  end
3768
3770
 
3769
3771
  instance_threshold = json_response['instanceThreshold']
3770
-
3772
+ instance_schedules = json_response['instanceSchedules']
3771
3773
  title = "Instance Scaling: [#{instance['id']}] #{instance['name']} (#{instance['instanceType']['name']})"
3772
3774
  print_h1 title, [], options
3773
3775
  if instance_threshold.empty?
@@ -3776,6 +3778,11 @@ EOT
3776
3778
  # print_h1 "Threshold Settings", [], options
3777
3779
  print cyan
3778
3780
  print_instance_threshold_description_list(instance_threshold)
3781
+
3782
+ if instance_schedules && instance_schedules.size > 0
3783
+ print_h2 "Instance Schedules"
3784
+ print as_pretty_table(instance_schedules, instance_schedule_list_column_definitions(options).upcase_keys!, options)
3785
+ end
3779
3786
  end
3780
3787
  print reset, "\n"
3781
3788
  return 0
@@ -3783,124 +3790,323 @@ EOT
3783
3790
  end
3784
3791
 
3785
3792
  def scaling_update(args)
3786
- usage = "Usage: morpheus instances scaling-update [instance] [options]"
3793
+ print_error "#{yellow}DEPRECATION WARNING: `instances scaling-update` has been renamed to `instances update-scaling`. Please use `instances update-scaling` instead.#{reset}\n"
3794
+ update_scaling(args)
3795
+ end
3796
+
3797
+ def update_scaling(args)
3787
3798
  options = {}
3788
3799
  optparse = Morpheus::Cli::OptionParser.new do|opts|
3789
3800
  opts.banner = subcommand_usage("[instance]")
3790
- build_option_type_options(opts, options, instance_scaling_option_types(nil))
3791
- build_common_options(opts, options, [:options, :json, :dry_run, :remote])
3792
- opts.footer = "Update scaling threshold information for an instance."
3801
+ build_option_type_options(opts, options, update_instance_scaling_option_types)
3802
+ build_option_type_options(opts, options, instance_threshold_option_types)
3803
+ build_standard_update_options(opts, options)
3804
+ opts.footer = "Update scaling threshold settings for an instance."
3793
3805
  end
3794
3806
  optparse.parse!(args)
3795
- # if args.count < 1
3796
- if args.count != 1
3797
- print_error Morpheus::Terminal.angry_prompt
3798
- puts_error "#{command_name} scaling-update requires only one argument [id or name]\n#{optparse}"
3799
- return 1
3800
- end
3807
+ verify_args!(args:args, optparse:optparse, count:1)
3801
3808
  connect(options)
3802
-
3803
- begin
3804
-
3805
- instance = find_instance_by_name_or_id(args[0])
3806
- return 1 if instance.nil?
3807
- instance_threshold = @instances_interface.threshold(instance['id'])['instanceThreshold'] || {}
3808
- my_option_types = instance_scaling_option_types(instance)
3809
-
3810
- # preserve current values by setting the prompt options defaultValue attribute
3811
- # note: checkbox type converts true,false to 'on','off'
3812
- my_option_types.each do |opt|
3813
- field_key = opt['fieldName'] # .sub('instanceThreshold.', '')
3814
- if instance_threshold[field_key] != nil
3815
- opt['defaultValue'] = instance_threshold[field_key]
3816
- end
3817
- end
3818
-
3819
- # params = Morpheus::Cli::OptionTypes.prompt(my_option_types, options[:options], @api_client, {})
3820
-
3821
- # ok, gotta split these inputs into sections with conditional logic
3809
+ # load objects
3810
+ instance = find_instance_by_name_or_id(args[0])
3811
+ return 1 if instance.nil?
3812
+ instance_threshold = @instances_interface.threshold(instance['id'])['instanceThreshold'] || {}
3813
+ # construct payload
3814
+ object_key = 'instanceThreshold'
3815
+ payload = parse_payload(options, object_key)
3816
+ if !payload
3817
+ # payload = {object_key => {}}
3818
+ payload = {object_key => parse_passed_options(options, exclude: ['sourceThresholdId'])}
3822
3819
  params = {}
3823
-
3824
- option_types_group = my_option_types.select {|opt| ['autoUp', 'autoDown'].include?(opt['fieldName']) }
3825
- params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
3826
-
3827
- option_types_group = my_option_types.select {|opt| ['zoneId'].include?(opt['fieldName']) }
3828
- params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
3829
- if params['zoneId']
3830
- if params['zoneId'] == '' || params['zoneId'] == 'null' || params['zoneId'].to_s == '0'
3831
- params['zoneId'] = 0
3832
- else
3833
- params['zoneId'] = params['zoneId'].to_i
3820
+ params.deep_merge! Morpheus::Cli::OptionTypes.prompt(update_instance_scaling_option_types, options[:options], @api_client, {})
3821
+ source_threshold_id = params.delete('sourceThresholdId')
3822
+ customize_threshold_prompt = true
3823
+ params ||= {}
3824
+ if source_threshold_id.to_s != '' && source_threshold_id.to_s != 'custom'
3825
+ params['sourceThresholdId']= source_threshold_id.to_i
3826
+ customize_threshold_prompt = false
3827
+ end
3828
+ # always parse the threshold options but customize_threshold means prompt also
3829
+ my_option_types = instance_threshold_option_types
3830
+ if customize_threshold_prompt
3831
+ # preserve all current values by setting the prompt options defaultValue attribute
3832
+ my_option_types.each do |opt|
3833
+ field_key = opt['fieldName']
3834
+ if instance_threshold[field_key] != nil
3835
+ opt['defaultValue'] = instance_threshold[field_key]
3836
+ end
3834
3837
  end
3835
- end
3836
-
3837
- option_types_group = my_option_types.select {|opt| ['minCount', 'maxCount'].include?(opt['fieldName']) }
3838
- params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
3839
-
3840
- option_types_group = my_option_types.select {|opt| ['memoryEnabled'].include?(opt['fieldName']) }
3841
- params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
3842
- if params['memoryEnabled'] == 'on' || params['memoryEnabled'] == true
3843
- option_types_group = my_option_types.select {|opt| ['minMemory', 'maxMemory'].include?(opt['fieldName']) }
3844
- params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
3838
+ params.deep_merge! Morpheus::Cli::OptionTypes.prompt(my_option_types, options[:options], @api_client, {})
3845
3839
  else
3846
- params['minMemory'] = nil
3847
- params['maxMemory'] = nil
3848
- end
3849
-
3850
- option_types_group = my_option_types.select {|opt| ['diskEnabled'].include?(opt['fieldName']) }
3851
- params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
3852
- if params['diskEnabled'] == 'on' || params['diskEnabled'] == true
3853
- option_types_group = my_option_types.select {|opt| ['minDisk', 'maxDisk'].include?(opt['fieldName']) }
3854
- params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
3855
- else
3856
- params['minDisk'] = nil
3857
- params['maxDisk'] = nil
3840
+ # preserve current values by setting the prompt options defaultValue attribute
3841
+ # only prompt for autoUp and autoDown
3842
+ my_option_types.each do |opt|
3843
+ field_key = opt['fieldName']
3844
+ if ['autoUp','autoDown'].include?(field_key)
3845
+ if instance_threshold[field_key] != nil
3846
+ opt['defaultValue'] = instance_threshold[field_key]
3847
+ end
3848
+ opt['noPrompt'] = false
3849
+ else
3850
+ opt['noPrompt'] = true
3851
+ end
3852
+ end
3853
+ params.deep_merge! Morpheus::Cli::OptionTypes.prompt(my_option_types, options[:options], @api_client, {})
3858
3854
  end
3855
+ params.booleanize! # convert checkbox "on" and "off" to true and false
3856
+ payload[object_key].deep_merge!(params)
3857
+ end
3858
+ # unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to update the scaling settings for instance '#{instance['name']}'?", options)
3859
+ # return 9, "aborted command"
3860
+ # end
3861
+ @instances_interface.setopts(options)
3862
+ if options[:dry_run]
3863
+ print_dry_run @instances_interface.dry.update_threshold(instance['id'], payload)
3864
+ return
3865
+ end
3866
+ json_response = @instances_interface.update_threshold(instance['id'], payload)
3867
+ render_response(json_response, options) do
3868
+ print_green_success "Updated scaling settings for instance #{instance['name']}"
3869
+ # return _get_inventory(integration, integration_inventory["id"], {}, options)
3870
+ end
3871
+ return 0, nil
3872
+ end
3859
3873
 
3860
- option_types_group = my_option_types.select {|opt| ['cpuEnabled'].include?(opt['fieldName']) }
3861
- params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
3862
- if params['cpuEnabled'] == 'on' || params['cpuEnabled'] == true
3863
- option_types_group = my_option_types.select {|opt| ['minCpu', 'maxCpu'].include?(opt['fieldName']) }
3864
- params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
3874
+ def list_schedules(args)
3875
+ params = {}
3876
+ options = {}
3877
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
3878
+ opts.banner = subcommand_usage("[instance]")
3879
+ build_standard_get_options(opts, options) # build_standard_list_options(opts, options) # phrase,max,etc is not supported
3880
+ opts.footer = <<-EOT
3881
+ List instance scaling threshold schedules.
3882
+ [instance] is required. This is the name or id of an instance
3883
+ EOT
3884
+ end
3885
+ optparse.parse!(args)
3886
+ verify_args!(args:args, optparse:optparse, count:1)
3887
+ connect(options)
3888
+ parse_get_options!(args, options, params) # parse_list_options!(args, options, params) # phrase,max,etc is not supported
3889
+ instance = find_instance_by_name_or_id(args[0])
3890
+ return 1 if instance.nil?
3891
+ @instances_interface.setopts(options)
3892
+ if options[:dry_run]
3893
+ print_dry_run @instances_interface.dry.list_schedules(instance['id'], params)
3894
+ return 0, nil
3895
+ end
3896
+ json_response = @instances_interface.list_schedules(instance['id'], params)
3897
+ list_key = 'instanceSchedules'
3898
+ render_response(json_response, options, list_key) do
3899
+ records = json_response[list_key]
3900
+ title = "Morpheus Instance Schedules"
3901
+ subtitles = []
3902
+ subtitles += parse_list_subtitles(options)
3903
+ print_h1 title, subtitles, options
3904
+ if records.nil? || records.empty?
3905
+ print cyan,"No schedules found.",reset,"\n"
3865
3906
  else
3866
- params['minCpu'] = nil
3867
- params['maxCpu'] = nil
3907
+ print as_pretty_table(records, instance_schedule_list_column_definitions(options).upcase_keys!, options)
3908
+ print_results_pagination(json_response) if json_response['meta']
3868
3909
  end
3910
+ print reset,"\n"
3911
+ end
3912
+ return 0, nil
3869
3913
 
3870
- # argh, convert on/off to true/false
3871
- # this needs a global solution...
3872
- params.each do |k,v|
3873
- if v == 'on' || v == 'true' || v == 'yes'
3874
- params[k] = true
3875
- elsif v == 'off' || v == 'false' || v == 'no'
3876
- params[k] = false
3877
- end
3878
- end
3914
+ end
3879
3915
 
3880
- payload = {
3881
- 'instanceThreshold' => {}
3882
- }
3883
- payload['instanceThreshold'].merge!(params)
3916
+ def get_schedule(args)
3917
+ params = {}
3918
+ options = {}
3919
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
3920
+ opts.banner = subcommand_usage("[instance] [schedule]")
3921
+ # build_standard_list_options(opts, options)
3922
+ build_standard_get_options(opts, options) # phrase,max,etc is not supported
3923
+ opts.footer = <<-EOT
3924
+ Get details about an instance scaling threshold schedule.
3925
+ [instance] is required. This is the name or id of an instance
3926
+ [schedule] is required. This is id of an instance schedule
3927
+ EOT
3928
+ end
3929
+ optparse.parse!(args)
3930
+ verify_args!(args:args, optparse:optparse, count:2)
3931
+ connect(options)
3932
+ parse_get_options!(args, options, params)
3933
+ instance = find_instance_by_name_or_id(args[0])
3934
+ return 1 if instance.nil?
3935
+ @instances_interface.setopts(options)
3936
+ if options[:dry_run]
3937
+ print_dry_run @instances_interface.dry.list(instance['id'], args[1], params)
3938
+ return 0, nil
3939
+ end
3940
+ json_response = @instances_interface.get_schedule(instance['id'], args[1], params)
3941
+ object_key = 'instanceSchedule'
3942
+ render_response(json_response, options, object_key) do
3943
+ record = json_response[object_key]
3944
+ title = "Instance Schedule Details"
3945
+ print_h1 title, options
3946
+ columns = instance_schedule_column_definitions(options)
3947
+ print print_description_list(columns, record, options)
3948
+ print reset,"\n"
3949
+ end
3950
+ return 0, nil
3951
+ end
3884
3952
 
3885
- # unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to update the scaling settings for instance '#{instance['name']}'?", options)
3886
- # return 9, "aborted command"
3953
+ def add_schedule(args)
3954
+ options = {}
3955
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
3956
+ opts.banner = subcommand_usage("[instance]")
3957
+ # opts.on( '--threshold VALUE', String, "Threshold template to apply scaling settings with. Default is no template (custom)." ) do |val|
3958
+ # options[:threshold] = val
3887
3959
  # end
3888
- @instances_interface.setopts(options)
3889
- if options[:dry_run]
3890
- print_dry_run @instances_interface.dry.update_threshold(instance['id'], payload)
3891
- return
3892
- end
3893
- json_response = @instances_interface.update_threshold(instance['id'], payload)
3894
- if options[:json]
3895
- puts as_json(json_response, options)
3960
+ build_option_type_options(opts, options, add_instance_schedule_option_types)
3961
+ build_option_type_options(opts, options, instance_threshold_option_types)
3962
+ build_standard_update_options(opts, options)
3963
+ opts.footer = <<-EOT
3964
+ Update an existing instance scaling threshold schedule
3965
+ [instance] is required. This is the name or id of an instance
3966
+ EOT
3967
+ end
3968
+ optparse.parse!(args)
3969
+ verify_args!(args:args, optparse:optparse, count:1)
3970
+ connect(options)
3971
+ instance = find_instance_by_name_or_id(args[0])
3972
+ return 1 if instance.nil?
3973
+ # construct payload
3974
+ object_key = 'instanceSchedule'
3975
+ payload = parse_payload(options, object_key)
3976
+ if !payload
3977
+ # payload = {object_key => {}}
3978
+ # support -O option but avoid duplicate threshold settings... so -O maxCpu, goes under threshold only
3979
+ # could just use options -O threshold.maxCpu instead, which is what the api wants...
3980
+ payload = {object_key => parse_passed_options(options, exclude: ['sourceThresholdId'] + instance_threshold_option_types.collect {|i|i['fieldName']})}
3981
+ params = {}
3982
+ params.deep_merge! Morpheus::Cli::OptionTypes.prompt(add_instance_schedule_option_types, options[:options], @api_client, {})
3983
+ source_threshold_id = params.delete('sourceThresholdId')
3984
+ customize_threshold_prompt = true
3985
+ params['threshold'] ||= {}
3986
+ if source_threshold_id.to_s != '' && source_threshold_id.to_s != 'custom'
3987
+ #params['threshold']['id']= source_threshold_id
3988
+ params['threshold']['sourceThresholdId']= source_threshold_id.to_i
3989
+ customize_threshold_prompt = false
3990
+ end
3991
+ # always parse the threshold options but customize_threshold means prompt also
3992
+ if customize_threshold_prompt
3993
+ params['threshold'].deep_merge! Morpheus::Cli::OptionTypes.prompt(instance_threshold_option_types, options[:options], @api_client, {})
3896
3994
  else
3897
- print_green_success "Updated scaling settings for instance #{instance['name']}"
3995
+ params['threshold'].deep_merge! Morpheus::Cli::OptionTypes.no_prompt(instance_threshold_option_types, options[:options], @api_client, {})
3898
3996
  end
3899
- return 0
3900
- rescue RestClient::Exception => e
3901
- print_rest_exception(e, options)
3902
- exit 1
3997
+ params.booleanize! # convert checkbox "on" and "off" to true and false
3998
+ payload[object_key].deep_merge!(params)
3999
+ # unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to update the scaling settings for instance '#{instance['name']}' with the above scaling schedule?", options)
4000
+ # return 9, "aborted command"
4001
+ # end
3903
4002
  end
4003
+ @instances_interface.setopts(options)
4004
+ if options[:dry_run]
4005
+ print_dry_run @instances_interface.dry.create_schedule(instance['id'], payload)
4006
+ return 0, nil
4007
+ end
4008
+ json_response = @instances_interface.create_schedule(instance['id'], payload)
4009
+ render_response(json_response, options) do
4010
+ print_green_success "Added scaling schedule for instance #{instance['name']}"
4011
+ #_scaling(instance['id'], options)
4012
+ end
4013
+ return 0, nil
4014
+ end
4015
+
4016
+ def update_schedule(args)
4017
+ options = {}
4018
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
4019
+ opts.banner = subcommand_usage("[instance] [schedule]")
4020
+ build_option_type_options(opts, options, update_instance_schedule_option_types)
4021
+ build_option_type_options(opts, options, instance_threshold_option_types)
4022
+ build_standard_update_options(opts, options)
4023
+ opts.footer = <<-EOT
4024
+ Update an existing instance scaling threshold schedule.
4025
+ [instance] is required. This is the name or id of an instance
4026
+ [schedule] is required. This is id of an instance schedule
4027
+ EOT
4028
+ end
4029
+ optparse.parse!(args)
4030
+ verify_args!(args:args, optparse:optparse, count:2)
4031
+ connect(options)
4032
+ instance = find_instance_by_name_or_id(args[0])
4033
+ return 1, "Instance not found for '#{args[0]}'" if instance.nil?
4034
+ instance_schedule = find_instance_schedule_by_id(instance['id'], args[1])
4035
+ return 1, "Instance schedule not found for '#{args[1]}'" if instance_schedule.nil?
4036
+ # construct payload
4037
+ object_key = 'instanceSchedule'
4038
+ payload = parse_payload(options, object_key)
4039
+ if !payload
4040
+ # payload = {object_key => {}}
4041
+ # support -O option but avoid duplicate threshold settings... so -O maxCpu, goes under threshold only
4042
+ # could just use options -O threshold.maxCpu instead, which is what the api wants...
4043
+ payload = {object_key => parse_passed_options(options, exclude: ['sourceThresholdId'] + instance_threshold_option_types.collect {|i|i['fieldName']})}
4044
+ params = {}
4045
+ params.deep_merge! Morpheus::Cli::OptionTypes.no_prompt(update_instance_schedule_option_types, options[:options], @api_client, {})
4046
+ source_threshold_id = params.delete('sourceThresholdId')
4047
+ customize_threshold_prompt = true
4048
+ params['threshold'] ||= {}
4049
+ if source_threshold_id.to_s != '' && source_threshold_id.to_s != 'custom'
4050
+ #params['threshold']['id']= source_threshold_id
4051
+ params['threshold']['sourceThresholdId']= source_threshold_id.to_i
4052
+ customize_threshold_prompt = false
4053
+ end
4054
+ params['threshold'].deep_merge! Morpheus::Cli::OptionTypes.no_prompt(instance_threshold_option_types, options[:options], @api_client, {})
4055
+ params.booleanize! # convert checkbox "on" and "off" to true and false
4056
+ payload[object_key].deep_merge!(params)
4057
+ if (payload[object_key].keys - ['threshold']).empty? && payload[object_key]['threshold'].empty?
4058
+ raise_command_error "Specify at least one option to update.\n#{optparse}"
4059
+ end
4060
+ # unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to update the scaling settings for instance '#{instance['name']}' with the above scaling schedule?", options)
4061
+ # return 9, "aborted command"
4062
+ # end
4063
+ end
4064
+ @instances_interface.setopts(options)
4065
+ if options[:dry_run]
4066
+ print_dry_run @instances_interface.dry.update_schedule(instance['id'], instance_schedule['id'], payload)
4067
+ return 0, nil
4068
+ end
4069
+ json_response = @instances_interface.update_schedule(instance['id'], instance_schedule['id'], payload)
4070
+ render_response(json_response, options) do
4071
+ print_green_success "Updated scaling schedule for instance #{instance['name']}"
4072
+ #_scaling(instance['id'], options)
4073
+ end
4074
+ return 0, nil
4075
+ end
4076
+
4077
+ def remove_schedule(args)
4078
+ params = {}
4079
+ options = {}
4080
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
4081
+ opts.banner = subcommand_usage("[instance] [schedule]")
4082
+ build_standard_remove_options(opts, options)
4083
+ opts.footer = <<-EOT
4084
+ Delete an existing instance scaling threshold schedule
4085
+ [instance] is required. This is the name or id of an instance
4086
+ [schedule] is required. This is id of an instance schedule
4087
+ EOT
4088
+ end
4089
+ optparse.parse!(args)
4090
+ verify_args!(args:args, optparse:optparse, count:2)
4091
+ connect(options)
4092
+ params.merge!(parse_query_options(options))
4093
+ instance = find_instance_by_name_or_id(args[0])
4094
+ return 1, "Instance not found for '#{args[0]}'" if instance.nil?
4095
+ instance_schedule = find_instance_schedule_by_id(instance['id'], args[1])
4096
+ return 1, "Instance schedule not found for '#{args[1]}'" if instance_schedule.nil?
4097
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the instance schedule #{instance_schedule['id']}?")
4098
+ return 9, "aborted"
4099
+ end
4100
+ @instances_interface.setopts(options)
4101
+ if options[:dry_run]
4102
+ print_dry_run @instances_interface.dry.destroy_schedule(instance['id'], instance_schedule['id'], params)
4103
+ return 0, nil
4104
+ end
4105
+ json_response = @instances_interface.destroy_schedule(instance['id'], instance_schedule['id'], params)
4106
+ render_response(json_response, options) do
4107
+ print_green_success "Removed instance schedule #{instance_schedule['id']}"
4108
+ end
4109
+ return 0, nil
3904
4110
  end
3905
4111
 
3906
4112
  def load_balancer_update(args)
@@ -3990,7 +4196,6 @@ EOT
3990
4196
  options = {}
3991
4197
  optparse = Morpheus::Cli::OptionParser.new do|opts|
3992
4198
  opts.banner = subcommand_usage("[instance]")
3993
- build_option_type_options(opts, options, instance_scaling_option_types(nil))
3994
4199
  build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
3995
4200
  opts.footer = "Remove a load balancer from an instance."
3996
4201
  end
@@ -4364,7 +4569,7 @@ EOT
4364
4569
  end
4365
4570
  opts.on('--file FILE', "File containing the script. This can be used instead of --script" ) do |filename|
4366
4571
  full_filename = File.expand_path(filename)
4367
- if File.exists?(full_filename)
4572
+ if File.exist?(full_filename)
4368
4573
  script_content = File.read(full_filename)
4369
4574
  else
4370
4575
  print_red_alert "File not found: #{full_filename}"
@@ -5104,50 +5309,25 @@ private
5104
5309
  end
5105
5310
  end
5106
5311
 
5107
- def instance_scaling_option_types(instance=nil)
5108
-
5109
- # Group
5110
- group_id = nil
5111
- if instance && instance['group']
5112
- group_id = instance['group']['id']
5113
- end
5114
-
5115
- available_clouds = group_id ? get_available_clouds(group_id) : []
5116
- zone_dropdown = [{'name' => 'Use Scale Priority', 'value' => 0}]
5117
- zone_dropdown += available_clouds.collect {|cloud| {'name' => cloud['name'], 'value' => cloud['id']} }
5118
-
5119
- list = []
5120
- list << {'fieldName' => 'autoUp', 'fieldLabel' => 'Auto Upscale', 'type' => 'checkbox', 'description' => 'Enable auto upscaling', 'required' => true, 'defaultValue' => false}
5121
- list << {'fieldName' => 'autoDown', 'fieldLabel' => 'Auto Downscale', 'type' => 'checkbox', 'description' => 'Enable auto downscaling', 'required' => true, 'defaultValue' => false}
5122
-
5123
- list << {'fieldName' => 'zoneId', 'fieldLabel' => 'Cloud', 'type' => 'select', 'selectOptions' => zone_dropdown, 'description' => "Choose a cloud to scale into.", 'placeHolder' => 'ID'}
5124
-
5125
- list << {'fieldName' => 'minCount', 'fieldLabel' => 'Min Count', 'type' => 'number', 'description' => 'Minimum number of nodes', 'placeHolder' => 'NUMBER'}
5126
- list << {'fieldName' => 'maxCount', 'fieldLabel' => 'Max Count', 'type' => 'number', 'description' => 'Maximum number of nodes', 'placeHolder' => 'NUMBER'}
5127
-
5128
-
5129
- list << {'fieldName' => 'memoryEnabled', 'fieldLabel' => 'Enable Memory Threshold', 'type' => 'checkbox', 'description' => 'Scale when memory thresholds are met.', 'required' => true, 'defaultValue' => false}
5130
- list << {'fieldName' => 'minMemory', 'fieldLabel' => 'Min Memory', 'type' => 'number', 'description' => 'Minimum memory percent (0-100)', 'placeHolder' => 'PERCENT'}
5131
- list << {'fieldName' => 'maxMemory', 'fieldLabel' => 'Max Memory', 'type' => 'number', 'description' => 'Maximum memory percent (0-100)', 'placeHolder' => 'PERCENT'}
5132
-
5133
- list << {'fieldName' => 'diskEnabled', 'fieldLabel' => 'Enable Disk Threshold', 'type' => 'checkbox', 'description' => 'Scale when disk thresholds are met.', 'required' => true, 'defaultValue' => false}
5134
- list << {'fieldName' => 'minDisk', 'fieldLabel' => 'Min Disk', 'type' => 'number', 'description' => 'Minimum storage percent (0-100)', 'placeHolder' => 'PERCENT'}
5135
- list << {'fieldName' => 'maxDisk', 'fieldLabel' => 'Max Disk', 'type' => 'number', 'description' => 'Maximum storage percent (0-100)', 'placeHolder' => 'PERCENT'}
5136
-
5137
- list << {'fieldName' => 'cpuEnabled', 'fieldLabel' => 'Enable CPU Threshold', 'type' => 'checkbox', 'description' => 'Scale when cpu thresholds are met.', 'required' => true, 'defaultValue' => false}
5138
- list << {'fieldName' => 'minCpu', 'fieldLabel' => 'Min CPU', 'type' => 'number', 'description' => 'Minimum CPU percent (0-100)', 'placeHolder' => 'PERCENT'}
5139
- list << {'fieldName' => 'maxCpu', 'fieldLabel' => 'Max CPU', 'type' => 'number', 'description' => 'Maximum CPU percent (0-100)', 'placeHolder' => 'PERCENT'}
5140
-
5141
- # list << {'fieldName' => 'iopsEnabled', 'fieldLabel' => 'Enable Iops Threshold', 'type' => 'checkbox', 'description' => 'Scale when iops thresholds are met.'}
5142
- # list << {'fieldName' => 'minIops', 'fieldLabel' => 'Min Iops', 'type' => 'number', 'description' => 'Minimum iops'}
5143
- # list << {'fieldName' => 'maxIops', 'fieldLabel' => 'Max Iops', 'type' => 'number', 'description' => 'Maximum iops'}
5144
-
5145
- # list << {'fieldName' => 'networkEnabled', 'fieldLabel' => 'Enable Iops Threshold', 'type' => 'checkbox', 'description' => 'Scale when network thresholds are met.'}
5146
- # list << {'fieldName' => 'minNetwork', 'fieldLabel' => 'Min Network', 'type' => 'number', 'description' => 'Minimum networking'}
5147
-
5148
- # list << {'fieldName' => 'comment', 'fieldLabel' => 'Comment', 'type' => 'text', 'description' => 'Comment on these scaling settings.'}
5149
-
5150
- list
5312
+ def update_instance_scaling_option_types()
5313
+ [
5314
+ {'code' => 'sourceThresholdId', 'switch' => 'threshold', 'fieldName' => 'sourceThresholdId', 'fieldLabel' => 'Threshold', 'type' => 'select', 'optionSource' => lambda {|api_client, api_params|
5315
+ [{'name' => 'Custom', 'value' => 'custom'}] + api_client.options.options_for_source('instanceThresholdTemplates')['data'] rescue []
5316
+ }, 'description' => "Threshold template to use as source for scaling threshold settings.", 'defaultValue' => 'custom', 'required' => true}, #, 'required' => true, 'defaultValue' => ''},
5317
+ # {'fieldName' => 'autoUp', 'fieldLabel' => 'Auto Upscale', 'type' => 'checkbox', 'description' => 'Enable auto upscaling'},
5318
+ # {'fieldName' => 'autoDown', 'fieldLabel' => 'Auto Downscale', 'type' => 'checkbox', 'description' => 'Enable auto downscaling'},
5319
+ # {'dependsOnCode' => 'sourceThresholdId:custom', 'fieldName' => 'minCount', 'fieldLabel' => 'Min Count', 'type' => 'number', 'description' => 'Minimum number of nodes'},
5320
+ # {'dependsOnCode' => 'sourceThresholdId:custom', 'fieldName' => 'maxCount', 'fieldLabel' => 'Max Count', 'type' => 'number', 'description' => 'Maximum number of nodes'},
5321
+ # {'dependsOnCode' => 'sourceThresholdId:custom', 'fieldName' => 'cpuEnabled', 'fieldLabel' => 'Enable CPU Threshold', 'type' => 'checkbox', 'description' => 'Scale when CPU thresholds are met.'},
5322
+ # {'dependsOnCode' => 'sourceThresholdId:custom', 'fieldName' => 'minCpu', 'fieldLabel' => 'Min CPU', 'type' => 'number', 'description' => 'Minimum CPU percent (0-100)'},
5323
+ # {'dependsOnCode' => 'sourceThresholdId:custom', 'fieldName' => 'maxCpu', 'fieldLabel' => 'Max CPU', 'type' => 'number', 'description' => 'Maximum CPU percent (0-100)'},
5324
+ # {'dependsOnCode' => 'sourceThresholdId:custom', 'fieldName' => 'memoryEnabled', 'fieldLabel' => 'Enable Memory Threshold', 'type' => 'checkbox', 'description' => 'Scale when memory thresholds are met.'},
5325
+ # {'dependsOnCode' => 'sourceThresholdId:custom', 'fieldName' => 'minMemory', 'fieldLabel' => 'Min Memory', 'type' => 'number', 'description' => 'Minimum memory percent (0-100)'},
5326
+ # {'dependsOnCode' => 'sourceThresholdId:custom', 'fieldName' => 'maxMemory', 'fieldLabel' => 'Max Memory', 'type' => 'number', 'description' => 'Maximum memory percent (0-100)'},
5327
+ # {'dependsOnCode' => 'sourceThresholdId:custom', 'fieldName' => 'diskEnabled', 'fieldLabel' => 'Enable Disk Threshold', 'type' => 'checkbox', 'description' => 'Scale when storage thresholds are met.'},
5328
+ # {'dependsOnCode' => 'sourceThresholdId:custom', 'fieldName' => 'minDisk', 'fieldLabel' => 'Min Disk', 'type' => 'number', 'description' => 'Minimum storage percent (0-100)'},
5329
+ # {'dependsOnCode' => 'sourceThresholdId:custom', 'fieldName' => 'maxDisk', 'fieldLabel' => 'Max Disk', 'type' => 'number', 'description' => 'Maximum storage percent (0-100)'},
5330
+ ]
5151
5331
  end
5152
5332
 
5153
5333
  def instance_load_balancer_option_types(instance=nil)
@@ -5162,7 +5342,7 @@ private
5162
5342
  # "Instance" => lambda {|it| "#{instance['id']} - #{instance['name']}" },
5163
5343
  "Auto Upscale" => lambda {|it| format_boolean(it['autoUp']) },
5164
5344
  "Auto Downscale" => lambda {|it| format_boolean(it['autoDown']) },
5165
- "Cloud" => lambda {|it| it['zoneId'] ? "#{it['zoneId']}" : 'Use Scale Priority' },
5345
+ #"Cloud" => lambda {|it| it['zoneId'] ? "#{it['zoneId']}" : 'Use Scale Priority' },
5166
5346
  "Min Count" => lambda {|it| it['minCount'] },
5167
5347
  "Max Count" => lambda {|it| it['maxCount'] },
5168
5348
  "Memory Enabled" => lambda {|it| format_boolean(it['memoryEnabled']) },
@@ -5183,6 +5363,96 @@ private
5183
5363
  print_description_list(description_cols, instance_threshold)
5184
5364
  end
5185
5365
 
5366
+ def instance_schedule_column_definitions(options)
5367
+ {
5368
+ "ID" => lambda {|it| it['id'] },
5369
+ "Start" => lambda {|it| it['startDisplay'] },
5370
+ "End" => lambda {|it| it['endDisplay'] },
5371
+ "Auto Upscale" => lambda {|it| format_boolean(it['threshold']['autoUp']) rescue nil },
5372
+ "Auto Downscale" => lambda {|it| format_boolean(it['threshold']['autoDown']) rescue nil },
5373
+ "Min Count" => lambda {|it| it['threshold']['minCount'] rescue nil },
5374
+ "Max Count" => lambda {|it| it['threshold']['maxCount'] rescue nil },
5375
+ "Enable CPU Threshold" => lambda {|it| format_boolean(it['threshold']['cpuEnabled']) rescue nil },
5376
+ "Min CPU" => lambda {|it| format_percent(it['threshold']['minCpu'], 9, true) rescue nil },
5377
+ "Max CPU" => lambda {|it| format_percent(it['threshold']['maxCpu'], 9, true) rescue nil },
5378
+ "Enable Memory Threshold" => lambda {|it| format_boolean(it['threshold']['memoryEnabled']) rescue nil },
5379
+ "Min Memory" => lambda {|it| format_percent(it['threshold']['minMemory'], 9, true) rescue nil },
5380
+ "Max Memory" => lambda {|it| format_percent(it['threshold']['maxMemory'], 9, true) rescue nil },
5381
+ "Enable Disk Threshold" => lambda {|it| format_boolean(it['threshold']['diskEnabled']) rescue nil },
5382
+ "Min Disk" => lambda {|it| format_percent(it['threshold']['minDisk'], 9, true) rescue nil },
5383
+ "Max Disk" => lambda {|it| format_percent(it['threshold']['maxDisk'], 9, true) rescue nil },
5384
+ }
5385
+ end
5386
+
5387
+ def instance_schedule_list_column_definitions(options)
5388
+ instance_schedule_column_definitions(options)
5389
+ end
5390
+
5391
+ def find_instance_schedule_by_id(instance_id, id)
5392
+ begin
5393
+ json_response = @instances_interface.get_schedule(instance_id, id)
5394
+ return json_response['instanceSchedule']
5395
+ rescue RestClient::Exception => e
5396
+ if e.response && e.response.code == 404
5397
+ print_red_alert "Instance Schedule not found by id #{id}"
5398
+ exit 1
5399
+ else
5400
+ raise e
5401
+ end
5402
+ end
5403
+ end
5404
+
5405
+ def day_of_week_dropdown()
5406
+ [
5407
+ {'name' => 'Sunday', 'value' => 1},
5408
+ {'name' => 'Monday', 'value' => 2},
5409
+ {'name' => 'Tuesday', 'value' => 3},
5410
+ {'name' => 'Wednesday', 'value' => 4},
5411
+ {'name' => 'Thursday', 'value' => 5},
5412
+ {'name' => 'Friday', 'value' => 6},
5413
+ {'name' => 'Saturday', 'value' => 7}
5414
+ ]
5415
+ end
5416
+
5417
+ def add_instance_schedule_option_types()
5418
+ [
5419
+ {'code' => 'scheduleType', 'fieldName' => 'scheduleType', 'fieldLabel' => 'Schedule Type', 'type' => 'select', 'selectOptions' => [{'name'=>'Day Of Week', 'value'=>'dayOfWeek'},{'name'=>'Exact', 'value'=>'exact'}], 'description' => "Schedule type can be recurring day of the week str or exact start and end timestamp", 'required' => true, 'defaultValue' => 'dayOfWeek'},
5420
+ {'dependsOnCode' => 'scheduleType:dayOfWeek', 'fieldName' => 'startDayOfWeek', 'fieldLabel' => 'Start Day Of Week', 'type' => 'select', 'selectOptions' => day_of_week_dropdown, 'description' => "Start day of the week Sunday-Saturday (1-7)", 'defaultValue' => "Sunday", 'required' => true},
5421
+ {'dependsOnCode' => 'scheduleType:dayOfWeek', 'fieldName' => 'startTime', 'fieldLabel' => 'Start Time (HH:MM)', 'type' => 'text', 'description' => "Start time in HH:MM 24-hour format", 'placeHolder' => 'HH:MM', 'defaultValue' => "01:00", 'required' => true},
5422
+ {'dependsOnCode' => 'scheduleType:dayOfWeek', 'fieldName' => 'endDayOfWeek', 'fieldLabel' => 'End Day Of Week', 'type' => 'select', 'selectOptions' => day_of_week_dropdown, 'description' => "End day of the week Sunday-Saturday (1-7)", 'defaultValue' => "Sunday", 'required' => true},
5423
+ {'dependsOnCode' => 'scheduleType:dayOfWeek', 'fieldName' => 'endTime', 'fieldLabel' => 'End Time (HH:MM)', 'type' => 'text', 'description' => "End time in HH:MM 24-hour format", 'placeHolder' => 'HH:MM', 'defaultValue' => "01:00", 'required' => true},
5424
+ {'dependsOnCode' => 'scheduleType:exact', 'fieldName' => 'startDate', 'fieldLabel' => 'Start Date', 'type' => 'text', 'description' => "Exact start date timestamp in standard iso8601 format", 'placeHolder' => 'YYYY-MM-DD', 'required' => true},
5425
+ {'dependsOnCode' => 'scheduleType:exact', 'fieldName' => 'endDate', 'fieldLabel' => 'End Date', 'type' => 'text', 'description' => "Exact end date timestamp in standard iso8601 format", 'placeHolder' => 'YYYY-MM-DD', 'required' => true},
5426
+ {'switch' => 'threshold', 'fieldName' => 'sourceThresholdId', 'fieldLabel' => 'Threshold', 'type' => 'select', 'optionSource' => lambda {|api_client, api_params|
5427
+ [{'name' => 'Custom', 'value' => 'custom'}] + api_client.options.options_for_source('instanceThresholdTemplates')['data'] # rescue []
5428
+ }, 'description' => "Threshold template to use as source for scaling threshold settings.", 'defaultValue' => 'custom', 'required' => true}, #, 'required' => true, 'defaultValue' => ''},
5429
+ ]
5430
+ end
5431
+
5432
+ def update_instance_schedule_option_types()
5433
+ option_types = add_instance_schedule_option_types.collect {|it| it.delete('required'); it.delete('defaultValue'); it.delete('dependsOnCode'); it }
5434
+ #option_types.reject! {|it| it['fieldName'] == 'sourceThresholdId' }
5435
+ option_types
5436
+ end
5437
+
5438
+ def instance_threshold_option_types()
5439
+ [
5440
+ {'fieldName' => 'autoUp', 'fieldLabel' => 'Auto Upscale', 'type' => 'checkbox', 'description' => 'Enable auto upscaling'},
5441
+ {'fieldName' => 'autoDown', 'fieldLabel' => 'Auto Downscale', 'type' => 'checkbox', 'description' => 'Enable auto downscaling'},
5442
+ {'fieldName' => 'minCount', 'fieldLabel' => 'Min Count', 'type' => 'number', 'description' => 'Minimum number of nodes'},
5443
+ {'fieldName' => 'maxCount', 'fieldLabel' => 'Max Count', 'type' => 'number', 'description' => 'Maximum number of nodes'},
5444
+ {'fieldName' => 'cpuEnabled', 'fieldLabel' => 'Enable CPU Threshold', 'type' => 'checkbox', 'description' => 'Scale when CPU thresholds are met.'},
5445
+ {'fieldName' => 'minCpu', 'fieldLabel' => 'Min CPU', 'type' => 'number', 'description' => 'Minimum CPU percent (0-100)'},
5446
+ {'fieldName' => 'maxCpu', 'fieldLabel' => 'Max CPU', 'type' => 'number', 'description' => 'Maximum CPU percent (0-100)'},
5447
+ {'fieldName' => 'memoryEnabled', 'fieldLabel' => 'Enable Memory Threshold', 'type' => 'checkbox', 'description' => 'Scale when memory thresholds are met.'},
5448
+ {'fieldName' => 'minMemory', 'fieldLabel' => 'Min Memory', 'type' => 'number', 'description' => 'Minimum memory percent (0-100)'},
5449
+ {'fieldName' => 'maxMemory', 'fieldLabel' => 'Max Memory', 'type' => 'number', 'description' => 'Maximum memory percent (0-100)'},
5450
+ {'fieldName' => 'diskEnabled', 'fieldLabel' => 'Enable Disk Threshold', 'type' => 'checkbox', 'description' => 'Scale when storage thresholds are met.'},
5451
+ {'fieldName' => 'minDisk', 'fieldLabel' => 'Min Disk', 'type' => 'number', 'description' => 'Minimum storage percent (0-100)'},
5452
+ {'fieldName' => 'maxDisk', 'fieldLabel' => 'Max Disk', 'type' => 'number', 'description' => 'Maximum storage percent (0-100)'},
5453
+ ]
5454
+ end
5455
+
5186
5456
  def print_process_details(process)
5187
5457
  description_cols = {
5188
5458
  "Process ID" => lambda {|it| it['id'] },
@@ -5285,4 +5555,5 @@ private
5285
5555
  return false
5286
5556
  end
5287
5557
  end
5558
+
5288
5559
  end