morpheus-cli 5.5.3 → 5.5.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/Dockerfile +1 -1
 - data/lib/morpheus/api/api_client.rb +12 -0
 - data/lib/morpheus/api/appliance_settings_interface.rb +15 -0
 - data/lib/morpheus/api/cypher_interface.rb +1 -2
 - data/lib/morpheus/api/guidance_settings_interface.rb +17 -0
 - data/lib/morpheus/api/monitoring_settings_interface.rb +25 -0
 - data/lib/morpheus/api/network_server_groups_interface.rb +7 -0
 - data/lib/morpheus/cli/cli_command.rb +10 -1
 - data/lib/morpheus/cli/commands/appliance_settings_command.rb +57 -2
 - data/lib/morpheus/cli/commands/backup_settings_command.rb +1 -1
 - data/lib/morpheus/cli/commands/catalog_item_types_command.rb +6 -1
 - data/lib/morpheus/cli/commands/cypher_command.rb +3 -0
 - data/lib/morpheus/cli/commands/guidance_command.rb +2 -2
 - data/lib/morpheus/cli/commands/guidance_settings.rb +148 -0
 - data/lib/morpheus/cli/commands/log_settings_command.rb +1 -1
 - data/lib/morpheus/cli/commands/monitoring_settings.rb +228 -0
 - data/lib/morpheus/cli/commands/network_server_groups_command.rb +222 -0
 - data/lib/morpheus/cli/commands/provisioning_settings_command.rb +1 -1
 - data/lib/morpheus/cli/commands/reports_command.rb +10 -0
 - data/lib/morpheus/cli/commands/service_catalog_command.rb +36 -2
 - data/lib/morpheus/cli/commands/whitelabel_settings_command.rb +1 -1
 - data/lib/morpheus/cli/credentials.rb +2 -1
 - data/lib/morpheus/cli/mixins/provisioning_helper.rb +14 -12
 - data/lib/morpheus/cli/mixins/rest_command.rb +5 -1
 - data/lib/morpheus/cli/mixins/secondary_rest_command.rb +35 -12
 - data/lib/morpheus/cli/option_types.rb +14 -7
 - data/lib/morpheus/cli/version.rb +1 -1
 - data/lib/morpheus/cli.rb +13 -0
 - data/lib/morpheus/ext/string.rb +6 -4
 - data/lib/morpheus/routes.rb +39 -7
 - data/test/test_case.rb +3 -0
 - metadata +8 -2
 
| 
         @@ -0,0 +1,228 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'morpheus/cli/cli_command'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Morpheus::Cli::MonitoringSettings
         
     | 
| 
      
 4 
     | 
    
         
            +
              include Morpheus::Cli::CliCommand
         
     | 
| 
      
 5 
     | 
    
         
            +
              include Morpheus::Cli::AccountsHelper
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              set_command_name :'monitor-settings'
         
     | 
| 
      
 8 
     | 
    
         
            +
              set_command_description "View and manage monitoring settings"
         
     | 
| 
      
 9 
     | 
    
         
            +
              register_subcommands :get, :update
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              def connect(opts)
         
     | 
| 
      
 12 
     | 
    
         
            +
                @api_client = establish_remote_appliance_connection(opts)
         
     | 
| 
      
 13 
     | 
    
         
            +
                @monitoring_settings_interface = @api_client.monitoring_settings
         
     | 
| 
      
 14 
     | 
    
         
            +
                @options_interface = @api_client.options
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def handle(args)
         
     | 
| 
      
 18 
     | 
    
         
            +
                handle_subcommand(args)
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              def get(args)
         
     | 
| 
      
 22 
     | 
    
         
            +
                params = {}
         
     | 
| 
      
 23 
     | 
    
         
            +
                options = {}
         
     | 
| 
      
 24 
     | 
    
         
            +
                optparse = Morpheus::Cli::OptionParser.new do |opts|
         
     | 
| 
      
 25 
     | 
    
         
            +
                  opts.banner = subcommand_usage()
         
     | 
| 
      
 26 
     | 
    
         
            +
                  build_standard_get_options(opts, options)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  opts.footer = "Get monitoring settings."
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
                optparse.parse!(args)
         
     | 
| 
      
 30 
     | 
    
         
            +
                connect(options)
         
     | 
| 
      
 31 
     | 
    
         
            +
                verify_args!(args:args, optparse:optparse, count:0)
         
     | 
| 
      
 32 
     | 
    
         
            +
                params.merge!(parse_query_options(options))
         
     | 
| 
      
 33 
     | 
    
         
            +
                @monitoring_settings_interface.setopts(options)
         
     | 
| 
      
 34 
     | 
    
         
            +
                if options[:dry_run]
         
     | 
| 
      
 35 
     | 
    
         
            +
                  print_dry_run @monitoring_settings_interface.dry.get(options)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  return
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
                json_response = @monitoring_settings_interface.get(options)
         
     | 
| 
      
 39 
     | 
    
         
            +
                render_response(json_response, options, 'monitoringSettings') do
         
     | 
| 
      
 40 
     | 
    
         
            +
                  monitoring_settings = json_response['monitoringSettings']
         
     | 
| 
      
 41 
     | 
    
         
            +
                  service_now_settings = monitoring_settings['serviceNow']
         
     | 
| 
      
 42 
     | 
    
         
            +
                  new_relic_settings = monitoring_settings['newRelic']
         
     | 
| 
      
 43 
     | 
    
         
            +
                  print_h1 "Monitoring Settings"
         
     | 
| 
      
 44 
     | 
    
         
            +
                  print cyan
         
     | 
| 
      
 45 
     | 
    
         
            +
                  description_cols = {
         
     | 
| 
      
 46 
     | 
    
         
            +
                    "Auto Create Checks" => lambda {|it| format_boolean(it['autoManageChecks']) },
         
     | 
| 
      
 47 
     | 
    
         
            +
                    "Availability Time Frame" => lambda {|it| it['availabilityTimeFrame'] ? it['availabilityTimeFrame'].to_s + ' days' : '' },
         
     | 
| 
      
 48 
     | 
    
         
            +
                    "Availability Precision" => lambda {|it| it['availabilityPrecision'] ? it['availabilityPrecision'].to_s : '' },
         
     | 
| 
      
 49 
     | 
    
         
            +
                    "Default Check Interval" => lambda {|it| it['defaultCheckInterval'] ? it['defaultCheckInterval'].to_s + ' minutes' : '' },
         
     | 
| 
      
 50 
     | 
    
         
            +
                  }
         
     | 
| 
      
 51 
     | 
    
         
            +
                  print_description_list(description_cols, monitoring_settings, options)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  
         
     | 
| 
      
 53 
     | 
    
         
            +
                    print_h2 "ServiceNow Settings", options.merge(:border_style => :thin)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    description_cols = {
         
     | 
| 
      
 55 
     | 
    
         
            +
                      "Enabled" => lambda {|it| format_boolean(it['enabled']) },
         
     | 
| 
      
 56 
     | 
    
         
            +
                      "Integration" => lambda {|it| it['integration'] ? it['integration']['name'] : '' },
         
     | 
| 
      
 57 
     | 
    
         
            +
                      "New Incident Action" => lambda {|it| format_service_now_action(it['newIncidentAction']) },
         
     | 
| 
      
 58 
     | 
    
         
            +
                      "Close Incident Action" => lambda {|it| format_service_now_action(it['closeIncidentAction']) },
         
     | 
| 
      
 59 
     | 
    
         
            +
                      "Info Mapping" => lambda {|it| format_service_now_mapping(it['infoMapping']) },
         
     | 
| 
      
 60 
     | 
    
         
            +
                      "Warning Mapping" => lambda {|it| format_service_now_mapping(it['warningMapping']) },
         
     | 
| 
      
 61 
     | 
    
         
            +
                      "Critical Mapping" => lambda {|it| format_service_now_mapping(it['criticalMapping']) },
         
     | 
| 
      
 62 
     | 
    
         
            +
                    }
         
     | 
| 
      
 63 
     | 
    
         
            +
                    print_description_list(description_cols, service_now_settings)
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                    print_h2 "New Relic Settings", options.merge(:border_style => :thin)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    description_cols = {
         
     | 
| 
      
 67 
     | 
    
         
            +
                      "Enabled" => lambda {|it| format_boolean(it['enabled']) },
         
     | 
| 
      
 68 
     | 
    
         
            +
                      "License Key" => lambda {|it| it['licenseKey'] },
         
     | 
| 
      
 69 
     | 
    
         
            +
                    }
         
     | 
| 
      
 70 
     | 
    
         
            +
                    print_description_list(description_cols, new_relic_settings, options)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  
         
     | 
| 
      
 72 
     | 
    
         
            +
                  print reset, "\n"
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
                return 0, nil
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
              def update(args)
         
     | 
| 
      
 78 
     | 
    
         
            +
                params = {}
         
     | 
| 
      
 79 
     | 
    
         
            +
                options = {}
         
     | 
| 
      
 80 
     | 
    
         
            +
                optparse = Morpheus::Cli::OptionParser.new do |opts|
         
     | 
| 
      
 81 
     | 
    
         
            +
                  opts.banner = opts.banner = subcommand_usage()
         
     | 
| 
      
 82 
     | 
    
         
            +
                  opts.on('--auto-create-checks [on|off]', String, "Auto Create Checks") do |val|
         
     | 
| 
      
 83 
     | 
    
         
            +
                    params['autoManageChecks'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
      
 85 
     | 
    
         
            +
                  opts.on("--availability-time-frame DAYS", Integer, "Availability Time Frame. The number of days availability should be calculated for. Changes will not take effect until your checks have passed their check interval.") do |val|
         
     | 
| 
      
 86 
     | 
    
         
            +
                    params['availabilityTimeFrame'] = val.to_i
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
                  opts.on("--availability-precision DIGITS", Integer, "Availability Precision. The number of decimal places availability should be displayed in. Can be anywhere between 0 and 5.") do |val|
         
     | 
| 
      
 89 
     | 
    
         
            +
                    params['availabilityPrecision'] = val.to_i
         
     | 
| 
      
 90 
     | 
    
         
            +
                  end
         
     | 
| 
      
 91 
     | 
    
         
            +
                  opts.on("--default-check-interval MINUTES", Integer, "Default Check Interval. The default interval to use when creating new checks. Value is in minutes.") do |val|
         
     | 
| 
      
 92 
     | 
    
         
            +
                    params['defaultCheckInterval'] = val.to_i
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
                  opts.on('--service-now-enabled [on|off]', String, "ServiceNow: Enabled (on) or disabled (off)") do |val|
         
     | 
| 
      
 95 
     | 
    
         
            +
                    params['serviceNow'] ||= {}
         
     | 
| 
      
 96 
     | 
    
         
            +
                    params['serviceNow']['enabled'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
         
     | 
| 
      
 97 
     | 
    
         
            +
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
                  opts.on('--service-now-integration ID', String, "ServiceNow: Integration ID or Name") do |val|
         
     | 
| 
      
 99 
     | 
    
         
            +
                    params['serviceNow'] ||= {}
         
     | 
| 
      
 100 
     | 
    
         
            +
                    params['serviceNow']['integration'] = val # {'id' => val.to_i}
         
     | 
| 
      
 101 
     | 
    
         
            +
                  end
         
     | 
| 
      
 102 
     | 
    
         
            +
                  opts.on("--service-now-new-incident-action create|none", String, "ServiceNow: New Incident Action") do |val|
         
     | 
| 
      
 103 
     | 
    
         
            +
                    # allowed_values = 'create|none'.split('|') #get_service_now_actions().keys
         
     | 
| 
      
 104 
     | 
    
         
            +
                    # if !allowed_values.include?(val)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    #   raise ::OptionParser::InvalidOption.new("New Incident Action value '#{val}' is invalid.\nThe allowed values are: #{allowed_values.join(', ')}")
         
     | 
| 
      
 106 
     | 
    
         
            +
                    # end
         
     | 
| 
      
 107 
     | 
    
         
            +
                    params['serviceNow'] ||= {}
         
     | 
| 
      
 108 
     | 
    
         
            +
                    params['serviceNow']['newIncidentAction'] = val
         
     | 
| 
      
 109 
     | 
    
         
            +
                  end
         
     | 
| 
      
 110 
     | 
    
         
            +
                  opts.on("--service-now-close-incident-action close|activity|none", String, "ServiceNow: Close Incident Action") do |val|
         
     | 
| 
      
 111 
     | 
    
         
            +
                    # allowed_values = 'close|activity|none'.split('|') #get_service_now_mappings().keys
         
     | 
| 
      
 112 
     | 
    
         
            +
                    # if !allowed_values.include?(val)
         
     | 
| 
      
 113 
     | 
    
         
            +
                    #   raise ::OptionParser::InvalidOption.new("Close Incident Action value '#{val}' is invalid.\nThe allowed values are: #{allowed_values.join(', ')}")
         
     | 
| 
      
 114 
     | 
    
         
            +
                    # end
         
     | 
| 
      
 115 
     | 
    
         
            +
                    params['serviceNow'] ||= {}
         
     | 
| 
      
 116 
     | 
    
         
            +
                    params['serviceNow']['closeIncidentAction'] = val
         
     | 
| 
      
 117 
     | 
    
         
            +
                  end
         
     | 
| 
      
 118 
     | 
    
         
            +
                  opts.on("--service-now-info-mapping low|medium|high", String, "ServiceNow: Info Mapping") do |val|
         
     | 
| 
      
 119 
     | 
    
         
            +
                    # allowed_values = 'low|medium|high'.split('|') # get_service_now_mappings().keys
         
     | 
| 
      
 120 
     | 
    
         
            +
                    # if !allowed_values.include?(val)
         
     | 
| 
      
 121 
     | 
    
         
            +
                    #   raise ::OptionParser::InvalidOption.new("Info Mapping value '#{val}' is invalid.\nThe allowed values are: #{allowed_values.join(', ')}")
         
     | 
| 
      
 122 
     | 
    
         
            +
                    # end
         
     | 
| 
      
 123 
     | 
    
         
            +
                    params['serviceNow'] ||= {}
         
     | 
| 
      
 124 
     | 
    
         
            +
                    params['serviceNow']['infoMapping'] = val
         
     | 
| 
      
 125 
     | 
    
         
            +
                  end
         
     | 
| 
      
 126 
     | 
    
         
            +
                  opts.on("--service-now-warning-mapping low|medium|high", String, "ServiceNow: Warning Mapping") do |val|
         
     | 
| 
      
 127 
     | 
    
         
            +
                    # allowed_values = 'low|medium|high'.split('|') # get_service_now_mappings().keys
         
     | 
| 
      
 128 
     | 
    
         
            +
                    # if !allowed_values.include?(val)
         
     | 
| 
      
 129 
     | 
    
         
            +
                    #   raise ::OptionParser::InvalidOption.new("Warning Info Mapping value '#{val}' is invalid.\nThe allowed values are: #{allowed_values.join(', ')}")
         
     | 
| 
      
 130 
     | 
    
         
            +
                    # end
         
     | 
| 
      
 131 
     | 
    
         
            +
                    params['serviceNow'] ||= {}
         
     | 
| 
      
 132 
     | 
    
         
            +
                    params['serviceNow']['warningMapping'] = val
         
     | 
| 
      
 133 
     | 
    
         
            +
                  end
         
     | 
| 
      
 134 
     | 
    
         
            +
                  opts.on("--service-now-critical-mapping low|medium|high", String, "ServiceNow: Critical Mapping") do |val|
         
     | 
| 
      
 135 
     | 
    
         
            +
                    # allowed_values = 'low|medium|high'.split('|') # get_service_now_mappings().keys
         
     | 
| 
      
 136 
     | 
    
         
            +
                    # if !allowed_values.include?(val)
         
     | 
| 
      
 137 
     | 
    
         
            +
                    #   raise ::OptionParser::InvalidOption.new("Critical Info Mapping value '#{val}' is invalid.\nThe allowed values are: #{allowed_values.join(', ')}")
         
     | 
| 
      
 138 
     | 
    
         
            +
                    # end
         
     | 
| 
      
 139 
     | 
    
         
            +
                    params['serviceNow'] ||= {}
         
     | 
| 
      
 140 
     | 
    
         
            +
                    params['serviceNow']['criticalMapping'] = val
         
     | 
| 
      
 141 
     | 
    
         
            +
                  end
         
     | 
| 
      
 142 
     | 
    
         
            +
                  opts.on('--new-relic-enabled [on|off]', String, "New Relic: Enabled (on) or disabled (off)") do |val|
         
     | 
| 
      
 143 
     | 
    
         
            +
                    params['newRelic'] ||= {}
         
     | 
| 
      
 144 
     | 
    
         
            +
                    params['newRelic']['enabled'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
         
     | 
| 
      
 145 
     | 
    
         
            +
                  end
         
     | 
| 
      
 146 
     | 
    
         
            +
                  opts.on("--new-relic-license-key [VALUE]", String, "New Relic: License Key") do |val|
         
     | 
| 
      
 147 
     | 
    
         
            +
                    params['newRelic'] ||= {}
         
     | 
| 
      
 148 
     | 
    
         
            +
                    params['newRelic']['licenseKey'] = val
         
     | 
| 
      
 149 
     | 
    
         
            +
                  end
         
     | 
| 
      
 150 
     | 
    
         
            +
                  build_standard_update_options(opts, options)
         
     | 
| 
      
 151 
     | 
    
         
            +
                  opts.footer = "Update monitoring settings."
         
     | 
| 
      
 152 
     | 
    
         
            +
                end
         
     | 
| 
      
 153 
     | 
    
         
            +
                optparse.parse!(args)
         
     | 
| 
      
 154 
     | 
    
         
            +
                connect(options)
         
     | 
| 
      
 155 
     | 
    
         
            +
                verify_args!(args:args, optparse:optparse, count:0)
         
     | 
| 
      
 156 
     | 
    
         
            +
                payload = parse_payload(options)
         
     | 
| 
      
 157 
     | 
    
         
            +
                if !payload
         
     | 
| 
      
 158 
     | 
    
         
            +
                  payload = {}
         
     | 
| 
      
 159 
     | 
    
         
            +
                  payload.deep_merge!({object_key => parse_passed_options(options)}) # inject options passed with -O foo=bar
         
     | 
| 
      
 160 
     | 
    
         
            +
                  if params['serviceNow'] && params['serviceNow']['integration']
         
     | 
| 
      
 161 
     | 
    
         
            +
                    integration = find_by_name_or_id(:integration, params['serviceNow']['integration'])
         
     | 
| 
      
 162 
     | 
    
         
            +
                    if integration.nil?
         
     | 
| 
      
 163 
     | 
    
         
            +
                      exit 1 #return 1, "Integration not found by '#{options[:servicenow_integration]}'"
         
     | 
| 
      
 164 
     | 
    
         
            +
                    else
         
     | 
| 
      
 165 
     | 
    
         
            +
                      if integration['integrationType']['code'] != 'serviceNow'
         
     | 
| 
      
 166 
     | 
    
         
            +
                        raise_command_error "Integration '#{integration['id']}' must be a Service Now integration"
         
     | 
| 
      
 167 
     | 
    
         
            +
                      end
         
     | 
| 
      
 168 
     | 
    
         
            +
                      params['serviceNow'] ||= {}
         
     | 
| 
      
 169 
     | 
    
         
            +
                      params['serviceNow']['integration'] = {'id' => integration['id'].to_i}
         
     | 
| 
      
 170 
     | 
    
         
            +
                    end
         
     | 
| 
      
 171 
     | 
    
         
            +
                  end
         
     | 
| 
      
 172 
     | 
    
         
            +
                  payload.deep_merge!({object_key => params})
         
     | 
| 
      
 173 
     | 
    
         
            +
                end
         
     | 
| 
      
 174 
     | 
    
         
            +
                if payload[object_key].empty?
         
     | 
| 
      
 175 
     | 
    
         
            +
                  raise_command_error "Specify at least one option to update.\n#{optparse}"
         
     | 
| 
      
 176 
     | 
    
         
            +
                end
         
     | 
| 
      
 177 
     | 
    
         
            +
                @monitoring_settings_interface.setopts(options)
         
     | 
| 
      
 178 
     | 
    
         
            +
                if options[:dry_run]
         
     | 
| 
      
 179 
     | 
    
         
            +
                  print_dry_run @monitoring_settings_interface.dry.update(payload)
         
     | 
| 
      
 180 
     | 
    
         
            +
                  return
         
     | 
| 
      
 181 
     | 
    
         
            +
                end
         
     | 
| 
      
 182 
     | 
    
         
            +
                json_response = @monitoring_settings_interface.update(payload)
         
     | 
| 
      
 183 
     | 
    
         
            +
                exit_code, err = 0, nil
         
     | 
| 
      
 184 
     | 
    
         
            +
                render_response(json_response, options, object_key) do
         
     | 
| 
      
 185 
     | 
    
         
            +
                  if json_response['success']
         
     | 
| 
      
 186 
     | 
    
         
            +
                    print_green_success "Updated monitoring settings"
         
     | 
| 
      
 187 
     | 
    
         
            +
                    get([] + (options[:remote] ? ["-r",options[:remote]] : []))
         
     | 
| 
      
 188 
     | 
    
         
            +
                  else
         
     | 
| 
      
 189 
     | 
    
         
            +
                    exit_code, err = 1, "Error updating monitoring settings: #{json_response['msg'] || json_response['errors']}"
         
     | 
| 
      
 190 
     | 
    
         
            +
                    print_rest_errors(json_response)
         
     | 
| 
      
 191 
     | 
    
         
            +
                  end
         
     | 
| 
      
 192 
     | 
    
         
            +
                end
         
     | 
| 
      
 193 
     | 
    
         
            +
                return exit_code, err
         
     | 
| 
      
 194 
     | 
    
         
            +
              end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
              private
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
              def get_service_now_actions()
         
     | 
| 
      
 199 
     | 
    
         
            +
                {
         
     | 
| 
      
 200 
     | 
    
         
            +
                  'create' => 'Create new incident in ServiceNow',
         
     | 
| 
      
 201 
     | 
    
         
            +
                  'close' => 'Resolve Incident in ServiceNow',
         
     | 
| 
      
 202 
     | 
    
         
            +
                  'activity' => 'Add Activity to Incident in ServiceNow',
         
     | 
| 
      
 203 
     | 
    
         
            +
                  'none' => 'No action',
         
     | 
| 
      
 204 
     | 
    
         
            +
                }
         
     | 
| 
      
 205 
     | 
    
         
            +
              end
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
              def format_service_now_action(action_value)
         
     | 
| 
      
 208 
     | 
    
         
            +
                get_service_now_actions()[action_value].to_s
         
     | 
| 
      
 209 
     | 
    
         
            +
              end
         
     | 
| 
      
 210 
     | 
    
         
            +
             
     | 
| 
      
 211 
     | 
    
         
            +
              def get_service_now_mappings()
         
     | 
| 
      
 212 
     | 
    
         
            +
                {
         
     | 
| 
      
 213 
     | 
    
         
            +
                  'low' => 'Low',
         
     | 
| 
      
 214 
     | 
    
         
            +
                  'medium' => 'Medium',
         
     | 
| 
      
 215 
     | 
    
         
            +
                  'high' => 'High',
         
     | 
| 
      
 216 
     | 
    
         
            +
                }
         
     | 
| 
      
 217 
     | 
    
         
            +
              end
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
              def format_service_now_mapping(mapping_value)
         
     | 
| 
      
 220 
     | 
    
         
            +
                get_service_now_mappings()[mapping_value].to_s
         
     | 
| 
      
 221 
     | 
    
         
            +
              end
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
              def object_key
         
     | 
| 
      
 225 
     | 
    
         
            +
                'monitoringSettings'
         
     | 
| 
      
 226 
     | 
    
         
            +
              end
         
     | 
| 
      
 227 
     | 
    
         
            +
             
     | 
| 
      
 228 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,222 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'morpheus/cli/cli_command'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Morpheus::Cli::NetworkServerGroups
         
     | 
| 
      
 4 
     | 
    
         
            +
              include Morpheus::Cli::CliCommand
         
     | 
| 
      
 5 
     | 
    
         
            +
              include Morpheus::Cli::WhoamiHelper
         
     | 
| 
      
 6 
     | 
    
         
            +
              include Morpheus::Cli::RestCommand
         
     | 
| 
      
 7 
     | 
    
         
            +
              include Morpheus::Cli::SecondaryRestCommand
         
     | 
| 
      
 8 
     | 
    
         
            +
              include Morpheus::Cli::ProvisioningHelper
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              set_command_description "View and manage network server groups."
         
     | 
| 
      
 11 
     | 
    
         
            +
              set_command_name :'network-server-groups'
         
     | 
| 
      
 12 
     | 
    
         
            +
              register_subcommands :list, :get, :add, :update, :remove
         
     | 
| 
      
 13 
     | 
    
         
            +
              register_interfaces :network_servers, :network_server_groups, :accounts
         
     | 
| 
      
 14 
     | 
    
         
            +
              set_rest_perms_config({enabled:true, excludes:['groups', 'plans', 'visibility', 'resource'], context: 'permissions'})
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              protected
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              NSXT_CRITERIA_TYPES = ['Condition', 'NestedExpression'] unless defined? NSXT_CRITERIA_TYPES
         
     | 
| 
      
 19 
     | 
    
         
            +
              NSXT_MEMBER_TYPES = ['Path', 'ExternalID'] unless defined? NSXT_MEMBER_TYPES
         
     | 
| 
      
 20 
     | 
    
         
            +
              NSXT_IP_TYPES = ['IPAddress', 'MACAddress'] unless defined? NSXT_IP_TYPES
         
     | 
| 
      
 21 
     | 
    
         
            +
              NSXT_AD_GROUP_TYPES = ['IdentityGroup'] unless defined? NSXT_AD_GROUP_TYPES
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              def network_server_group_list_key
         
     | 
| 
      
 24 
     | 
    
         
            +
                'groups'
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              def network_server_group_object_key
         
     | 
| 
      
 28 
     | 
    
         
            +
                'group'
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              def network_server_group_field_context
         
     | 
| 
      
 32 
     | 
    
         
            +
                network_server_group_object_key
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def load_option_types_for_network_server_group(record_type, parent_record)
         
     | 
| 
      
 36 
     | 
    
         
            +
                parent_record['type']['groupOptionTypes']
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              def network_server_group_list_column_definitions(options)
         
     | 
| 
      
 40 
     | 
    
         
            +
                if options[:parent_record]['type']['code'] == 'nsx-t'
         
     | 
| 
      
 41 
     | 
    
         
            +
                  members_lambda = lambda do |group|
         
     | 
| 
      
 42 
     | 
    
         
            +
                    members = []
         
     | 
| 
      
 43 
     | 
    
         
            +
                    {
         
     | 
| 
      
 44 
     | 
    
         
            +
                      'Criteria' => NSXT_CRITERIA_TYPES,
         
     | 
| 
      
 45 
     | 
    
         
            +
                      'Members' => NSXT_MEMBER_TYPES,
         
     | 
| 
      
 46 
     | 
    
         
            +
                      'IPS / MACS' => NSXT_IP_TYPES,
         
     | 
| 
      
 47 
     | 
    
         
            +
                      'AD Groups' => NSXT_AD_GROUP_TYPES
         
     | 
| 
      
 48 
     | 
    
         
            +
                    }.each do |label, types|
         
     | 
| 
      
 49 
     | 
    
         
            +
                      if (count = group['members'].select{|member| types.include?(member['type'])}.count) > 0
         
     | 
| 
      
 50 
     | 
    
         
            +
                        members << "#{count} #{label}"
         
     | 
| 
      
 51 
     | 
    
         
            +
                      end
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
                    members.join(', ')
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                else
         
     | 
| 
      
 56 
     | 
    
         
            +
                  members_lambda = lambda do |group|
         
     | 
| 
      
 57 
     | 
    
         
            +
                    group['members'].collect{|member| member['type']}.join(', ')
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                columns = {
         
     | 
| 
      
 62 
     | 
    
         
            +
                  'ID' => 'id',
         
     | 
| 
      
 63 
     | 
    
         
            +
                  'Name' => 'name',
         
     | 
| 
      
 64 
     | 
    
         
            +
                  'Description' => {:label => 'Description', :max_width => 50, :display_method => lambda {|group| group['description']}},
         
     | 
| 
      
 65 
     | 
    
         
            +
                  'Members' => members_lambda
         
     | 
| 
      
 66 
     | 
    
         
            +
                }
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                if is_master_account
         
     | 
| 
      
 69 
     | 
    
         
            +
                  columns['Visibility'] = lambda {|it| it['visibility'].capitalize}
         
     | 
| 
      
 70 
     | 
    
         
            +
                  columns['Tenants'] = lambda do |it|
         
     | 
| 
      
 71 
     | 
    
         
            +
                    tenants = []
         
     | 
| 
      
 72 
     | 
    
         
            +
                    if it['permissions'] and it['permissions']['tenantPermissions']
         
     | 
| 
      
 73 
     | 
    
         
            +
                      tenants = @accounts_interface.list({:ids => it['permissions']['tenantPermissions']['accounts']})['accounts'].collect{|account| account['name']}
         
     | 
| 
      
 74 
     | 
    
         
            +
                    end
         
     | 
| 
      
 75 
     | 
    
         
            +
                    tenants.join(', ')
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
                columns
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
              def network_server_group_column_definitions(options)
         
     | 
| 
      
 82 
     | 
    
         
            +
                if options[:parent_record]['type']['code'] == 'nsx-t'
         
     | 
| 
      
 83 
     | 
    
         
            +
                  tags_lambda = lambda{|group|
         
     | 
| 
      
 84 
     | 
    
         
            +
                    (group['tags'] || []).collect{|tag|
         
     | 
| 
      
 85 
     | 
    
         
            +
                      "#{tag['name']}#{(tag['value'] || '').length > 0 ? " (scope: #{tag['value']})" : ''}"
         
     | 
| 
      
 86 
     | 
    
         
            +
                    }.join(', ')
         
     | 
| 
      
 87 
     | 
    
         
            +
                  }
         
     | 
| 
      
 88 
     | 
    
         
            +
                else
         
     | 
| 
      
 89 
     | 
    
         
            +
                  tags_lambda = lambda {|group| group['tags'] ? format_metadata(group['tags']) : '' }
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
                columns = {
         
     | 
| 
      
 92 
     | 
    
         
            +
                  "ID" => 'id',
         
     | 
| 
      
 93 
     | 
    
         
            +
                  "Name" => 'name',
         
     | 
| 
      
 94 
     | 
    
         
            +
                  "Description" => 'description',
         
     | 
| 
      
 95 
     | 
    
         
            +
                  "Tags" => tags_lambda
         
     | 
| 
      
 96 
     | 
    
         
            +
                }
         
     | 
| 
      
 97 
     | 
    
         
            +
                columns
         
     | 
| 
      
 98 
     | 
    
         
            +
              end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
              def network_server_group_add_prompt(record_payload, record_type, parent_record, options)
         
     | 
| 
      
 101 
     | 
    
         
            +
                unless parent_record['type']['code'] != 'nsx-t' or options[:no_prompt]
         
     | 
| 
      
 102 
     | 
    
         
            +
                  nsxt_add_prompt(record_payload, record_type, parent_record, options)
         
     | 
| 
      
 103 
     | 
    
         
            +
                end
         
     | 
| 
      
 104 
     | 
    
         
            +
              end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
              def nsxt_add_prompt(record_payload, record_type, parent_record, options)
         
     | 
| 
      
 107 
     | 
    
         
            +
                # criteria
         
     | 
| 
      
 108 
     | 
    
         
            +
                criteria = []
         
     | 
| 
      
 109 
     | 
    
         
            +
                while criteria.count < 5 && Morpheus::Cli::OptionTypes.confirm("Add#{criteria.count == 0 ? '': ' another'} criteria?", {:default => false})
         
     | 
| 
      
 110 
     | 
    
         
            +
                  if true #members.count == 0 or members.last['memberValue'] == 'OR' # Can't have nested follow AND conjunction
         
     | 
| 
      
 111 
     | 
    
         
            +
                    type = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => 'Criteria Type', 'type' => 'select', 'selectOptions' => ['Condition', 'Nested Expression'].map{|it| {'name' => it, 'value' => it.sub(' ', '')}}, 'required' => true, 'defaultValue' => 'Condition'}], options[:options])['type']
         
     | 
| 
      
 112 
     | 
    
         
            +
                  end
         
     | 
| 
      
 113 
     | 
    
         
            +
                  prompt_condition = lambda do
         
     | 
| 
      
 114 
     | 
    
         
            +
                    compare_type = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'memberType', 'fieldLabel' => 'Criteria Item', 'type' => 'select', 'selectOptions' => ['Virtual Machine', 'Segment Port', 'Segment', 'IP Set'].map{|it| {'name' => it, 'value' => it.sub(' ', '')}}, 'required' => true, 'defaultValue' => 'VirtualMachine'}], options[:options])['memberType']
         
     | 
| 
      
 115 
     | 
    
         
            +
                    compare_key = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'key', 'fieldLabel' => "#{compare_type} Field", 'type' => 'select', 'selectOptions' => (compare_type == 'VirtualMachine' ? ['Name', 'Tag', 'OS Name', 'Computer Name'] : ['Tag'] ).map{|it| {'name' => it, 'value' => it.sub(' ', '')}}, 'required' => true, 'defaultValue' => 'Tag'}], options[:options])['key']
         
     | 
| 
      
 116 
     | 
    
         
            +
                    compare_operator = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'operator', 'fieldLabel' => "#{compare_key} Operator", 'type' => 'select', 'selectOptions' => (compare_type == 'VirtualMachine' ? ['Equals', 'Contains', 'Starts With', 'Ends With'] : ['Equals']).map{|it| {'name' => it, 'value' => it.sub(' ', '').upcase}}, 'required' => true, 'defaultValue' => 'EQUALS'}], options[:options])['operator']
         
     | 
| 
      
 117 
     | 
    
         
            +
                    compare_value = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'value', 'type' => 'text', 'fieldLabel' => "#{compare_key} Value", 'required' => true, 'description' => 'Value to compare.'}], options[:options])['value']
         
     | 
| 
      
 118 
     | 
    
         
            +
                    compare_scope = nil
         
     | 
| 
      
 119 
     | 
    
         
            +
                    if compare_key == 'Tag'
         
     | 
| 
      
 120 
     | 
    
         
            +
                      compare_scope = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'scope', 'type' => 'text', 'fieldLabel' => "#{compare_key} Scope", 'required' => false}], options[:options], @api_client, {}, false, true)['scope']
         
     | 
| 
      
 121 
     | 
    
         
            +
                    end
         
     | 
| 
      
 122 
     | 
    
         
            +
                    compare_expr = {key: compare_key, operator: compare_operator, value: compare_value}
         
     | 
| 
      
 123 
     | 
    
         
            +
                    compare_expr.merge!({scope: compare_scope}) if compare_scope
         
     | 
| 
      
 124 
     | 
    
         
            +
                    {'type' => 'Condition', 'memberType' => compare_type, 'memberExpression' => JSON.generate(compare_expr)}
         
     | 
| 
      
 125 
     | 
    
         
            +
                  end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                  if criteria.count > 0
         
     | 
| 
      
 128 
     | 
    
         
            +
                    criteria.last['memberValue'] = 'OR'
         
     | 
| 
      
 129 
     | 
    
         
            +
                  end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  if type == 'Condition'
         
     | 
| 
      
 132 
     | 
    
         
            +
                    prev_criteria = criteria.count > 0 ? criteria.last : nil
         
     | 
| 
      
 133 
     | 
    
         
            +
                    criteria << prompt_condition.call
         
     | 
| 
      
 134 
     | 
    
         
            +
                    if prev_criteria and prev_criteria['type'] != 'NestedExpression' and prev_criteria['memberType'] == criteria.last['memberType']
         
     | 
| 
      
 135 
     | 
    
         
            +
                      prev_criteria['memberValue'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'memberValue', 'fieldLabel' => 'And/Or', 'type' => 'select', 'selectOptions' => ['and', 'or'].map{|it| {'name' => it, 'value' => it.upcase}}, 'required' => true, 'defaultValue' => 'AND', 'description' => 'Conjunction to use between this condition and the previous condition'}], options[:options])['memberValue']
         
     | 
| 
      
 136 
     | 
    
         
            +
                    end
         
     | 
| 
      
 137 
     | 
    
         
            +
                  else
         
     | 
| 
      
 138 
     | 
    
         
            +
                    # just prompt for conditions w/
         
     | 
| 
      
 139 
     | 
    
         
            +
                    nested_members = [prompt_condition.call]
         
     | 
| 
      
 140 
     | 
    
         
            +
                    while nested_members.count < 5 && Morpheus::Cli::OptionTypes.confirm("Add another criteria to nested expression?", {:default => false})
         
     | 
| 
      
 141 
     | 
    
         
            +
                      nested_members.last['memberValue'] = 'AND'
         
     | 
| 
      
 142 
     | 
    
         
            +
                      nested_members << prompt_condition.call
         
     | 
| 
      
 143 
     | 
    
         
            +
                    end
         
     | 
| 
      
 144 
     | 
    
         
            +
                    criteria << {'type' => type, 'members' => nested_members}
         
     | 
| 
      
 145 
     | 
    
         
            +
                  end
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                members = []
         
     | 
| 
      
 149 
     | 
    
         
            +
                while members.count < 500 && Morpheus::Cli::OptionTypes.confirm("Add#{members.count == 0 ? '': ' another'} member?", {:default => false})
         
     | 
| 
      
 150 
     | 
    
         
            +
                  member_type = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'memberType', 'fieldLabel' => 'Member Type', 'type' => 'select', 'selectOptions' => ['Group', 'Segment', 'Segment Port', 'Virtual Network Interface', 'Virtual Machine', 'Physical Server'].map{|it| {'name' => it, 'value' => it.gsub(' ', '')}}, 'required' => true, 'defaultValue' => 'Group'}], options[:options])['memberType']
         
     | 
| 
      
 151 
     | 
    
         
            +
                  member_value = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'memberValue', 'fieldLabel' => member_type, 'type' => 'select', 'optionSource' => 'nsxtGroupMembers', 'optionSourceType' => 'nsxt', 'required' => true}], options[:options], @api_client, {networkServerId: parent_record['id'], memberType: member_type}, false, true)['memberValue']
         
     | 
| 
      
 152 
     | 
    
         
            +
                  type = ['Group', 'Segment', 'SegmentPort'].include?(member_type) ? 'Path' : 'ExternalID'
         
     | 
| 
      
 153 
     | 
    
         
            +
                  members << {'type' => type, 'memberType' => member_type, 'memberValue' => member_value}
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                # ip/mac
         
     | 
| 
      
 157 
     | 
    
         
            +
                ips = []
         
     | 
| 
      
 158 
     | 
    
         
            +
                while members.count + ips.count < 500 && Morpheus::Cli::OptionTypes.confirm("Add#{ips.count == 0 ? '': ' another'} IP/MAC address?", {:default => false})
         
     | 
| 
      
 159 
     | 
    
         
            +
                  member_value = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'ipAddress', 'type' => 'text', 'fieldLabel' => "IP/MAC Address", 'required' => true, 'description' => 'Enter an IP or MAC address. x.x.x.x'}], options[:options])['ipAddress']
         
     | 
| 
      
 160 
     | 
    
         
            +
                  type = member_value.match(/[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}/) ? 'MACAddress' : 'IPAddress'
         
     | 
| 
      
 161 
     | 
    
         
            +
                  ips << {'type' => type, 'memberValue' => member_value}
         
     | 
| 
      
 162 
     | 
    
         
            +
                end
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
                # ad groups
         
     | 
| 
      
 165 
     | 
    
         
            +
                ad_groups = []
         
     | 
| 
      
 166 
     | 
    
         
            +
                while members.count + ips.count + ad_groups.count < 500 && Morpheus::Cli::OptionTypes.confirm("Add#{ad_groups.count == 0 ? '': ' another'} AD Group?", {:default => false})
         
     | 
| 
      
 167 
     | 
    
         
            +
                  member_value = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'identityGroup', 'type' => 'select', 'optionSource' => 'nsxtIdentityGroups', 'optionSourceType' => 'nsxt', 'required' => true, 'fieldLabel' => "AD Group"}], options[:options], @api_client, {networkServerId: parent_record['id'], memberType: member_type}, false, true)['identityGroup']
         
     | 
| 
      
 168 
     | 
    
         
            +
                  ad_groups << {'type' => 'IdentityGroup', 'memberValue' => member_value}
         
     | 
| 
      
 169 
     | 
    
         
            +
                end
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                record_payload['members'] = criteria + members + ips + ad_groups
         
     | 
| 
      
 172 
     | 
    
         
            +
                record_payload
         
     | 
| 
      
 173 
     | 
    
         
            +
              end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
              def render_response_details_for_get(record, options)
         
     | 
| 
      
 176 
     | 
    
         
            +
                if options[:parent_record]['type']['code'] == 'nsx-t'
         
     | 
| 
      
 177 
     | 
    
         
            +
                  members = record['members'].select{|member| NSXT_CRITERIA_TYPES.include?(member['type'])}
         
     | 
| 
      
 178 
     | 
    
         
            +
                  if members.count > 0
         
     | 
| 
      
 179 
     | 
    
         
            +
                    cond_criteria = lambda do |member|
         
     | 
| 
      
 180 
     | 
    
         
            +
                      expr = JSON.parse(member['memberExpression'])
         
     | 
| 
      
 181 
     | 
    
         
            +
                      "#{member['memberType']} #{expr['key']} #{expr['operator']} #{expr['value']}#{expr['scope'].nil? ? '' : " w/ #{expr['scope']} scope"}"
         
     | 
| 
      
 182 
     | 
    
         
            +
                    end
         
     | 
| 
      
 183 
     | 
    
         
            +
                    criteria_parts = []
         
     | 
| 
      
 184 
     | 
    
         
            +
                    members.each_with_index do |member, index|
         
     | 
| 
      
 185 
     | 
    
         
            +
                      if member['type'] == 'NestedExpression'
         
     | 
| 
      
 186 
     | 
    
         
            +
                        criteria_parts << "("
         
     | 
| 
      
 187 
     | 
    
         
            +
                        member['members'].each do |child_member|
         
     | 
| 
      
 188 
     | 
    
         
            +
                          criteria_parts << "  #{cond_criteria.call(child_member)}"
         
     | 
| 
      
 189 
     | 
    
         
            +
                          criteria_parts << "  #{child_member['memberValue']}"
         
     | 
| 
      
 190 
     | 
    
         
            +
                        end
         
     | 
| 
      
 191 
     | 
    
         
            +
                        criteria_parts.pop # remove last conjunction
         
     | 
| 
      
 192 
     | 
    
         
            +
                        criteria_parts << ")"
         
     | 
| 
      
 193 
     | 
    
         
            +
                      else
         
     | 
| 
      
 194 
     | 
    
         
            +
                        criteria_parts << cond_criteria.call(member)
         
     | 
| 
      
 195 
     | 
    
         
            +
                        criteria_parts << member['memberValue']
         
     | 
| 
      
 196 
     | 
    
         
            +
                      end
         
     | 
| 
      
 197 
     | 
    
         
            +
                    end
         
     | 
| 
      
 198 
     | 
    
         
            +
                    criteria_parts.pop if ['AND', 'OR'].include?(criteria_parts.last) # remove last conjunction
         
     | 
| 
      
 199 
     | 
    
         
            +
                    print_h2 "Criteria (#{members.count})", options
         
     | 
| 
      
 200 
     | 
    
         
            +
                    print "#{cyan}#{criteria_parts.join("\n")}\n"
         
     | 
| 
      
 201 
     | 
    
         
            +
                  end
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
                  members = record['members'].select{|member| NSXT_MEMBER_TYPES.include?(member['type'])}
         
     | 
| 
      
 204 
     | 
    
         
            +
                  if members.count > 0
         
     | 
| 
      
 205 
     | 
    
         
            +
                    print_h2 "Members (#{members.count})", options
         
     | 
| 
      
 206 
     | 
    
         
            +
                    print as_pretty_table(members, {'Type' => 'memberType', 'Path/ExternalID' => 'memberValue'}, options)
         
     | 
| 
      
 207 
     | 
    
         
            +
                  end
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
                  members = record['members'].select{|member| NSXT_IP_TYPES.include?(member['type'])}
         
     | 
| 
      
 210 
     | 
    
         
            +
                  if members.count > 0
         
     | 
| 
      
 211 
     | 
    
         
            +
                    print_h2 "IP/MAC Addresses (#{members.count})", options
         
     | 
| 
      
 212 
     | 
    
         
            +
                    print "#{cyan}#{members.collect{|member| "#{member['memberValue']}"}.join("\n")}\n"
         
     | 
| 
      
 213 
     | 
    
         
            +
                  end
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                  members = record['members'].select{|member| NSXT_AD_GROUP_TYPES.include?(member['type'])}
         
     | 
| 
      
 216 
     | 
    
         
            +
                  if members.count > 0
         
     | 
| 
      
 217 
     | 
    
         
            +
                    print_h2 "AD Groups (#{members.count})", options
         
     | 
| 
      
 218 
     | 
    
         
            +
                    print "#{cyan}#{members.collect{|member| "#{member['memberValue']}"}.join("\n")}\n"
         
     | 
| 
      
 219 
     | 
    
         
            +
                  end
         
     | 
| 
      
 220 
     | 
    
         
            +
                end
         
     | 
| 
      
 221 
     | 
    
         
            +
              end
         
     | 
| 
      
 222 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -83,7 +83,7 @@ class Morpheus::Cli::ProvisioningSettingsCommand 
     | 
|
| 
       83 
83 
     | 
    
         
             
                    "Default Blueprint Type" => lambda {|it| it['defaultTemplateType'] ? it['defaultTemplateType']['name'].capitalize : 'Morpheus'}
         
     | 
| 
       84 
84 
     | 
    
         
             
                  }
         
     | 
| 
       85 
85 
     | 
    
         
             
                  print_description_list(description_cols, settings)
         
     | 
| 
       86 
     | 
    
         
            -
                  print reset "\n"
         
     | 
| 
      
 86 
     | 
    
         
            +
                  print reset, "\n"
         
     | 
| 
       87 
87 
     | 
    
         
             
                  return 0
         
     | 
| 
       88 
88 
     | 
    
         
             
                rescue RestClient::Exception => e
         
     | 
| 
       89 
89 
     | 
    
         
             
                  print_rest_exception(e, options)
         
     | 
| 
         @@ -303,6 +303,16 @@ class Morpheus::Cli::ReportsCommand 
     | 
|
| 
       303 
303 
     | 
    
         | 
| 
       304 
304 
     | 
    
         
             
                  end
         
     | 
| 
       305 
305 
     | 
    
         | 
| 
      
 306 
     | 
    
         
            +
                  if payload['report']['startMonth'].size > 7 || payload['report']['endMonth'].size > 7
         
     | 
| 
      
 307 
     | 
    
         
            +
                     print_green_success "The CLI generates a query that will use only month and year. However, the API does support yyyy-mm-dd from a previous version of Morpheus.\nReplace startMonth/endMonth keys with startDate,endDate ie:"
         
     | 
| 
      
 308 
     | 
    
         
            +
                     payload['report'].delete('startMonth')
         
     | 
| 
      
 309 
     | 
    
         
            +
                     payload['report'].delete('endMonth')
         
     | 
| 
      
 310 
     | 
    
         
            +
                     payload['report']['startDate'] = 'yyyy-mm-dd'
         
     | 
| 
      
 311 
     | 
    
         
            +
                     payload['report']['endDate'] = 'yyyy-mm-dd'
         
     | 
| 
      
 312 
     | 
    
         
            +
                     print_dry_run @reports_interface.dry.create(payload)
         
     | 
| 
      
 313 
     | 
    
         
            +
                  return 0
         
     | 
| 
      
 314 
     | 
    
         
            +
                  end
         
     | 
| 
      
 315 
     | 
    
         
            +
             
     | 
| 
       306 
316 
     | 
    
         
             
                  @reports_interface.setopts(options)
         
     | 
| 
       307 
317 
     | 
    
         
             
                  if options[:dry_run]
         
     | 
| 
       308 
318 
     | 
    
         
             
                    print_dry_run @reports_interface.dry.create(payload)
         
     | 
| 
         @@ -661,7 +661,8 @@ EOT 
     | 
|
| 
       661 
661 
     | 
    
         
             
                    it
         
     | 
| 
       662 
662 
     | 
    
         
             
                  }
         
     | 
| 
       663 
663 
     | 
    
         
             
                  if catalog_option_types && !catalog_option_types.empty?
         
     | 
| 
       664 
     | 
    
         
            -
                     
     | 
| 
      
 664 
     | 
    
         
            +
                    api_params = construct_catalog_api_params(catalog_item_type)
         
     | 
| 
      
 665 
     | 
    
         
            +
                    config_prompt = Morpheus::Cli::OptionTypes.prompt(catalog_option_types, options[:options], @api_client, api_params, options[:no_prompt], false, false, true)['config']
         
     | 
| 
       665 
666 
     | 
    
         
             
                    payload[add_item_object_key].deep_merge!({'config' => config_prompt})
         
     | 
| 
       666 
667 
     | 
    
         
             
                  end
         
     | 
| 
       667 
668 
     | 
    
         
             
                  if workflow_context
         
     | 
| 
         @@ -999,11 +1000,13 @@ EOT 
     | 
|
| 
       999 
1000 
     | 
    
         
             
                    catalog_option_types = catalog_item_type['optionTypes']
         
     | 
| 
       1000 
1001 
     | 
    
         
             
                    # instead of config.customOptions just use config...
         
     | 
| 
       1001 
1002 
     | 
    
         
             
                    catalog_option_types = catalog_option_types.collect {|it|
         
     | 
| 
      
 1003 
     | 
    
         
            +
                      it['fieldContext'] = nil
         
     | 
| 
       1002 
1004 
     | 
    
         
             
                      it['fieldContext'] = 'config'
         
     | 
| 
       1003 
1005 
     | 
    
         
             
                      it
         
     | 
| 
       1004 
1006 
     | 
    
         
             
                    }
         
     | 
| 
       1005 
1007 
     | 
    
         
             
                    if catalog_option_types && !catalog_option_types.empty?
         
     | 
| 
       1006 
     | 
    
         
            -
                       
     | 
| 
      
 1008 
     | 
    
         
            +
                      api_params = construct_catalog_api_params(catalog_item_type)
         
     | 
| 
      
 1009 
     | 
    
         
            +
                      config_prompt = Morpheus::Cli::OptionTypes.prompt(catalog_option_types, options[:options], @api_client, api_params, options[:no_prompt], false, false, true)['config']
         
     | 
| 
       1007 
1010 
     | 
    
         
             
                      item_payload.deep_merge!({'config' => config_prompt})
         
     | 
| 
       1008 
1011 
     | 
    
         
             
                    end
         
     | 
| 
       1009 
1012 
     | 
    
         | 
| 
         @@ -1471,4 +1474,35 @@ EOT 
     | 
|
| 
       1471 
1474 
     | 
    
         
             
                out + return_color
         
     | 
| 
       1472 
1475 
     | 
    
         
             
              end
         
     | 
| 
       1473 
1476 
     | 
    
         | 
| 
      
 1477 
     | 
    
         
            +
              
         
     | 
| 
      
 1478 
     | 
    
         
            +
              def construct_catalog_api_params(record)
         
     | 
| 
      
 1479 
     | 
    
         
            +
                catalog_item_type_id = record['id'].to_i
         
     | 
| 
      
 1480 
     | 
    
         
            +
                api_params = {}
         
     | 
| 
      
 1481 
     | 
    
         
            +
                api_params['catalogItemType'] ||= {}
         
     | 
| 
      
 1482 
     | 
    
         
            +
                api_params['catalogItemType']['id'] = catalog_item_type_id
         
     | 
| 
      
 1483 
     | 
    
         
            +
                # Determine instance.type value
         
     | 
| 
      
 1484 
     | 
    
         
            +
                # the UI is injecting this parameter into the option source requests
         
     | 
| 
      
 1485 
     | 
    
         
            +
                # it is needed to populate api option lists eg. optionTypeClouds
         
     | 
| 
      
 1486 
     | 
    
         
            +
                # this should be fixed on the api side, so it automatically extracts this input from the config
         
     | 
| 
      
 1487 
     | 
    
         
            +
                begin
         
     | 
| 
      
 1488 
     | 
    
         
            +
                  instance_type_code = nil
         
     | 
| 
      
 1489 
     | 
    
         
            +
                  catalog_item_type = find_by_id(:catalog_item_type, catalog_item_type_id.to_i)
         
     | 
| 
      
 1490 
     | 
    
         
            +
                  if catalog_item_type
         
     | 
| 
      
 1491 
     | 
    
         
            +
                    if catalog_item_type['type'] == 'instance'
         
     | 
| 
      
 1492 
     | 
    
         
            +
                      if catalog_item_type['config'] && catalog_item_type['config']['type']
         
     | 
| 
      
 1493 
     | 
    
         
            +
                        instance_type_code = catalog_item_type['config']['type']
         
     | 
| 
      
 1494 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1495 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1496 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1497 
     | 
    
         
            +
                  if instance_type_code
         
     | 
| 
      
 1498 
     | 
    
         
            +
                    api_params['instance'] ||= {}
         
     | 
| 
      
 1499 
     | 
    
         
            +
                    api_params['instance']['type'] = instance_type_code
         
     | 
| 
      
 1500 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1501 
     | 
    
         
            +
                rescue ::RestClient::Exception => e
         
     | 
| 
      
 1502 
     | 
    
         
            +
                  # users may not have permission to this endpoint
         
     | 
| 
      
 1503 
     | 
    
         
            +
                  # puts "Failed to load catalog item type"
         
     | 
| 
      
 1504 
     | 
    
         
            +
                end
         
     | 
| 
      
 1505 
     | 
    
         
            +
                return api_params
         
     | 
| 
      
 1506 
     | 
    
         
            +
              end
         
     | 
| 
      
 1507 
     | 
    
         
            +
             
     | 
| 
       1474 
1508 
     | 
    
         
             
            end
         
     | 
| 
         @@ -137,7 +137,7 @@ class Morpheus::Cli::WhitelabelSettingsCommand 
     | 
|
| 
       137 
137 
     | 
    
         
             
                    print cyan
         
     | 
| 
       138 
138 
     | 
    
         
             
                    print options[:details] ? content : truncate_string(content, trunc_len), "\n"
         
     | 
| 
       139 
139 
     | 
    
         
             
                  end
         
     | 
| 
       140 
     | 
    
         
            -
                  print reset "\n"
         
     | 
| 
      
 140 
     | 
    
         
            +
                  print reset, "\n"
         
     | 
| 
       141 
141 
     | 
    
         
             
                  return 0
         
     | 
| 
       142 
142 
     | 
    
         
             
                rescue RestClient::Exception => e
         
     | 
| 
       143 
143 
     | 
    
         
             
                  print_rest_exception(e, options)
         
     | 
| 
         @@ -123,7 +123,8 @@ module Morpheus 
     | 
|
| 
       123 
123 
     | 
    
         
             
                          end
         
     | 
| 
       124 
124 
     | 
    
         
             
                          if password.empty?
         
     | 
| 
       125 
125 
     | 
    
         
             
                            # readline is still echoing secret with 'NUL:'' so just use $stdin on windows for now
         
     | 
| 
       126 
     | 
    
         
            -
                             
     | 
| 
      
 126 
     | 
    
         
            +
                            # and some other environments? just use noecho unless running unit tests
         
     | 
| 
      
 127 
     | 
    
         
            +
                            if Morpheus::Cli.windows? || !Morpheus::Cli.testing?
         
     | 
| 
       127 
128 
     | 
    
         
             
                              print "Password: #{required_blue_prompt} "
         
     | 
| 
       128 
129 
     | 
    
         
             
                              # this should be my_terminal.stdin instead of STDIN and $stdin
         
     | 
| 
       129 
130 
     | 
    
         
             
                              password = $stdin.noecho(&:gets).chomp!
         
     | 
| 
         @@ -1435,7 +1435,7 @@ module Morpheus::Cli::ProvisioningHelper 
     | 
|
| 
       1435 
1435 
     | 
    
         
             
                          'id' => current_volume['id'].to_i,
         
     | 
| 
       1436 
1436 
     | 
    
         
             
                          'rootVolume' => false,
         
     | 
| 
       1437 
1437 
     | 
    
         
             
                          'name' => current_volume['name'],
         
     | 
| 
       1438 
     | 
    
         
            -
                          'size' => current_volume['size']  
     | 
| 
      
 1438 
     | 
    
         
            +
                          'size' => current_volume['size'] ? current_volume['size'] : (plan_size || 0),
         
     | 
| 
       1439 
1439 
     | 
    
         
             
                          'sizeId' => nil,
         
     | 
| 
       1440 
1440 
     | 
    
         
             
                          'storageType' => (current_volume['type'] || current_volume['storageType']),
         
     | 
| 
       1441 
1441 
     | 
    
         
             
                          'datastoreId' => current_volume['datastoreId']
         
     | 
| 
         @@ -2003,9 +2003,10 @@ module Morpheus::Cli::ProvisioningHelper 
     | 
|
| 
       2003 
2003 
     | 
    
         
             
                group_access = nil
         
     | 
| 
       2004 
2004 
     | 
    
         
             
                all_plans = nil
         
     | 
| 
       2005 
2005 
     | 
    
         
             
                plan_access = nil
         
     | 
| 
      
 2006 
     | 
    
         
            +
                permissions = {}
         
     | 
| 
       2006 
2007 
     | 
    
         | 
| 
       2007 
2008 
     | 
    
         
             
                # Group Access
         
     | 
| 
       2008 
     | 
    
         
            -
                 
     | 
| 
      
 2009 
     | 
    
         
            +
                unless excludes.include?('groups')
         
     | 
| 
       2009 
2010 
     | 
    
         
             
                  if !options[:groupAccessAll].nil?
         
     | 
| 
       2010 
2011 
     | 
    
         
             
                    all_groups = options[:groupAccessAll]
         
     | 
| 
       2011 
2012 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -2055,7 +2056,7 @@ module Morpheus::Cli::ProvisioningHelper 
     | 
|
| 
       2055 
2056 
     | 
    
         
             
                end
         
     | 
| 
       2056 
2057 
     | 
    
         | 
| 
       2057 
2058 
     | 
    
         
             
                # Plan Access
         
     | 
| 
       2058 
     | 
    
         
            -
                 
     | 
| 
      
 2059 
     | 
    
         
            +
                unless excludes.include?('plans')
         
     | 
| 
       2059 
2060 
     | 
    
         
             
                  if !options[:planAccessAll].nil?
         
     | 
| 
       2060 
2061 
     | 
    
         
             
                    all_plans = options[:planAccessAll]
         
     | 
| 
       2061 
2062 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -2101,13 +2102,14 @@ module Morpheus::Cli::ProvisioningHelper 
     | 
|
| 
       2101 
2102 
     | 
    
         
             
                  end
         
     | 
| 
       2102 
2103 
     | 
    
         
             
                end
         
     | 
| 
       2103 
2104 
     | 
    
         | 
| 
       2104 
     | 
    
         
            -
                 
     | 
| 
       2105 
     | 
    
         
            -
             
     | 
| 
       2106 
     | 
    
         
            -
             
     | 
| 
       2107 
     | 
    
         
            -
             
     | 
| 
       2108 
     | 
    
         
            -
             
     | 
| 
       2109 
     | 
    
         
            -
             
     | 
| 
       2110 
     | 
    
         
            -
             
     | 
| 
      
 2105 
     | 
    
         
            +
                unless excludes.include?('resource')
         
     | 
| 
      
 2106 
     | 
    
         
            +
                  resource_perms = {}
         
     | 
| 
      
 2107 
     | 
    
         
            +
                  resource_perms['all'] = all_groups if !all_groups.nil?
         
     | 
| 
      
 2108 
     | 
    
         
            +
                  resource_perms['sites'] = group_access if !group_access.nil?
         
     | 
| 
      
 2109 
     | 
    
         
            +
                  resource_perms['allPlans'] = all_plans if !all_plans.nil?
         
     | 
| 
      
 2110 
     | 
    
         
            +
                  resource_perms['plans'] = plan_access if !plan_access.nil?
         
     | 
| 
      
 2111 
     | 
    
         
            +
                  permissions['resourcePermissions'] = resource_perms
         
     | 
| 
      
 2112 
     | 
    
         
            +
                end
         
     | 
| 
       2111 
2113 
     | 
    
         | 
| 
       2112 
2114 
     | 
    
         
             
                available_accounts = get_available_accounts() #.collect {|it| {'name' => it['name'], 'value' => it['id']}}
         
     | 
| 
       2113 
2115 
     | 
    
         
             
                accounts = []
         
     | 
| 
         @@ -2115,7 +2117,7 @@ module Morpheus::Cli::ProvisioningHelper 
     | 
|
| 
       2115 
2117 
     | 
    
         
             
                # Prompts for multi tenant
         
     | 
| 
       2116 
2118 
     | 
    
         
             
                if available_accounts.count > 1
         
     | 
| 
       2117 
2119 
     | 
    
         
             
                  visibility = options[:visibility]
         
     | 
| 
       2118 
     | 
    
         
            -
                   
     | 
| 
      
 2120 
     | 
    
         
            +
                  unless excludes.include?('visibility')
         
     | 
| 
       2119 
2121 
     | 
    
         
             
                    if !visibility && !options[:no_prompt]
         
     | 
| 
       2120 
2122 
     | 
    
         
             
                      visibility = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'visibility', 'fieldLabel' => 'Tenant Permissions Visibility', 'type' => 'select', 'defaultValue' => 'private', 'required' => true, 'selectOptions' => [{'name' => 'Private', 'value' => 'private'},{'name' => 'Public', 'value' => 'public'}]}], options[:options], @api_client, {})['visibility']
         
     | 
| 
       2121 
2123 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -2123,7 +2125,7 @@ module Morpheus::Cli::ProvisioningHelper 
     | 
|
| 
       2123 
2125 
     | 
    
         
             
                  end
         
     | 
| 
       2124 
2126 
     | 
    
         | 
| 
       2125 
2127 
     | 
    
         
             
                  # Tenants
         
     | 
| 
       2126 
     | 
    
         
            -
                   
     | 
| 
      
 2128 
     | 
    
         
            +
                  unless excludes.include?('tenants')
         
     | 
| 
       2127 
2129 
     | 
    
         
             
                    if !options[:tenants].nil?
         
     | 
| 
       2128 
2130 
     | 
    
         
             
                      accounts = options[:tenants].collect {|id| id.to_i}
         
     | 
| 
       2129 
2131 
     | 
    
         
             
                    elsif !options[:no_prompt]
         
     | 
| 
         @@ -720,9 +720,13 @@ EOT 
     | 
|
| 
       720 
720 
     | 
    
         
             
                    else
         
     | 
| 
       721 
721 
     | 
    
         
             
                      perms = prompt_permissions(options.deep_merge(rest_perms_config[:options] || {}), rest_perms_config[:excludes] || [])
         
     | 
| 
       722 
722 
     | 
    
         
             
                    end
         
     | 
| 
       723 
     | 
    
         
            -
                     
     | 
| 
      
 723 
     | 
    
         
            +
                    unless rest_perms_config[:name].nil?
         
     | 
| 
       724 
724 
     | 
    
         
             
                      perms.transform_keys! {|k| k == 'resourcePermissions' ? rest_perms_config[:name] : k}
         
     | 
| 
       725 
725 
     | 
    
         
             
                    end
         
     | 
| 
      
 726 
     | 
    
         
            +
                    unless rest_perms_config[:context].nil?
         
     | 
| 
      
 727 
     | 
    
         
            +
                      perms_context = {}
         
     | 
| 
      
 728 
     | 
    
         
            +
                      perms_context[rest_perms_config[:context]] = perms
         
     | 
| 
      
 729 
     | 
    
         
            +
                    end
         
     | 
| 
       726 
730 
     | 
    
         
             
                    record_payload.merge!(perms)
         
     | 
| 
       727 
731 
     | 
    
         
             
                  end
         
     | 
| 
       728 
732 
     | 
    
         
             
                  payload[rest_object_key] = record_payload
         
     |