class Object
Constants
- ALTERNATE_TIME_FORMAT
- DEFAULT_DATE_FORMAT
- DEFAULT_TIME_FORMAT
Public Instance Methods
Source
# File lib/morpheus/cli/commands/apps.rb, line 1775 def _restart(app_id, options) app = find_app_by_name_or_id(app_id) return 1 if app.nil? tier_records = extract_app_tiers(app) if options[:dry_run] print_h1 "Dry Run", [], options end tier_records.each do |tier_record| tier_record[:instances].each do |instance| restart_cmd = "instances restart #{instance['id']} -y" if options[:dry_run] puts restart_cmd else my_terminal.execute(restart_cmd) end end end return 0 end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1731 def _start(app_id, options) app = find_app_by_name_or_id(app_id) return 1 if app.nil? tier_records = extract_app_tiers(app) if options[:dry_run] print_h1 "Dry Run", [], options end tier_records.each do |tier_record| tier_record[:instances].each do |instance| start_cmd = "instances start #{instance['id']} -y" if options[:dry_run] puts start_cmd else my_terminal.execute(start_cmd) end end end return 0 end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1687 def _stop(app_id, options) app = find_app_by_name_or_id(app_id) return 1 if app.nil? tier_records = extract_app_tiers(app) if options[:dry_run] print_h1 "Dry Run", [], options end tier_records.each do |tier_record| tier_record[:instances].each do |instance| stop_cmd = "instances stop #{instance['id']} -y" if options[:dry_run] puts stop_cmd else my_terminal.execute(stop_cmd) end end end return 0 end
Source
# File lib/morpheus/cli/commands/apps.rb, line 2131 def _view(arg, options={}) begin app = find_app_by_name_or_id(arg) return 1 if app.nil? link = "#{@appliance_url}/login/oauth-redirect?access_token=#{@access_token}\\&redirectUri=/provisioning/apps/#{app['id']}" if options[:link_tab] link << "#!#{options[:link_tab]}" end if options[:dry_run] puts Morpheus::Util.open_url_command(link) return 0 end return Morpheus::Util.open_url(link) rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/formatters.rb, line 493 def a_or_an(v) v.to_s =~ /^[aeiou]/i ? "an" : "a" end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 258 def add(args) params = {} file_params = {} options = {} task_name = nil task_code = nil task_type_name = nil task_visibility = nil optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[name] -t TASK_TYPE") opts.on( '-t', '--type TASK_TYPE', "Task Type" ) do |val| task_type_name = val end opts.on('--name NAME', String, "Task Name" ) do |val| task_name = val end opts.on('--visibility VISIBILITY', String, "Task Visibility" ) do |val| task_visibility = val end opts.on('-l', '--labels [LIST]', String, "Labels") do |val| options[:options]['labels'] = parse_labels(val) end opts.on('--code CODE', String, "Task Code" ) do |val| task_code = val end opts.on('--source VALUE', String, "Source Type. local, repository, url. Only applies to script task types.") do |val| file_params['sourceType'] = val end opts.on('--content TEXT', String, "Contents of the task script. This implies source is local.") do |val| file_params['sourceType'] = 'local' if file_params['sourceType'].nil? file_params['content'] = val end opts.on('--file FILE', "File containing the task script. This can be used instead of --content" ) do |filename| file_params['sourceType'] = 'local' if file_params['sourceType'].nil? full_filename = File.expand_path(filename) if File.exist?(full_filename) file_params['content'] = File.read(full_filename) else print_red_alert "File not found: #{full_filename}" exit 1 end end opts.on('--url VALUE', String, "URL, for use when source is url") do |val| file_params['contentPath'] = val end opts.on('--content-path VALUE', String, "Content Path, for use when source is repository or url") do |val| file_params['contentPath'] = val end opts.on('--content-ref VALUE', String, "Content Ref (Version Ref), for use when source is repository") do |val| file_params['contentRef'] = val end opts.on('--result-type VALUE', String, "Result Type" ) do |val| options[:options]['resultType'] = val end opts.on('--result-type VALUE', String, "Result Type" ) do |val| options[:options]['executeTarget'] = val end opts.on('--execute-target VALUE', String, "Execute Target" ) do |val| options[:options]['executeTarget'] = val end opts.on('--credential VALUE', String, "Credential ID or \"local\"" ) do |val| options[:options]['credential'] = val end opts.on('--target-host VALUE', String, "Target Host" ) do |val| options[:options]['taskOptions'] ||= {} options[:options]['taskOptions']['host'] = val end opts.on('--target-port VALUE', String, "Target Port" ) do |val| options[:options]['taskOptions'] ||= {} options[:options]['taskOptions']['port'] = val end opts.on('--target-username VALUE', String, "Target Username" ) do |val| options[:options]['taskOptions'] ||= {} options[:options]['taskOptions']['username'] = val end opts.on('--target-password VALUE', String, "Target Password" ) do |val| options[:options]['taskOptions'] ||= {} options[:options]['taskOptions']['password'] = val end opts.on('--target-ssh-key VALUE', String, "Target SSH Key" ) do |val| options[:options]['taskOptions'] ||= {} options[:options]['taskOptions']['sshKey'] = val end opts.on('--git-repo VALUE', String, "Git Repo ID" ) do |val| options[:options]['taskOptions'] ||= {} options[:options]['taskOptions']['localScriptGitId'] = val end opts.on('--git-ref VALUE', String, "Git Ref" ) do |val| options[:options]['taskOptions'] ||= {} options[:options]['taskOptions']['localScriptGitRef'] = val end opts.on('--retryable [on|off]', String, "Retryable" ) do |val| options[:options]['retryable'] = val.to_s == 'on' || val.to_s == 'true' || val == '' || val.nil? end opts.on('--retry-count COUNT', String, "Retry Count" ) do |val| options[:options]['retryCount'] = val.to_i end opts.on('--retry-delay SECONDS', String, "Retry Delay Seconds" ) do |val| options[:options]['retryDelaySeconds'] = val.to_i end opts.on('--allow-custom-config [on|off]', String, "Allow Custom Config") do |val| options[:options]['allowCustomConfig'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '' end build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote]) end optparse.parse!(args) #verify_args!(args:args, count:1, optparse:optparse) if args[0] # task_name = args[0] task_name = args[0] end # if task_name.nil? || task_type_name.nil? # puts optparse # exit 1 # end connect(options) begin passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {} if passed_options['type'] task_type_name = passed_options.delete('type') end payload = nil if options[:payload] payload = options[:payload] payload.deep_merge!({'task' => passed_options}) unless passed_options.empty? payload.deep_merge!({'task' => {'file' => file_params}}) unless file_params.empty? else # construct payload payload = { "task" => { #"name" => task_name, #"code" => task_code, #"taskType" {"id" => task_type['id'], "code" => task_type['code']}, #"taskOptions" => {} } } payload.deep_merge!({'task' => passed_options}) unless passed_options.empty? # Name if task_name payload['task']['name'] = task_name else v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Name'}], options[:options], @api_client) payload['task']['name'] = v_prompt['name'] unless v_prompt['name'].to_s.empty? end # Code if task_code payload['task']['code'] = task_code else v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'code', 'fieldLabel' => 'Code', 'type' => 'text', 'description' => 'Code'}], options[:options], @api_client) payload['task']['code'] = v_prompt['code'] unless v_prompt['code'].to_s.empty? end # Task Type @all_task_types ||= @tasks_interface.list_types({max:1000})['taskTypes'] task_types_dropdown = @all_task_types.collect {|it| {"name" => it["name"], "value" => it["code"]}} if task_type_name #payload['task']['taskType'] = task_type_name else v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => task_types_dropdown, 'required' => true}], options[:options], @api_client) task_type_name = v_prompt['type'] end task_type = find_task_type_by_name(task_type_name) if task_type.nil? print_red_alert "Task Type not found by code '#{task_type_name}'" return 1 end # Visibility if task_visibility != nil payload['task']['visibility'] = task_visibility else payload['task']['visibility'] = 'private' end payload['task']['taskType'] = {"id" => task_type['id'], "code" => task_type['code']} # Result Type if options[:options]['resultType'] payload['task']['resultType'] = options[:options]['resultType'] elsif task_type['hasResults'] result_types_dropdown = [{"name" => "Value", "value" => "value"}, {"name" => "Exit Code", "value" => "exitCode"}, {"name" => "Key Value", "value" => "keyValue"}, {"name" => "JSON", "value" => "json"}] v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'resultType', 'fieldLabel' => 'Result Type', 'type' => 'select', 'selectOptions' => result_types_dropdown}], options[:options], @api_client) payload['task']['resultType'] = v_prompt['resultType'] unless v_prompt['resultType'].to_s.empty? end # Task Type Option Types # correct fieldContext has_file_content = false task_option_types = task_type['optionTypes'] || [] task_option_types.each do |it| if it['type'] == 'file-content' has_file_content = true it['fieldContext'] = nil it['fieldName'] = 'file' # this should be required right!? fix api optionType data plz it['required'] = true it['defaultValue'] = 'local' else if it['fieldContext'].nil? || it['fieldContext'] == '' it['fieldContext'] = 'taskOptions' end # taskOptions should prompt for code instead of fieldName, oy vey if it['fieldContext'] == 'taskOptions' it['fieldName'] = it['code'] end end end process_special_task_option_typeaheads(task_option_types) # inject file_params into options for file-content prompt # or into taskOptions.script for types not yet using file-content unless file_params.empty? if has_file_content options[:options]['file'] ||= {} options[:options]['file'].merge!(file_params) else options[:options]['taskOptions'] ||= {} options[:options]['taskOptions']['script'] = file_params['content'] if file_params['content'] end end # prompt # tasks are different in that they use the optionType code instead of fieldName for the key values input_options = Morpheus::Cli::OptionTypes.prompt(task_option_types, options[:options],@api_client, options[:params]) # flatten taskOptions as serverside expects if input_options['taskOptions'] input_options['taskOptions'] = Morpheus::RestClient.grails_params(input_options['taskOptions']) # remove "off" checkbox values, like the UI does input_options['taskOptions'].keys.each do |k| if input_options['taskOptions'][k] == "off" input_options['taskOptions'].delete(k) end end end payload.deep_merge!({'task' => input_options}) unless input_options.empty? # Target Options if options[:options]['executeTarget'] != nil payload['task']['executeTarget'] = options[:options]['executeTarget'] else default_target = nil execute_targets_dropdown = [] if task_type['allowExecuteLocal'] default_target = 'local' execute_targets_dropdown << {"name" => "Local", "value" => "local"} end if task_type['allowExecuteRemote'] default_target = 'remote' execute_targets_dropdown << {"name" => "Remote", "value" => "remote"} end if task_type['allowExecuteResource'] default_target = 'resource' execute_targets_dropdown << {"name" => "Resource", "value" => "resource"} end if !execute_targets_dropdown.empty? v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'executeTarget', 'fieldLabel' => 'Execute Target', 'type' => 'select', 'selectOptions' => execute_targets_dropdown, 'defaultValue' => default_target, 'required' => true}], options[:options], @api_client) payload['task']['executeTarget'] = v_prompt['executeTarget'].to_s unless v_prompt['executeTarget'].to_s.empty? end end if payload['task']['executeTarget'] == 'local' if task_type['allowLocalRepo'] # Git Repo v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'taskOptions', 'fieldName' => 'localScriptGitId', 'fieldLabel' => 'Git Repo', 'type' => 'text', 'description' => 'Git Repo ID'}], options[:options], @api_client) if v_prompt['taskOptions'] && !v_prompt['taskOptions']['localScriptGitId'].to_s.empty? payload['task']['taskOptions'] ||= {} payload['task']['taskOptions']['localScriptGitId'] = v_prompt['taskOptions']['localScriptGitId'] end # Git Ref v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'taskOptions', 'fieldName' => 'localScriptGitRef', 'fieldLabel' => 'Git Ref', 'type' => 'text', 'description' => 'Git Ref eg. master'}], options[:options], @api_client) if v_prompt['taskOptions'] && !v_prompt['taskOptions']['localScriptGitRef'].to_s.empty? payload['task']['taskOptions'] ||= {} payload['task']['taskOptions']['localScriptGitRef'] = v_prompt['taskOptions']['localScriptGitRef'] end end elsif payload['task']['executeTarget'] == 'remote' # Host v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'taskOptions', 'fieldName' => 'host', 'fieldLabel' => 'IP Address', 'type' => 'text', 'description' => 'IP Address / Host for remote execution'}], options[:options], @api_client) if v_prompt['taskOptions'] && !v_prompt['taskOptions']['host'].to_s.empty? payload['task']['taskOptions'] ||= {} payload['task']['taskOptions']['host'] = v_prompt['taskOptions']['host'] end # Port v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'taskOptions', 'fieldName' => 'port', 'fieldLabel' => 'Port', 'type' => 'text', 'description' => 'Port for remote execution', 'defaultValue' => '22'}], options[:options], @api_client) if v_prompt['taskOptions'] && !v_prompt['taskOptions']['port'].to_s.empty? payload['task']['taskOptions'] ||= {} payload['task']['taskOptions']['port'] = v_prompt['taskOptions']['port'] end # Credentials credential_code = "credential" credential_option_type = {'code' => credential_code, 'fieldName' => credential_code, 'fieldLabel' => 'Credentials', 'type' => 'select', 'optionSource' => 'credentials', 'description' => 'Enter an existing credential ID or choose "local"', 'defaultValue' => "local", 'required' => true} supported_credential_types = ['username-keypair', 'username-password', 'username-password-keypair'].compact.flatten.join(",").split(",").collect {|it| it.strip } credential_params = {"new" => false, "credentialTypes" => supported_credential_types} credential_value = Morpheus::Cli::OptionTypes.select_prompt(credential_option_type, @api_client, credential_params, options[:no_prompt], options[:options][credential_code]) if !credential_value.to_s.empty? if credential_value == "local" payload['task'][credential_code] = {"type" => credential_value} elsif credential_value.to_s =~ /\A\d{1,}\Z/ payload['task'][credential_code] = {"id" => credential_value.to_i} end end if credential_value == "local" # Username v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'taskOptions', 'fieldName' => 'username', 'fieldLabel' => 'Username', 'type' => 'text', 'description' => 'Username for remote execution'}], options[:options], @api_client) if v_prompt['taskOptions'] && !v_prompt['taskOptions']['username'].to_s.empty? payload['task']['taskOptions'] ||= {} payload['task']['taskOptions']['username'] = v_prompt['taskOptions']['username'] end # Password v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'taskOptions', 'fieldName' => 'password', 'fieldLabel' => 'Password', 'type' => 'password', 'description' => 'Password for remote execution'}], options[:options], @api_client) if v_prompt['taskOptions'] && !v_prompt['taskOptions']['password'].to_s.empty? payload['task']['taskOptions'] ||= {} payload['task']['taskOptions']['password'] = v_prompt['taskOptions']['password'] end # SSH Key v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'taskOptions', 'fieldName' => 'sshKey', 'fieldLabel' => 'Key', 'type' => 'select', 'optionSource' => 'keyPairs', 'description' => 'SSH Key for remote execution'}], options[:options], @api_client) if v_prompt['taskOptions'] && !v_prompt['taskOptions']['sshKey'].to_s.empty? payload['task']['taskOptions'] ||= {} payload['task']['taskOptions']['sshKey'] = v_prompt['taskOptions']['sshKey'] end end end # Retryable if options[:options]['retryable'] != nil payload['task']['retryable'] = options[:options]['retryable'] else v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'retryable', 'fieldLabel' => 'Retryable', 'type' => 'checkbox', 'defaultValue' => false}], options[:options], @api_client) payload['task']['retryable'] = ['true','on'].include?(v_prompt['retryable'].to_s) unless v_prompt['retryable'].nil? end if payload['task']['retryable'] # Retry Count if options[:options]['retryCount'] payload['task']['retryCount'] = options[:options]['retryCount'].to_i else v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'retryCount', 'fieldLabel' => 'Retry Count', 'type' => 'number', 'defaultValue' => 5}], options[:options], @api_client) payload['task']['retryCount'] = v_prompt['retryCount'].to_i unless v_prompt['retryCount'].nil? end # Retry Delay if options[:options]['retryDelaySeconds'] payload['task']['retryDelaySeconds'] = options[:options]['retryDelaySeconds'].to_i else v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'retryDelaySeconds', 'fieldLabel' => 'Retry Delay', 'type' => 'number', 'defaultValue' => 10}], options[:options], @api_client) payload['task']['retryDelaySeconds'] = v_prompt['retryDelaySeconds'].to_i unless v_prompt['retryDelaySeconds'].nil? end end # Allow Custom Config if options[:options]['allowCustomConfig'] != nil payload['task']['allowCustomConfig'] = options[:options]['allowCustomConfig'] else v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'allowCustomConfig', 'fieldLabel' => 'Allow Custom Config', 'type' => 'checkbox', 'defaultValue' => false}], options[:options], @api_client) payload['task']['allowCustomConfig'] = ['true','on'].include?(v_prompt['allowCustomConfig'].to_s) unless v_prompt['allowCustomConfig'].nil? end end @tasks_interface.setopts(options) if options[:dry_run] print_dry_run @tasks_interface.dry.create(payload) return end json_response = @tasks_interface.create(payload) task = json_response['task'] if options[:json] print JSON.pretty_generate(json_response),"\n" elsif !options[:quiet] task = json_response['task'] print_green_success "Task #{task['name']} created" get([task['id']]) end rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1304 def add_instance(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app] [instance] [tier]") build_common_options(opts, options, [:options, :json, :dry_run]) opts.footer = "Add an existing instance to an app.\n" + "[app] is required. This is the name or id of an app." + "\n" + "[instance] is required. This is the name or id of an instance." + "\n" + "[tier] is required. This is the name of the tier." end optparse.parse!(args) if args.count < 1 || args.count > 3 print_error Morpheus::Terminal.angry_prompt puts_error "#{command_name} add-instance expects 1-3 arguments and received #{args.count}: #{args}\n#{optparse}" return 1 end # optional [tier] and [instance] arguments if args[1] && args[1] !~ /\A\-/ options[:instance_name] = args[1] if args[2] && args[2] !~ /\A\-/ options[:tier_name] = args[2] end end connect(options) begin app = find_app_by_name_or_id(args[0]) # Only supports adding an existing instance right now.. payload = {} if options[:instance_name] instance = find_instance_by_name_or_id(options[:instance_name]) else v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'instance', 'fieldLabel' => 'Instance', 'type' => 'text', 'required' => true, 'description' => 'Enter the instance name or id'}], options[:options]) instance = find_instance_by_name_or_id(v_prompt['instance']) end payload[:instanceId] = instance['id'] if options[:tier_name] payload[:tierName] = options[:tier_name] else v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'tier', 'fieldLabel' => 'Tier', 'type' => 'text', 'required' => true, 'description' => 'Enter the name of the tier'}], options[:options]) payload[:tierName] = v_prompt['tier'] end @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.add_instance(app['id'], payload) return end json_response = @apps_interface.add_instance(app['id'], payload) if options[:json] print JSON.pretty_generate(json_response) print "\n" else print_green_success "Added instance #{instance['name']} to app #{app['name']}" #get(app['id']) end return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/formatters.rb, line 465 def anded_list(items, limit=nil) format_list(items, "and", limit) end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1022 def apply(args) default_refresh_interval = 5 params, payload, options = {}, {}, {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app] [options]") opts.on( '-p', '--parameter NAME=VALUE', "Template parameter name and value" ) do |val| k, v = val.split("=") options[:options]['templateParameter'] ||= {} options[:options]['templateParameter'][k] = v end opts.on('--refresh [SECONDS]', String, "Refresh until execution is complete. Default interval is #{default_refresh_interval} seconds.") do |val| options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f end opts.on(nil, '--no-refresh', "Do not refresh" ) do options[:no_refresh] = true end opts.on(nil, '--no-validate', "Do not validate planned changes before apply" ) do options[:no_validate] = true end opts.on(nil, '--validate-only', "Only validate planned changes, do not execute the apply command." ) do options[:validate_only] = true end build_standard_update_options(opts, options, [:auto_confirm]) opts.footer = <<-EOT Apply an app. [app] is required. This is the name or id of an app. This is only supported by certain types of apps such as terraform. By default this executes two requests to validate and then apply the changes. The first request corresponds to the terraform plan command only. Use --no-validate to skip this step apply changes in one step. EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, count:1) connect(options) app = find_app_by_name_or_id(args[0]) return 1 if app.nil? # construct request params.merge!(parse_query_options(options)) payload = {} if options[:payload] payload = options[:payload] payload.deep_merge!(parse_passed_options(options)) else payload.deep_merge!(parse_passed_options(options)) # attempt to load prepare-apply to get templateParameter values and prompt for them # ok, actually use options/layoutParameters to get the list of parameters begin prepare_apply_json_response = @apps_interface.prepare_apply(app["id"]) config = prepare_apply_json_response['data'] variable_map = config['templateParameter'] # need to load the instance details to get the app cloud...ugh first_instance = app['instances'][0] instance = first_instance ? find_instance_by_name_or_id(first_instance['id']) : nil zone_id = instance ? instance['cloud']['id'] : nil api_params = {templateId: app['blueprint']['id'], appId: app['id'], zoneId: zone_id, siteId: app['group']['id']} layout_parameters = @options_interface.options_for_source('templateParameters',api_params)['data'] if layout_parameters && !layout_parameters.empty? variable_option_types = [] i = 0 layout_parameters.each do |layout_parameter| var_label = layout_parameter['displayName'] || layout_parameter['name'] var_name = layout_parameter['name'] var_value = variable_map ? variable_map[var_name] : layout_parameter['defaultValue'] if var_value.nil? && layout_parameter['defaultValue'] var_value = layout_parameter['defaultValue'] end var_type = (layout_parameter['passwordType'] || layout_parameter['sensitive']) ? 'password' : 'text' option_type = {'fieldContext' => 'templateParameter', 'fieldName' => var_name, 'fieldLabel' => var_label, 'type' => var_type, 'required' => true, 'defaultValue' => (var_value.to_s.empty? ? nil : var_value.to_s), 'displayOrder' => (i+1) } variable_option_types << option_type i+=1 end blueprint_type_display = format_blueprint_type(config['type']) if blueprint_type_display == "terraform" blueprint_type_display = "Terraform" end print_h2 "#{blueprint_type_display} Variables" v_prompt = Morpheus::Cli::OptionTypes.prompt(variable_option_types, options[:options], @api_client) v_prompt.deep_compact! payload.deep_merge!(v_prompt) end rescue RestClient::Exception => ex # if e.response && e.response.code == 404 Morpheus::Logging::DarkPrinter.puts "Unable to load config for app apply, skipping parameter prompting" if Morpheus::Logging.debug? # print_rest_exception(ex, options) # end end end @apps_interface.setopts(options) if options[:validate_only] # validate only if options[:dry_run] print_dry_run @apps_interface.dry.validate_apply(app["id"], params, payload) return end json_response = @apps_interface.validate_apply(app["id"], params, payload) print_green_success "Validating app #{app['name']}" execution_id = json_response['executionId'] if !options[:no_refresh] #Morpheus::Cli::ExecutionRequestCommand.new.handle(["get", execution_id, "--refresh", options[:refresh_interval].to_s]+ (options[:remote] ? ["-r",options[:remote]] : [])) validate_execution_request = wait_for_execution_request(execution_id, options) end elsif options[:no_validate] # skip validate, apply only if options[:dry_run] print_dry_run @apps_interface.dry.apply(app["id"], params, payload) return end json_response = @apps_interface.apply(app["id"], params, payload) render_response(json_response, options) do print_green_success "Applying app #{app['name']}" execution_id = json_response['executionId'] if !options[:no_refresh] #Morpheus::Cli::ExecutionRequestCommand.new.handle(["get", execution_id, "--refresh", options[:refresh_interval].to_s]+ (options[:remote] ? ["-r",options[:remote]] : [])) apply_execution_request = wait_for_execution_request(execution_id, options) end end else # validate and then apply if options[:dry_run] print_dry_run @apps_interface.dry.validate_apply(app["id"], params, payload) print_dry_run @apps_interface.dry.apply(app["id"], params, payload) return end json_response = @apps_interface.validate_apply(app["id"], params, payload) print_green_success "Validating app #{app['name']}" execution_id = json_response['executionId'] validate_execution_request = wait_for_execution_request(execution_id, options) if validate_execution_request['status'] != 'complete' print_red_alert "Validation failed. Changes will not be applied." return 1, "Validation failed. Changes will not be applied." else unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to apply these changes?") return 9, "aborted command" end json_response = @apps_interface.apply(app["id"], params, payload) render_response(json_response, options) do print_green_success "Applying app #{app['name']}" execution_id = json_response['executionId'] if !options[:no_refresh] #Morpheus::Cli::ExecutionRequestCommand.new.handle(["get", execution_id, "--refresh", options[:refresh_interval].to_s]+ (options[:remote] ? ["-r",options[:remote]] : [])) apply_execution_request = wait_for_execution_request(execution_id, options) end end end end return 0, nil end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1895 def apply_security_groups(args) options = {} params = {} clear_or_secgroups_specified = false optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app] [--clear] [-s]") opts.on( '-c', '--clear', "Clear all security groups" ) do params[:securityGroupIds] = [] clear_or_secgroups_specified = true end opts.on( '-s', '--secgroups SECGROUPS', "Apply the specified comma separated security group ids" ) do |secgroups| params[:securityGroupIds] = secgroups.split(",") clear_or_secgroups_specified = true end opts.on( '-h', '--help', "Print this help" ) do puts opts exit end build_common_options(opts, options, [:json, :dry_run]) end optparse.parse!(args) if args.count != 1 print_error Morpheus::Terminal.angry_prompt puts_error "#{command_name} apply-security-groups expects 1 argument and received #{args.count}: #{args}\n#{optparse}" return 1 end if !clear_or_secgroups_specified print_error Morpheus::Terminal.angry_prompt puts_error "#{command_name} apply-security-groups requires either --clear or --secgroups\n#{optparse}" return 1 end connect(options) begin app = find_app_by_name_or_id(args[0]) payload = params @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.apply_security_groups(app['id'], payload) return end @apps_interface.apply_security_groups(app['id'], payload) security_groups([args[0]]) rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1436 def cancel_removal(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app]") build_common_options(opts, options, [:json, :dry_run, :quiet, :remote]) end optparse.parse!(args) if args.count < 1 puts optparse exit 1 end connect(options) begin app = find_app_by_name_or_id(args[0]) @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.cancel_removal(app['id']) return end json_response = @apps_interface.cancel_removal(app['id']) if options[:json] print as_json(json_response, options), "\n" return elsif !options[:quiet] get([app['id']] + (options[:remote] ? ["-r",options[:remote]] : [])) end rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/formatters.rb, line 406 def currency_sym(currency) Money::Currency.new((currency || 'USD').to_sym).symbol end
Source
# File lib/morpheus/formatters.rb, line 196 def display_appliance(name, url) if name.to_s == "" || name == 'remote-url' # "#{url}" "#{url}" else # "#{name} #{url}" "[#{name}] #{url}" end end
Source
# File lib/morpheus/formatters.rb, line 509 def escape_filepath(filepath) filepath.to_s.split("/").select {|it| !it.to_s.empty? }.collect {|it| CGI::escape(it) }.join("/") end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 857 def execute(args) params = {} options = {} target_type = nil instance_ids = [] instances = [] instance_label = nil server_ids = [] servers = [] server_label = nil default_refresh_interval = 5 all_target_types = ['appliance', 'instance', 'instance-label', 'server', 'server-label'] optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[task] [options]") opts.on('--context-type VALUE', String, "Context Type, #{ored_list(all_target_types)}") do |val| val = val.downcase val = 'appliance' if val == 'none' if target_type && target_type != val raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})") end if !all_target_types.include?(val) raise ::OptionParser::InvalidOption.new("'#{val}' is invalid. It must be one of the following: instance, instance-label, server, server-label or appliance") end target_type = val end opts.on('--target-type VALUE', String, "alias for context-type") do |val| val = val.downcase val = 'appliance' if val == 'none' if target_type && target_type != val raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})") end if !all_target_types.include?(val) raise ::OptionParser::InvalidOption.new("'#{val}' is invalid. It must be one of the following: instance, instance-label, server, server-label or appliance") end target_type = val end opts.add_hidden_option('--target-type') opts.on('--instance INSTANCE', String, "Instance name or id to target for execution. This option can be passed more than once.") do |val| if target_type && target_type != 'instance' raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})") end target_type = 'instance' instance_ids << val end opts.on('--instances LIST', Array, "Instances, comma separated list of instance names or IDs.") do |list| if target_type && target_type != 'instance' raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})") end target_type = 'instance' instance_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq end opts.on('--instance-label LABEL', String, "Instance Label") do |val| if target_type && target_type != 'instance-label' raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})") end target_type = 'instance-label' instance_label = val end opts.on('--server SERVER', String, "Server name or id to target for execution. This option can be passed more than once.") do |val| if target_type && target_type != 'server' raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})") end target_type = 'server' server_ids << val end opts.on('--servers LIST', Array, "Servers, comma separated list of host names or IDs.") do |list| if target_type && target_type != 'server' raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})") end target_type = 'server' server_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq end opts.on('--server-label LABEL', String, "Server Label") do |val| if target_type && target_type != 'server-label' raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})") end target_type = 'server-label' server_label = val end opts.on('--host HOST', String, "alias for --server") do |val| if target_type && target_type != 'server' raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})") end target_type = 'server' server_ids << val end opts.add_hidden_option('--host') opts.on('--hosts HOSTS', Array, "alias for --servers") do |list| if target_type && target_type != 'server' raise ::OptionParser::InvalidOption.new("The --hosts option cannot be combined with another context (#{target_type})") end target_type = 'server' server_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq end opts.add_hidden_option('--hosts') opts.on('-a', '--appliance', "Execute on the appliance, the target is the appliance itself.") do if target_type && target_type != 'appliance' raise ::OptionParser::InvalidOption.new("The --appliance option cannot be combined with another context (#{target_type})") end target_type = 'appliance' end opts.on('--config [TEXT]', String, "Custom config") do |val| params['customConfig'] = val.to_s end opts.on('--refresh [SECONDS]', String, "Refresh until execution is complete. Default interval is #{default_refresh_interval} seconds.") do |val| options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f end opts.on(nil, '--no-refresh', "Do not refresh" ) do options[:no_refresh] = true end build_standard_post_options(opts, options) end optparse.parse!(args) if args.count != 1 raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}" end verify_args!(args:args, count:1, optparse:optparse) task_name = args[0] connect(options) begin task = find_task_by_name_or_id(task_name) return 1 if task.nil? passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {} payload = nil if options[:payload] payload = options[:payload] payload.deep_merge!({'job' => passed_options}) unless passed_options.empty? else # prompt for target type and target if target_type.nil? # todo: Need api to fetch available Context Types for taskId/workflowId available_target_types = get_available_contexts_for_task(task) default_target_type = available_target_types.first ? available_target_types.first['name'] : nil if !available_target_types.empty? default_target_type = available_target_types.first ? available_target_types.first['name'] : nil target_type = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'context-type', 'fieldName' => 'targetType', 'fieldLabel' => 'Context Type', 'type' => 'select', 'selectOptions' => available_target_types, 'defaultValue' => default_target_type, 'required' => true, 'description' => 'Context Type determines the type of target(s) for the execution'}], options[:options], @api_client)['targetType'] end end if target_type params['targetType'] = target_type end if target_type == 'instance' if instance_ids.empty? instance_ids_value = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instances', 'fieldName' => 'instances', 'fieldLabel' => 'Instance(s)', 'type' => 'text', 'required' => true, 'description' => 'Instances, comma separated list of instance names or IDs.'}], options[:options], @api_client)['instances'] instance_ids = parse_array(instance_ids_value) end instance_ids.each do |instance_id| instance = find_instance_by_name_or_id(instance_id) return 1 if instance.nil? instances << instance end params['instances'] = instances.collect {|it| it['id'] } elsif target_type == 'instance-label' if instance_label.nil? instance_label = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instance-label', 'fieldName' => 'instanceLabel', 'fieldLabel' => 'Instance Label', 'type' => 'text', 'required' => true, 'description' => 'Instance Label'}], options[:options], @api_client)['instanceLabel'] end # params['config'] ||= {} # params['config']['instanceLabel'] = instance_label params['instanceLabel'] = instance_label elsif target_type == 'server' if server_ids.empty? server_ids_value = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'servers', 'fieldName' => 'servers', 'fieldLabel' => 'Server(s)', 'type' => 'text', 'required' => true, 'description' => 'Servers, comma separated list of server names or IDs.'}], options[:options], @api_client)['servers'] server_ids = parse_array(server_ids_value) end server_ids.each do |server_id| server = find_server_by_name_or_id(server_id) return 1 if server.nil? servers << server end params['servers'] = servers.collect {|it| it['id'] } elsif target_type == 'server-label' if server_label.nil? server_label = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'server-label', 'fieldName' => 'serverLabel', 'fieldLabel' => 'Server Label', 'type' => 'text', 'required' => true, 'description' => 'Server Label'}], options[:options], @api_client)['serverLabel'] end # params['config'] ||= {} # params['config']['serverLabel'] = server_label params['serverLabel'] = server_label end # todo: prompt to task optionTypes for customOptions if task['optionTypes'] end job_payload = {} job_payload.deep_merge!(params) job_payload.deep_merge!(passed_options) unless passed_options.empty? payload = {'job' => job_payload} end @tasks_interface.setopts(options) if options[:dry_run] print_dry_run @tasks_interface.dry.run(task['id'], payload) return end json_response = @tasks_interface.run(task['id'], payload) render_response(json_response, options) do target_desc = nil if instances.size() > 0 target_desc = (instances.size() == 1) ? "instance #{instances[0]['name']}" : "#{instances.size()} instances" elsif servers.size() > 0 target_desc = (servers.size() == 1) ? "host #{servers[0]['name']}" : "#{servers.size()} hosts" end if target_desc print_green_success "Executing task #{task['name']} on #{target_desc}" else print_green_success "Executing task #{task['name']}" end if json_response["jobExecution"] && json_response["jobExecution"]["id"] job_execution_id = json_response["jobExecution"]["id"] if options[:no_refresh] get_args = [json_response["jobExecution"]["id"], "--details"] + (options[:remote] ? ["-r",options[:remote]] : []) Morpheus::Logging::DarkPrinter.puts((['jobs', 'get-execution'] + get_args).join(' ')) if Morpheus::Logging.debug? ::Morpheus::Cli::JobsCommand.new.handle(['get-execution'] + get_args) else #Morpheus::Cli::JobsCommand.new.handle(["get-execution", job_execution_id, "--refresh", options[:refresh_interval].to_s]+ (options[:remote] ? ["-r",options[:remote]] : [])) job_execution_results = wait_for_job_execution(job_execution_id, options.merge({:details => true})) end end end return 0, nil end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 2341 def extract_app_tiers(app) tier_rows = [] begin app_tiers = app['appTiers'] || [] sorted_app_tiers = app_tiers.sort {|a,b| a['bootSequence'] <=> b['bootSequence'] } sorted_app_tiers.each do |app_tier| tier_name = app_tier['tier']['name'] boot_sequence = app_tier['bootSequence'] || 0 instances = (app_tier['appInstances'] || []).collect {|it| it['instance']} row = {tier_name: tier_name, boot_sequence: boot_sequence, instances: instances} tier_rows << row end rescue => ex Morpheus::Logging::DarkPrinter.puts "Error extracting app instances: #{ex}" if Morpheus::Logging.debug? end return tier_rows end
Source
# File lib/morpheus/formatters.rb, line 250 def filter_data(data, include_fields=nil, exclude_fields=nil) if !data return data elsif data.is_a?(Array) new_data = data.collect { |it| filter_data(it, include_fields, exclude_fields) } return new_data elsif data.is_a?(Hash) if include_fields #new_data = data.select {|k, v| include_fields.include?(k.to_s) || include_fields.include?(k.to_sym) } # allow extracting dot pathed fields, just like get_object_value my_data = {} include_fields.each do |field| if field.nil? next end field = field.to_s if field.empty? next end # supports "field as Label" field_key = field.strip field_label = field_key if field.index(/\s+as\s+/) field_key, field_label = field.split(/\s+as\s+/) if !field_label field_label = field_key end end if field.include?(".") #if field.index(/\s+as\s+/) if field_label != field_key # collapse to a value my_data[field_label] = get_object_value(data, field_key) else # keep the full object structure namespaces = field.split(".") cur_data = data cur_filtered_data = my_data namespaces.each_with_index do |ns, index| if index != namespaces.length - 1 if cur_data && cur_data.respond_to?("key?") cur_data = cur_data.key?(ns) ? cur_data[ns] : cur_data[ns.to_sym] else cur_data = nil end cur_filtered_data[ns] ||= {} cur_filtered_data = cur_filtered_data[ns] else if cur_data && cur_data.respond_to?("key?") cur_filtered_data[ns] = cur_data.key?(ns) ? cur_data[ns] : cur_data[ns.to_sym] else cur_filtered_data[ns] = nil end end end end else #my_data[field] = data[field] || data[field.to_sym] my_data[field_label] = data.key?(field_key) ? data[field_key] : data[field_key.to_sym] end end return my_data elsif exclude_fields new_data = data.reject {|k, v| exclude_fields.include?(k.to_s) || exclude_fields.include?(k.to_sym) } return new_data end else return data # .clone end end
filter_data
filters Hash-like data to only the specified fields To specify fields of child objects, use a “.” Usage: filter_data
(instance, [“id”, “name”, “plan.name”])
Source
# File lib/morpheus/cli/commands/apps.rb, line 2490 def find_blueprint_by_id(id) begin json_response = @blueprints_interface.get(id.to_i) return json_response['blueprint'] rescue RestClient::Exception => e if e.response && e.response.code == 404 print_red_alert "Blueprint not found by id #{id}" else raise e end end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 2503 def find_blueprint_by_name(name) blueprints = @blueprints_interface.list({name: name.to_s})['blueprints'] if blueprints.empty? print_red_alert "Blueprint not found by name #{name}" return nil elsif blueprints.size > 1 print_red_alert "#{blueprints.size} blueprints found by name #{name}" # print_blueprints_table(blueprints, {color: red}) rows = blueprints.collect { |it| {id: it['id'], name: it['name']} } print red print as_pretty_table(rows, [:id, :name], {color:red}) print reset,"\n" return nil else return blueprints[0] end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 2482 def find_blueprint_by_name_or_id(val) if val.to_s =~ /\A\d{1,}\Z/ return find_blueprint_by_id(val) else return find_blueprint_by_name(val) end end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1303 def find_instance_by_id(id) begin json_response = @instances_interface.get(id.to_i) return json_response['instance'] rescue RestClient::Exception => e if e.response && e.response.code == 404 print_red_alert "Instance not found by id #{id}" return nil else raise e end end end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1317 def find_instance_by_name(name) instances = @instances_interface.list({name: name.to_s})['instances'] if instances.empty? print_red_alert "Instance not found by name #{name}" return nil elsif instances.size > 1 print_red_alert "#{instances.size} instances found by name #{name}" as_pretty_table(instances, [:id, :name], {color: red}) print_red_alert "Try using ID instead" print reset,"\n" return nil else return instances[0] end end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1295 def find_instance_by_name_or_id(val) if val.to_s =~ /\A\d{1,}\Z/ return find_instance_by_id(val) else return find_instance_by_name(val) end end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1341 def find_server_by_id(id) begin json_response = @servers_interface.get(id.to_i) return json_response['server'] rescue RestClient::Exception => e if e.response && e.response.code == 404 print_red_alert "Server not found by id #{id}" return nil else raise e end end end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1355 def find_server_by_name(name) servers = @servers_interface.list({name: name.to_s})['servers'] if servers.empty? print_red_alert "Host not found by name #{name}" return nil elsif servers.size > 1 print_red_alert "#{servers.size} hosts found by name #{name}" as_pretty_table(servers, [:id, :name], {color: red}) print_red_alert "Try using ID instead" print reset,"\n" return nil else return servers[0] end end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1333 def find_server_by_name_or_id(val) if val.to_s =~ /\A\d{1,}\Z/ return find_server_by_id(val) else return find_server_by_name(val) end end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1219 def find_task_by_id(id) begin json_response = @tasks_interface.get(id.to_i) return json_response['task'] rescue RestClient::Exception => e if e.response && e.response.code == 404 print_red_alert "Task not found by id #{id}" return nil else raise e end end end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1233 def find_task_by_name(name) tasks = @tasks_interface.list({name: name.to_s})['tasks'] if tasks.empty? print_red_alert "Task not found by name #{name}" return nil elsif tasks.size > 1 print_red_alert "#{tasks.size} tasks by name #{name}" print_tasks_table(tasks, {color: red}) print reset,"\n\n" return nil else return tasks[0] end end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1211 def find_task_by_name_or_id(val) if val.to_s =~ /\A\d{1,}\Z/ return find_task_by_id(val) else return find_task_by_name(val) end end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1248 def find_task_type_by_name(val) raise "find_task_type_by_name passed a bad name: #{val.inspect}" if val.to_s == '' @all_task_types ||= @tasks_interface.list_types({max:1000})['taskTypes'] if @all_task_types.nil? && !@all_task_types.empty? print_red_alert "No task types found" return nil end matching_task_types = @all_task_types.select { |it| val && (it['name'] == val || it['code'] == val || it['id'].to_s == val.to_s) } if matching_task_types.size == 1 return matching_task_types[0] elsif matching_task_types.size == 0 print_red_alert "Task Type not found by '#{val}'" else print_red_alert "#{matching_task_types.size} task types found by name #{name}" rows = matching_task_types.collect do |it| {id: it['id'], name: it['name'], code: it['code']} end print "\n" puts as_pretty_table(rows, [:name, :code], {color:red}) return nil end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1795 def firewall_disable(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app]") build_common_options(opts, options, [:json, :dry_run]) end optparse.parse!(args) if args.count != 1 print_error Morpheus::Terminal.angry_prompt puts_error "#{command_name} firewall-disable expects 1 argument and received #{args.count}: #{args}\n#{optparse}" return 1 end connect(options) begin app = find_app_by_name_or_id(args[0]) @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.firewall_disable(app['id']) return end @apps_interface.firewall_disable(app['id']) security_groups([args[0]]) rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1824 def firewall_enable(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app]") build_common_options(opts, options, [:json, :dry_run]) end optparse.parse!(args) if args.count != 1 print_error Morpheus::Terminal.angry_prompt puts_error "#{command_name} firewall-enable expects 1 argument and received #{args.count}: #{args}\n#{optparse}" return 1 end connect(options) begin app = find_app_by_name_or_id(args[0]) @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.firewall_enable(app['id']) return end @apps_interface.firewall_enable(app['id']) security_groups([args[0]]) rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 2451 def format_app_tiers(app) out = "" begin app_tiers = app['appTiers'] if app_tiers app_tier_names = app_tiers.collect { |app_tier| app_tier['tier']['name'] } out << app_tier_names.join(", ") end if out.empty? #out = "(Empty)" end rescue => ex Morpheus::Logging::DarkPrinter.puts "A formatting exception occured: #{ex}" if Morpheus::Logging.debug? end out end
Source
# File lib/morpheus/formatters.rb, line 324 def format_bytes(bytes, units="B", round=nil) out = "" if bytes if bytes < 1024 && units == "B" out = "#{bytes.to_i} B" else out = Filesize.from("#{bytes}#{units == 'auto' ? '' : " #{units}"}").pretty.strip out = out.split(' ')[0].to_f.round(round).to_s + ' ' + out.split(' ')[1] if round end end out end
Source
# File lib/morpheus/formatters.rb, line 339 def format_bytes_short(bytes) out = format_bytes(bytes) if out.include?(" ") val, units = out.split(" ") val = val.to_f # round to 0 or 1 decimal point if val % 1 == 0 val = val.round(0).to_s else val = val.round(1).to_s end # K instead of KiB units = units[0].chr out = "#{val}#{units}" end return out end
returns bytes in an abbreviated format eg. 3.1K instead of 3.10 KiB
Source
# File lib/morpheus/formatters.rb, line 412 def format_currency(amount, currency='USD', opts={}) # currency '' should probably error, like money gem does if currency.to_s.empty? currency = 'USD' end currency = currency.to_s.upcase amount = amount.to_f if amount == 0 return currency_sym(currency).to_s + "0" # elsif amount.to_f < 0.01 # # return exponent notation like 3.4e-09 # return currency_sym(currency).to_s + "#{amount}" else sigdig = opts[:sigdig] ? opts[:sigdig].to_i : 2 # max decimal digits min_sigdig = opts[:min_sigdig] ? opts[:min_sigdig].to_i : (sigdig || 2) # min decimal digits display_value = format_sig_dig(amount, sigdig, min_sigdig, opts[:pad_zeros]) display_value = format_number(display_value) # commas rtn = currency_sym(currency).to_s + display_value if amount.to_i < 0 rtn = "(#{rtn})" if opts[:minus_color] rtn = "#{opts[:minus_color]}#{rtn}#{opts[:return_color] || cyan}" end end rtn end end
returns currency amount formatted like “$4,5123.00”. 0.00 is formatted as “$0” this is not ideal
Also aliased as: format_money
Source
# File lib/morpheus/formatters.rb, line 78 def format_date(dt, options={}) format_dt(dt, {format: DEFAULT_DATE_FORMAT}.merge(options)) end
Source
# File lib/morpheus/formatters.rb, line 64 def format_dt(dt, options={}) dt = parse_time(dt) return "" if dt.nil? if options[:local] dt = dt.getlocal end format = options[:format] || DEFAULT_TIME_FORMAT return dt.strftime(format) end
Source
# File lib/morpheus/formatters.rb, line 86 def format_dt_as_param(dt) dt = dt.getutc format_dt(dt, {format: "%Y-%m-%d %X"}) end
Source
# File lib/morpheus/formatters.rb, line 91 def format_duration(start_time, end_time=nil, format="human") if !start_time return "" end start_time = parse_time(start_time) if end_time end_time = parse_time(end_time) else end_time = Time.now end seconds = (end_time - start_time).abs format_duration_seconds(seconds, format) end
Source
# File lib/morpheus/formatters.rb, line 105 def format_duration_ago(start_time, end_time=nil) if !start_time return "" end start_time = parse_time(start_time) if end_time end_time = parse_time(end_time) else end_time = Time.now end seconds = (end_time - start_time).abs format_human_duration(seconds, true) end
Source
# File lib/morpheus/formatters.rb, line 135 def format_duration_milliseconds(milliseconds, format="human", ms_threshold=1000) out = "" milliseconds = milliseconds.to_i.abs if ms_threshold && ms_threshold > milliseconds out = "#{milliseconds}ms" else out = format_duration_seconds((milliseconds.to_f / 1000).floor, format) end out end
Source
# File lib/morpheus/formatters.rb, line 119 def format_duration_seconds(seconds, format="human") seconds = seconds.abs out = "" # interval = Math.abs(interval) if format == "human" out = format_human_duration(seconds) elsif format interval_time = Time.mktime(0) + seconds out = interval_time.strftime(format) else interval_time = Time.mktime(0) + seconds out = interval_time.strftime("%H:%M:%S") end out end
Source
# File lib/morpheus/formatters.rb, line 148 def format_human_duration(seconds, show_relative=false) out = "" #seconds = seconds.round days, hours, minutes = (seconds / (60*60*24)).floor, (seconds / (60*60)).floor, (seconds / (60)).floor if days > 365 out << "#{days.floor} days" elsif days > 61 out << "#{days.floor} days" elsif days > 31 out << "#{days.floor} days" elsif days > 0 if days.floor == 1 out << "1 day" else out << "#{days.floor} days" end elsif hours > 1 if hours == 1 out << "1 hour" else out << "#{hours.floor} hours" end elsif minutes > 1 if minutes == 1 out << "1 minute" else out << "#{minutes.floor} minutes" end elsif seconds > 0 && seconds < 1 ms = (seconds.to_f * 1000).to_i out << "#{ms}ms" else if seconds.floor == 1 out << "1 second" else out << "#{seconds.floor} seconds" end end if show_relative if seconds < 1 out = "just now" else out << " ago" end end out end
returns a human readable time duration @param seconds - duration in seconds
Source
# File lib/morpheus/formatters.rb, line 447 def format_list(items, conjunction="", limit=nil) items = items ? items.clone : [] num_items = items.size if limit items = items.first(limit) end last_item = items.pop if items.empty? return "#{last_item}" else if limit && limit < num_items items << last_item last_item = "(#{num_items - items.size} more)" end return items.join(", ") + (conjunction.to_s.empty? ? ", " : " #{conjunction} ") + "#{last_item}" end end
def format_money
(amount, currency=‘usd’, opts={})
format_currency(amount, currency, opts)
end
Source
# File lib/morpheus/formatters.rb, line 82 def format_local_date(dt, options={}) format_dt(dt, {local: true, format: DEFAULT_DATE_FORMAT}.merge(options)) end
Source
# File lib/morpheus/formatters.rb, line 74 def format_local_dt(dt, options={}) format_dt(dt, {local: true}.merge(options)) end
Source
# File lib/morpheus/formatters.rb, line 481 def format_name_and_id(obj) if(obj.is_a?(Array)) return "" if obj.empty? # && hide_empty names, ids = obj.collect {|it| it['name'] rescue "" }, obj.collect {|it| it['id'] rescue "" } "#{names.join(", ")} [#{ids.join(",")}]" elsif(obj.is_a?(Hash)) "#{obj['name']} [#{obj['id']}]" rescue "" else obj.to_s end end
Source
# File lib/morpheus/formatters.rb, line 473 def format_name_values(obj) if obj.is_a?(Hash) obj.collect {|k,v| "#{k}: #{v}"}.join(", ") else "" end end
Source
# File lib/morpheus/formatters.rb, line 362 def format_number(n, opts={}) delim = opts[:delimiter] || ',' out = "" parts = n.to_s.split(".") whole_number = parts[0].to_s decimal = parts[1] ? parts[1..-1].join('.') : nil i = 0 whole_number.reverse.each_char do |c| if c == "-" out = "#{c}#{out}" else out = (i > 0 && i % 3 == 0) ? "#{c}#{delim}#{out}" : "#{c}#{out}" end i+= 1 end if decimal out << "." + decimal end return out end
Source
# File lib/morpheus/formatters.rb, line 497 def format_ok_status(status) color = cyan if ['ok'].include? status color = green elsif ['error'].include? status color = red elsif ['warning'].include? status color = yellow end "#{color}#{status.to_s.upcase}#{cyan}" end
Source
# File lib/morpheus/formatters.rb, line 383 def format_sig_dig(n, sigdig=3, min_sigdig=nil, pad_zeros=false) v = "" if sigdig && sigdig > 0 # v = n.to_i.round(sigdig).to_s v = sprintf("%.#{sigdig}f", n) else v = n.to_i.round().to_s end # if pad_zeros != true # v = v.to_f.to_s # end if min_sigdig v_parts = v.split(".") decimal_str = v_parts[1] if decimal_str == nil v = v + "." + ('0' * min_sigdig) elsif decimal_str.size < min_sigdig v = v + ('0' * (min_sigdig - decimal_str.size)) end end v end
Source
# File lib/morpheus/cli/commands/apps.rb, line 2468 def get_available_blueprints(refresh=false) if !@available_blueprints || refresh #results = @options_interface.options_for_source('appTemplates',{}) # still exists results = @options_interface.options_for_source('blueprints',{}) @available_blueprints = results['data'].collect {|it| {"id" => it["value"], "name" => it["name"], "value" => it["value"]} } default_option = {"id" => "existing", "name" => "Existing Instances", "value" => "existing", "type" => "morpheus"} @available_blueprints.unshift(default_option) end #puts "get_available_blueprints() rtn: #{@available_blueprints.inspect}" return @available_blueprints end
Source
# File lib/morpheus/formatters.rb, line 212 def get_object_value(data, key) value = nil if key.is_a?(Proc) return key.call(data) end key = key.to_s if key.include?(".") namespaces = key.split(".") value = data namespaces.each do |ns| if value.respond_to?("key?") if value.key?(ns.to_s) value = value[ns] elsif value.key?(ns.to_sym) value = value[ns.to_sym] else value = nil end else value = nil end end else # value = data.key?(key) ? data[key] : data[key.to_sym] if data.respond_to?("key?") if data.key?(key.to_s) value = data[key.to_s] elsif data.key?(key.to_sym) value = data[key.to_sym] end end end return value end
get_object_value
returns a value within a Hash
like object Usage: get_object_value
(host, “plan.name”)
Source
# File lib/morpheus/cli/commands/apps.rb, line 2523 def get_scoped_instance_config(instance_config, env_name, group_name, cloud_name) config = instance_config.clone if env_name.to_s != '' && config['environments'] && config['environments'][env_name] config = config['environments'][env_name].clone end if group_name.to_s != '' && config['groups'] && config['groups'][group_name] config = config['groups'][group_name].clone end if cloud_name.to_s != '' && config['clouds'] && config['clouds'][cloud_name] config = config['clouds'][cloud_name].clone end config.delete('environments') config.delete('groups') config.delete('clouds') # puts "get_scoped_instance_config(instance_config, #{env_name}, #{group_name}, #{cloud_name})" # puts "returned config: #{config}" return config end
lookup scoped instance config in a blueprint this only finds one right now
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1130 def get_task_type(args) params = {} options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[type]") build_common_options(opts, options, [:query, :json, :yaml, :csv, :fields, :dry_run, :remote]) opts.footer = "Get details about a task type.\n" + "[type] is required. This is the id or code or name of a task type." end optparse.parse!(args) if args.count != 1 raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}" end connect(options) begin @tasks_interface.setopts(options) if options[:dry_run] if args[0].to_s =~ /\A\d{1,}\Z/ print_dry_run @tasks_interface.dry.get_type(args[0].to_i) else print_dry_run @tasks_interface.dry.list_types({name:args[0]}) end return end # find_task_type_by_name actually finds by name or code id task_type = find_task_type_by_name(args[0]) return 1 if task_type.nil? json_response = {'taskType' => task_type} # skip redundant request # json_response = @tasks_interface.get(task_type['id']) render_result = render_with_format(json_response, options, 'taskType') return 0 if render_result task_type = json_response['taskType'] title = "Morpheus Task Type" print_h1 "Morpheus Task Type", [], options print cyan description_cols = { "ID" => 'id', "Name" => 'name', "Code" => 'name', #"Description" => 'description', "Scriptable" => lambda {|it| format_boolean(it['scriptable']) }, # lots more here # "enabled" => lambda {|it| format_boolean(it['enabled']) }, # "hasResults" => lambda {|it| format_boolean(it['hasResults']) }, # "allowRemoteKeyAuth" => lambda {|it| format_boolean(it['allowRemoteKeyAuth']) }, # "allowExecuteLocal" => lambda {|it| format_boolean(it['allowExecuteLocal']) }, # "allowExecuteRemote" => lambda {|it| format_boolean(it['allowExecuteRemote']) }, # "allowExecuteResource" => lambda {|it| format_boolean(it['allowExecuteResource']) }, # "allowLocalRepo" => lambda {|it| format_boolean(it['allowLocalRepo']) }, # "allowRemoteKeyAuth" => lambda {|it| format_boolean(it['allowRemoteKeyAuth']) }, } print_description_list(description_cols, task_type) option_types = task_type['optionTypes'] || [] option_types = option_types.sort {|x,y| x['displayOrder'] <=> y['displayOrder'] } if !option_types.empty? print_h2 "Config Option Types", [], options option_type_cols = { "Name" => lambda {|it| it['fieldContext'].to_s != '' ? "#{it['fieldContext']}.#{it['fieldName']}" : it['fieldName'] }, "Label" => lambda {|it| it['fieldLabel'] }, "Type" => lambda {|it| it['type'] }, } print cyan print as_pretty_table(option_types, option_type_cols) end print reset,"\n" return 0 rescue RestClient::Exception => e print_rest_exception(e, options) return 1 end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1945 def history(args) raw_args = args.dup options = {} #options[:show_output] = true optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app]") # opts.on( '-n', '--node NODE_ID', "Scope history to specific Container or VM" ) do |node_id| # options[:node_id] = node_id.to_i # end opts.on( nil, '--events', "Display sub processes (events)." ) do options[:show_events] = true end opts.on( nil, '--output', "Display process output." ) do options[:show_output] = true end opts.on(nil, '--details', "Display more details. Shows everything, untruncated." ) do options[:show_events] = true options[:show_output] = true options[:details] = true end build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote]) opts.footer = "List historical processes for a specific app.\n" + "[app] is required. This is the name or id of an app." end optparse.parse!(args) if args.count != 1 puts optparse return 1 end connect(options) begin app = find_app_by_name_or_id(args[0]) instance_ids = [] # API used to only return apps.appTiers # now returns detailed instance list as "instances" app_tiers = app['appTiers'] || [] instances = app['instances'] if instances.nil? instances = [] app_tiers.each do |app_tier| instances += (app_tier['appInstances'] || []).collect {|it| it['instance']}.flatten().compact end end instances.each do |instance| instance_ids << instance['id'] end # container_ids = instance['containers'] # if options[:node_id] && container_ids.include?(options[:node_id]) # container_ids = [options[:node_id]] # end params = {} params['instanceIds'] = instance_ids params.merge!(parse_list_options(options)) # params['query'] = params.delete('phrase') if params['phrase'] @processes_interface.setopts(options) if options[:dry_run] print_dry_run @processes_interface.dry.list(params) return end json_response = @processes_interface.list(params) if options[:json] puts as_json(json_response, options, "processes") return 0 elsif options[:yaml] puts as_yaml(json_response, options, "processes") return 0 elsif options[:csv] puts records_as_csv(json_response['processes'], options) return 0 else title = "App History: #{app['name']}" subtitles = [] if params[:query] subtitles << "Search: #{params[:query]}".strip end subtitles += parse_list_subtitles(options) print_h1 title, subtitles, options if json_response['processes'].empty? print "#{cyan}No process history found.#{reset}\n\n" else history_records = [] json_response["processes"].each do |process| row = { id: process['id'], eventId: nil, uniqueId: process['uniqueId'], name: process['displayName'], description: process['description'], processType: process['processType'] ? (process['processType']['name'] || process['processType']['code']) : process['processTypeName'], createdBy: process['createdBy'] ? (process['createdBy']['displayName'] || process['createdBy']['username']) : '', startDate: format_local_dt(process['startDate']), duration: format_process_duration(process), status: format_process_status(process), error: format_process_error(process), output: format_process_output(process) } history_records << row process_events = process['events'] || process['processEvents'] if options[:show_events] if process_events process_events.each do |process_event| event_row = { id: process['id'], eventId: process_event['id'], uniqueId: process_event['uniqueId'], name: process_event['displayName'], # blank like the UI description: process_event['description'], processType: process_event['processType'] ? (process_event['processType']['name'] || process_event['processType']['code']) : process['processTypeName'], createdBy: process_event['createdBy'] ? (process_event['createdBy']['displayName'] || process_event['createdBy']['username']) : '', startDate: format_local_dt(process_event['startDate']), duration: format_process_duration(process_event), status: format_process_status(process_event), error: format_process_error(process_event, options[:details] ? nil : 20), output: format_process_output(process_event, options[:details] ? nil : 20) } history_records << event_row end else end end end columns = [ {:id => {:display_name => "PROCESS ID"} }, :name, :description, {:processType => {:display_name => "PROCESS TYPE"} }, {:createdBy => {:display_name => "CREATED BY"} }, {:startDate => {:display_name => "START DATE"} }, {:duration => {:display_name => "ETA/DURATION"} }, :status, :error ] if options[:show_events] columns.insert(1, {:eventId => {:display_name => "EVENT ID"} }) end if options[:show_output] columns << :output end # custom pretty table columns ... if options[:include_fields] columns = options[:include_fields] end print cyan print as_pretty_table(history_records, columns, options) #print_results_pagination(json_response) print_results_pagination(json_response, {:label => "process", :n_label => "processes"}) print reset, "\n" return 0 end end rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/formatters.rb, line 206 def iso8601(dt) dt.instance_of(Time) ? dt.iso8601 : "#{dt}" end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1080 def list_task_types(args) params = {} options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage() build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote]) opts.footer = "List task types." end optparse.parse!(args) if args.count > 0 raise_command_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.join(' ')}\n#{optparse}" end connect(options) begin params.merge!(parse_list_options(options)) @tasks_interface.setopts(options) if options[:dry_run] print_dry_run @tasks_interface.dry.list_types(params) return end json_response = @tasks_interface.list_types(params) render_result = render_with_format(json_response, options, 'taskTypes') return 0 if render_result title = "Morpheus Task Types" subtitles = [] subtitles += parse_list_subtitles(options) print_h1 title, subtitles task_types = json_response['taskTypes'] if task_types.empty? print cyan,"No task types found.",reset,"\n" else print cyan rows = task_types.collect do |task_type| {name: task_type['name'], id: task_type['id'], code: task_type['code'], description: task_type['description']} end print as_pretty_table(rows, [:id, :name, :code], options) #print_results_pagination(json_response) print_results_pagination({size:task_types.size,total:task_types.size}) end print reset,"\n" return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1524 def logs(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app]") # opts.on('--hosts HOSTS', String, "Filter logs to specific Host ID(s)") do |val| # params['servers'] = val.to_s.split(",").collect {|it| it.to_s.strip }.select {|it| it }.compact # end # opts.on('--servers HOSTS', String, "alias for --hosts") do |val| # params['servers'] = val.to_s.split(",").collect {|it| it.to_s.strip }.select {|it| it }.compact # end # opts.on('--vms HOSTS', String, "alias for --hosts") do |val| # params['servers'] = val.to_s.split(",").collect {|it| it.to_s.strip }.select {|it| it }.compact # end # opts.on('--container CONTAINER', String, "Filter logs to specific Container ID(s)") do |val| # params['containers'] = val.to_s.split(",").collect {|it| it.to_s.strip }.select {|it| it }.compact # end opts.on( '-n', '--node NODE_ID', "Scope logs to specific Container or VM" ) do |node_id| options[:node_id] = node_id.to_i end # opts.on('--nodes HOST', String, "alias for --containers") do |val| # params['containers'] = val.to_s.split(",").collect {|it| it.to_s.strip }.select {|it| it }.compact # end opts.on('--start TIMESTAMP','--start TIMESTAMP', "Start timestamp. Default is 30 days ago.") do |val| options[:start] = parse_time(val) #.utc.iso8601 end opts.on('--end TIMESTAMP','--end TIMESTAMP', "End timestamp. Default is now.") do |val| options[:end] = parse_time(val) #.utc.iso8601 end # opts.on('--interval TIME','--interval TIME', "Interval of time to include, in seconds. Default is 30 days ago.") do |val| # options[:interval] = parse_time(val).utc.iso8601 # end opts.on('--level VALUE', String, "Log Level. DEBUG,INFO,WARN,ERROR") do |val| params['level'] = params['level'] ? [params['level'], val].flatten : [val] end opts.on('--table', '--table', "Format ouput as a table.") do options[:table] = true end opts.on('-a', '--all', "Display all details: entire message." ) do options[:details] = true end build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote]) opts.footer = "List logs for an app.\n" + "[app] is required. This is the name or id of an app." end optparse.parse!(args) if args.count !=1 print_error Morpheus::Terminal.angry_prompt puts_error "#{command_name} logs expects 1 argument and received #{args.count}: #{args}\n#{optparse}" return 1 end connect(options) begin app = find_app_by_name_or_id(args[0]) container_ids = [] # API used to only return apps.appTiers # now returns detailed instance list as 'instances' app_tiers = app['appTiers'] || [] instances = app['instances'] if instances.nil? instances = [] app_tiers.each do |app_tier| instances += (app_tier['appInstances'] || []).collect {|it| it['instance']}.flatten().compact end end instances.each do |instance| container_ids += instance['containers'] end if container_ids.empty? print cyan,"app is empty",reset,"\n" return 0 # print_error yellow,"app is empty",reset,"\n" # return 1 end if options[:node_id] if container_ids.include?(options[:node_id]) container_ids = [options[:node_id]] else print_red_alert "App does not include node #{options[:node_id]}" return 1 end end params = {} params['level'] = params['level'].collect {|it| it.to_s.upcase }.join('|') if params['level'] # api works with INFO|WARN params.merge!(parse_list_options(options)) params['query'] = params.delete('phrase') if params['phrase'] params['order'] = params['direction'] unless params['direction'].nil? # old api version expects order instead of direction params['startMs'] = (options[:start].to_i * 1000) if options[:start] params['endMs'] = (options[:end].to_i * 1000) if options[:end] params['interval'] = options[:interval].to_s if options[:interval] @logs_interface.setopts(options) if options[:dry_run] print_dry_run @logs_interface.dry.container_logs(container_ids, params) return end json_response = @logs_interface.container_logs(container_ids, params) render_result = json_response['logs'] ? render_with_format(json_response, options, 'logs') : render_with_format(json_response, options, 'data') return 0 if render_result title = "App Logs: #{app['name']}" subtitles = parse_list_subtitles(options) if options[:start] subtitles << "Start: #{options[:start]}".strip end if options[:end] subtitles << "End: #{options[:end]}".strip end if params[:query] subtitles << "Search: #{params[:query]}".strip end if params['servers'] subtitles << "Servers: #{params['servers']}".strip end if params['containers'] subtitles << "Containers: #{params['containers']}".strip end if params[:query] subtitles << "Search: #{params[:query]}".strip end if params['level'] subtitles << "Level: #{params['level']}" end logs = json_response['data'] || json_response['logs'] print_h1 title, subtitles, options if logs.empty? print "#{cyan}No logs found.#{reset}\n" else print format_log_records(logs, options) print_results_pagination({'meta'=>{'total'=>(json_response['total']['value'] rescue json_response['total']),'size'=>logs.size,'max'=>(json_response['max'] || options[:max]),'offset'=>(json_response['offset'] || options[:offset] || 0)}}) end print reset,"\n" return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/formatters.rb, line 357 def no_colors(str) str.to_s.gsub(/\e\[\d+m/, "") end
Source
# File lib/morpheus/formatters.rb, line 469 def ored_list(items, limit=nil) format_list(items, "or", limit) end
Source
# File lib/morpheus/formatters.rb, line 11 def parse_time(dt, format=nil) if dt.nil? || dt == '' || dt.to_i == 0 return nil elsif dt.is_a?(Time) return dt elsif dt.is_a?(String) result = nil err = nil if !result format ||= DEFAULT_TIME_FORMAT if format begin result = Time.strptime(dt, format) rescue => e err = e end end end if !result begin result = Time.strptime(dt, ALTERNATE_TIME_FORMAT) rescue => e # err = e end end if !result begin result = Time.strptime(dt, DEFAULT_DATE_FORMAT) rescue => e # err = e end end if !result begin result = Time.parse(dt) rescue => e err = e end end if result return result else raise "unable to parse time '#{dt}'. #{err}" end elsif dt.is_a?(Numeric) return Time.at(dt) else raise "bad argument type for parse_time() #{dt.class} #{dt.inspect}" end end
returns an instance of Time
Source
# File lib/morpheus/cli/commands/apps.rb, line 969 def prepare_apply(args) params, payload, options = {}, {}, {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app] [options]") build_standard_update_options(opts, options, [:auto_confirm]) opts.footer = <<-EOT Prepare to apply an app. [app] is required. This is the name or id of an app. Displays the current configuration data used by the apply command. This is only supported by certain types of apps such as terraform. EOT end optparse.parse!(args) if args.count != 1 raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(', ')}\n#{optparse}" end connect(options) begin app = find_app_by_name_or_id(args[0]) return 1 if app.nil? # construct request params.merge!(parse_query_options(options)) payload = {} if options[:payload] payload = options[:payload] payload.deep_merge!(parse_passed_options(options)) else payload.deep_merge!(parse_passed_options(options)) # raise_command_error "Specify at least one option to update.\n#{optparse}" if payload.empty? end @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.prepare_apply(app["id"], params) return end json_response = @apps_interface.prepare_apply(app["id"], params) render_result = render_with_format(json_response, options) return 0 if render_result # print_green_success "Prepared to apply app: #{app['name']}" print_h1 "Prepared App: #{app['name']}" app_config = json_response['data'] # app_config = json_response if app_config.nil? puts as_yaml(app_config, options) #return get([app['id']] + (options[:remote] ? ["-r",options[:remote]] : [])) print "\n", reset return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 2377 def print_apps_table(apps, options={}) table_color = options[:color] || cyan rows = apps.collect do |app| tiers_str = format_app_tiers(app) instances_str = (app['instanceCount'].to_i == 1) ? "1" : "#{app['instanceCount']}" containers_str = (app['containerCount'].to_i == 1) ? "1" : "#{app['containerCount']}" stats = app['stats'] # app_stats = app['appStats'] cpu_usage_str = !stats ? "" : generate_usage_bar((stats['cpuUsage'] || stats['cpuUsagePeak']).to_f, 100, {max_bars: 10}) memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10}) storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10}) if options[:details] if stats['maxMemory'] && stats['maxMemory'].to_i != 0 memory_usage_str = memory_usage_str + cyan + format_bytes_short(stats['usedMemory']).strip.rjust(8, ' ') + " / " + format_bytes_short(stats['maxMemory']).strip end if stats['maxStorage'] && stats['maxStorage'].to_i != 0 storage_usage_str = storage_usage_str + cyan + format_bytes_short(stats['usedStorage']).strip.rjust(8, ' ') + " / " + format_bytes_short(stats['maxStorage']).strip end end { id: app['id'], name: app['name'], labels: format_list(app['labels'], '', 3), description: app['description'], blueprint: app['blueprint'] ? app['blueprint']['name'] : '', type: app['type'] ? format_blueprint_type(app['type']) : (format_blueprint_type(app['blueprint'] ? app['blueprint']['type'] : nil)), group: app['group'] ? app['group']['name'] : app['siteId'], environment: app['appContext'], tiers: tiers_str, instances: instances_str, containers: containers_str, owner: app['owner'] ? app['owner']['username'] : '', tenant: app['account'] ? app['account']['name'] : nil, status: format_app_status(app, table_color), cpu: cpu_usage_str + cyan, memory: memory_usage_str + table_color, storage: storage_usage_str + table_color, created: format_local_dt(app['dateCreated']), updated: format_local_dt(app['lastUpdated']) } end columns = [ :id, :name, :labels, # :description, :type, :blueprint, :group, :environment, :status, :tiers, :instances, :containers, {:cpu => {:display_name => "MAX CPU"} }, :memory, :storage, :owner, #:tenant, :created, :updated ] # custom pretty table columns ... # if options[:include_fields] # columns = options[:include_fields] # end # print cyan print as_pretty_table(rows, columns, options) #{color: table_color} print reset end
def update_app_option_types(connected=true)
list = add_app_option_types(connected) list = list.reject {|it| ["blueprint", "group"].include? it['fieldName'] } list.each {|it| it['required'] = false } list
end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1278 def print_tasks_table(tasks, opts={}) columns = [ {"ID" => lambda {|it| it['id'] } }, {"NAME" => lambda {|it| it['name'] } }, {"TYPE" => lambda {|it| it['taskType']['name'] ? it['taskType']['name'] : it['type'] } }, {"LABELS" => lambda {|it| format_list(it['labels'], '', 3) rescue '' }}, {"VISIBILITY" => lambda {|it| it['visibility'] } }, {"CREATED" => lambda {|it| format_local_dt(it['dateCreated']) } } # {"UPDATED" => lambda {|it| format_local_dt(it['lastUpdated']) } }, ] if opts[:include_fields] columns = opts[:include_fields] end print as_pretty_table(tasks, columns, opts) end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1371 def process_special_task_option_typeaheads(option_types) # massage special task typeaheads options # this makes us all sad option_types.each do |option_type| if option_type['type'] == 'typeahead' if ['operationalWorkflowName','ifOperationalWorkflowName','elseOperationalWorkflowName','containerScript','containerTemplate'].include?(option_type['code']) option_type.deep_merge!({'config' => {'valueField' => 'name'}}) end elsif option_type['type'] == 'hidden' if ['operationalWorkflowId','ifOperationalWorkflowId','elseOperationalWorkflowId','containerScriptId','containerTemplateId'].include?(option_type['code']) option_type['processValue'] = lambda {|val| if val.to_s.empty? selected_option = Morpheus::Cli::OptionTypes.get_last_select() selected_option ? selected_option['value'] : nil end } end end end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 921 def refresh(args) params, payload, options = {}, {}, {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app] [options]") build_standard_update_options(opts, options, [:auto_confirm]) opts.footer = <<-EOT Refresh an app. [app] is required. This is the name or id of an app. This is only supported by certain types of apps. EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, count:1) connect(options) begin app = find_app_by_name_or_id(args[0]) return 1 if app.nil? # construct request params.merge!(parse_query_options(options)) payload = {} if options[:payload] payload = options[:payload] payload.deep_merge!(parse_passed_options(options)) else payload.deep_merge!(parse_passed_options(options)) # raise_command_error "Specify at least one option to update.\n#{optparse}" if payload.empty? end unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to refresh this app: #{app['name']}?") return 9, "aborted command" end @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.refresh(app["id"], params, payload) return end json_response = @apps_interface.refresh(app["id"], params, payload) render_response(json_response, options) do print_green_success "Refreshing app #{app['name']}" # return _get(app['id'], options) end return 0, nil rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1369 def remove(args) options = {} query_params = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app]") #JD: UI defaults to on, but perhaps better to be explicate for now. opts.on('--remove-instances [on|off]', ['on','off'], "Remove instances. Default is off.") do |val| query_params[:removeInstances] = val.nil? ? 'on' : val end opts.on('--preserve-volumes [on|off]', ['on','off'], "Preserve Volumes. Default is off. Applies to certain types only.") do |val| query_params[:preserveVolumes] = val.nil? ? 'on' : val end opts.on( '--keep-backups', '--keep-backups', "Preserve copy of backups" ) do query_params[:keepBackups] = 'on' end opts.on('--release-ips [on|off]', ['on','off'], "Release Floating IPs. Default is on. Applies to certain types only. Only applies when used with --remove-instances") do |val| query_params[:releaseFloatingIps] = val.nil? ? 'on' : val query_params[:releaseEIPs] = query_params[:releaseFloatingIps] # old parameter before 6.0 end opts.on('--releaseEIPs [on|off]', ['on','off'], "Alias for Release Floating IPs") do |val| query_params[:releaseFloatingIps] = val.nil? ? 'on' : val query_params[:releaseEIPs] = query_params[:releaseFloatingIps] # old parameter before 6.0 end opts.add_hidden_option('--releaseEIPs') opts.on( '-f', '--force', "Force Delete" ) do query_params[:force] = 'on' end build_common_options(opts, options, [:json, :dry_run, :quiet, :auto_confirm]) opts.footer = "Delete an app.\n" + "[app] is required. This is the name or id of an app." end optparse.parse!(args) if args.count != 1 print_error Morpheus::Terminal.angry_prompt puts_error "#{command_name} remove expects 1 argument and received #{args.count}: #{args}\n#{optparse}" return 1 end connect(options) begin app = find_app_by_name_or_id(args[0]) unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove the app '#{app['name']}'?", options) return 9 end # JD: removeVolumes to maintain the old behavior with pre-3.5.2 appliances, remove me later if query_params[:preserveVolumes].nil? query_params[:removeVolumes] = 'on' end @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.destroy(app['id'], query_params) return end json_response = @apps_interface.destroy(app['id'], query_params) if options[:json] print JSON.pretty_generate(json_response) print "\n" elsif !options[:quiet] print_green_success "Removed app #{app['name']}" #list([]) end rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1468 def remove_instance(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app] [instance]") build_common_options(opts, options, [:options, :json, :dry_run]) opts.footer = "Remove an instance from an app.\n" + "[app] is required. This is the name or id of an app." + "\n" + "[instance] is required. This is the name or id of an instance." end optparse.parse!(args) if args.count < 1 || args.count > 2 print_error Morpheus::Terminal.angry_prompt puts_error "#{command_name} remove-instance expects 1-2 arguments and received #{args.count}: #{args}\n#{optparse}" return 1 end # optional [tier] and [instance] arguments if args[1] && args[1] !~ /\A\-/ options[:instance_name] = args[1] end connect(options) begin app = find_app_by_name_or_id(args[0]) payload = {} if options[:instance_name] instance = find_instance_by_name_or_id(options[:instance_name]) else v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'instance', 'fieldLabel' => 'Instance', 'type' => 'text', 'required' => true, 'description' => 'Enter the instance name or id'}], options[:options]) instance = find_instance_by_name_or_id(v_prompt['instance']) end payload[:instanceId] = instance['id'] @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.remove_instance(app['id'], payload) return end json_response = @apps_interface.remove_instance(app['id'], payload) if options[:json] print JSON.pretty_generate(json_response) print "\n" else print_green_success "Removed instance #{instance['name']} from app #{app['name']}" #list([]) # details_options = [app['name']] # details(details_options) end rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1751 def restart(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app]") build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote]) opts.footer = "Restart an app.\n" + "[app] is required. This is the name or id of an app. Supports 1-N [app] arguments." end optparse.parse!(args) if args.count < 1 puts_error "[id] argument is required" puts_error optparse return 1 end connect(options) id_list = parse_id_list(args) unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to restart #{id_list.size == 1 ? 'app' : 'apps'} #{anded_list(id_list)}?", options) return 9, "aborted command" end return run_command_for_each_arg(id_list) do |arg| _restart(arg, options) end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1853 def security_groups(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app]") build_common_options(opts, options, [:json, :dry_run]) end optparse.parse!(args) if args.count != 1 print_error Morpheus::Terminal.angry_prompt puts_error "#{command_name} security-groups expects 1 argument and received #{args.count}: #{args}\n#{optparse}" return 1 end connect(options) begin app = find_app_by_name_or_id(args[0]) @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.security_groups(app['id']) return end json_response = @apps_interface.security_groups(app['id']) securityGroups = json_response['securityGroups'] print_h1 "Morpheus Security Groups for App: #{app['name']}", options print cyan print_description_list({"Firewall Enabled" => lambda {|it| format_boolean it['firewallEnabled'] } }, json_response) if securityGroups.empty? print cyan,"\n","No security groups currently applied.",reset,"\n" else print "\n" securityGroups.each do |securityGroup| print cyan, "= #{securityGroup['id']} (#{securityGroup['name']}) - (#{securityGroup['description']})\n" end end print reset,"\n" rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1707 def start(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app]") build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote]) opts.footer = "Start an app.\n" + "[app] is required. This is the name or id of an app. Supports 1-N [app] arguments." end optparse.parse!(args) if args.count < 1 puts_error "[id] argument is required" puts_error optparse return 1 end connect(options) id_list = parse_id_list(args) unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to start #{id_list.size == 1 ? 'app' : 'apps'} #{anded_list(id_list)}?", options) return 9, "aborted command" end return run_command_for_each_arg(id_list) do |arg| _start(arg, options) end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1174 def state(args) params, payload, options = {}, {}, {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app] [options]") opts.on('--data', "Display State Data") do options[:include_state_data] = true end opts.on('--specs', "Display Spec Templates") do options[:include_spec_templates] = true end opts.on('--plan', "Display Plan Data") do options[:include_plan_data] = true end opts.on('--input', "Display Input") do options[:include_input] = true end opts.on('--output', "Display Output") do options[:include_output] = true end opts.on('-a','--all', "Display All Details") do options[:include_state_data] = true options[:include_spec_templates] = true options[:include_plan_data] = true options[:include_input] = true options[:include_output] = true options[:details] = true end build_standard_get_options(opts, options) opts.footer = <<-EOT View state of an app. [app] is required. This is the name or id of an app. This is only supported by certain types of apps such as terraform. EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, count:1) connect(options) app = find_app_by_name_or_id(args[0]) return 1 if app.nil? # construct request params.merge!(parse_query_options(options)) @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.state(app["id"], params) return end json_response = @apps_interface.state(app["id"], params) render_result = render_with_format(json_response, options) return 0 if render_result print_h1 "App State: #{app['name']}", options # print_h2 "Workloads", options if json_response['workloads'] && !json_response['workloads'].empty? workload_columns = { "Name" => lambda {|it| it['subRefName'].to_s.empty? ? "#{it['refName']}" : "#{it['refName']} - #{it['subRefName']}" }, "Last Check" => lambda {|it| format_local_dt(it['stateDate']) }, "Status" => lambda {|it| format_ok_status(it['status'] || 'ok') }, "Drift Status" => lambda {|it| it['iacDrift'] ? "Drift" : "No Drift" } } print as_pretty_table(json_response['workloads'], workload_columns.upcase_keys!, options) else print cyan,"No workloads found.",reset,"\n" end if options[:include_state_data] print_h2 "State Data", options puts json_response['stateData'] end if options[:include_spec_templates] print_h2 "Spec Templates", options spec_templates_columns = { "Resource Spec" => lambda {|it| it['name'] || (it['template'] ? it['template']['name'] : nil) }, "Attached to Source Template" => lambda {|it| format_boolean(!it['isolated']) }, "Source Spec Template" => lambda {|it| (it['template'] ? it['template']['name'] : nil) || it['name'] } } print as_pretty_table(json_response['specs'], spec_templates_columns.upcase_keys!, options) # print "\n", reset end if options[:include_plan_data] # print_h2 "Plan Data", options if app['type'] == 'terraform' print_h2 "Terraform Plan", options else print_h2 "Plan Data", options end puts json_response['planData'] # print "\n", reset end if options[:include_input] # print_h2 "Input", options if json_response['input'] && json_response['input']['variables'] print_h2 "VARIABLES", options input_variable_columns = { "Name" => lambda {|it| it['name'] }, "Value" => lambda {|it| it['value'] } } print as_pretty_table(json_response['input']['variables'], input_variable_columns.upcase_keys!, options) end if json_response['input'] && json_response['input']['providers'] print_h2 "PROVIDERS", options input_provider_columns = { "Name" => lambda {|it| it['name'] } } print as_pretty_table(json_response['input']['providers'], input_provider_columns.upcase_keys!, options) end if json_response['input'] && json_response['input']['data'] print_h2 "DATA", options input_data_columns = { "Type" => lambda {|it| it['type'] }, "Key" => lambda {|it| it['key'] }, "Name" => lambda {|it| it['name'] } } print as_pretty_table(json_response['input']['data'], input_data_columns.upcase_keys!, options) end # print "\n", reset end if options[:include_output] # print_h2 "Output", options if json_response['output'] && json_response['output']['outputs'] print_h2 "OUTPUTS", options input_variable_columns = { "Name" => lambda {|it| it['name'] }, "Value" => lambda {|it| it['value'] } } print as_pretty_table(json_response['output']['outputs'], input_variable_columns.upcase_keys!, options) end # print "\n", reset end print "\n", reset return 0 end
Source
# File lib/morpheus/cli/commands/apps.rb, line 1663 def stop(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app]") build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote]) opts.footer = "Stop an app.\n" + "[app] is required. This is the name or id of an app. Supports 1-N [app] arguments." end optparse.parse!(args) if args.count < 1 puts_error "[id] argument is required" puts_error optparse return 1 end connect(options) id_list = parse_id_list(args) unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to stop #{id_list.size == 1 ? 'app' : 'apps'} #{anded_list(id_list)}?", options) return 9, "aborted command" end return run_command_for_each_arg(id_list) do |arg| _stop(arg, options) end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 823 def update(args) params, payload, options = {}, {}, {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app] [options]") #build_option_type_options(opts, options, update_app_option_types(false)) opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val| options[:group] = val end opts.on( '--name VALUE', String, "Name" ) do |val| options[:name] = val end opts.on('-l', '--labels [LIST]', String, "Labels") do |val| options[:options]['labels'] = parse_labels(val) end opts.on( '--description VALUE', String, "Description" ) do |val| options[:description] = val end opts.on( '--environment VALUE', String, "Environment" ) do |val| options[:environment] = val end opts.on( '--owner USER', "Owner Username or ID" ) do |val| options[:owner] = val == 'null' ? nil : val end build_common_options(opts, options, [:options, :payload, :json, :dry_run]) opts.footer = "Update an app.\n" + "[app] is required. This is the name or id of an app." end optparse.parse!(args) if args.count != 1 print_error Morpheus::Terminal.angry_prompt puts_error "#{command_name} update expects 1 argument and received #{args.count}: #{args}\n#{optparse}" return 1 end connect(options) begin app = find_app_by_name_or_id(args[0]) return 1 if app.nil? if options[:payload] payload = options[:payload] end payload['app'] ||= {} payload.deep_merge!({'app' => parse_passed_options(options)}) if options[:name] payload['app']['name'] = options[:name] end if options[:description] payload['app']['description'] = options[:description] end if options[:environment] # payload['app']['environment'] = options[:environment] payload['app']['appContext'] = options[:environment] end if options[:group] group = find_group_by_name_or_id_for_provisioning(options[:group]) return 1 if group.nil? payload['app']['group'] = {'id' => group['id'], 'name' => group['name']} end if options.key?(:owner) owner_id = options[:owner] if owner_id.to_s.empty? # allow clearing owner_id = nil elsif options[:owner] if owner_id.to_s =~ /\A\d{1,}\Z/ # allow id without lookup else user = find_available_user_option(owner_id) return 1 if user.nil? owner_id = user['id'] end end payload['app']['ownerId'] = owner_id end if payload['app'] && payload['app'].empty? payload.delete('app') end if payload.empty? raise_command_error "Specify at least one option to update.\n#{optparse}" if payload.empty? end @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.update(app["id"], payload) return end json_response = @apps_interface.update(app["id"], payload) render_result = render_with_format(json_response, options) return 0 if render_result print_green_success "Updated app #{app['name']}" get([app['id']] + (options[:remote] ? ["-r",options[:remote]] : [])) return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/cli/commands/tasks.rb, line 1272 def update_task_option_types(task_type) [ {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 0} ] + task_type['optionTypes'] end
Source
# File lib/morpheus/cli/commands/apps.rb, line 2261 def update_wiki(args) options = {} params = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app] [options]") build_option_type_options(opts, options, update_wiki_page_option_types) opts.on('--file FILE', "File containing the wiki content. This can be used instead of --content") do |filename| full_filename = File.expand_path(filename) if File.exist?(full_filename) params['content'] = File.read(full_filename) else print_red_alert "File not found: #{full_filename}" return 1 end # use the filename as the name by default. if !params['name'] params['name'] = File.basename(full_filename) end end opts.on(nil, '--clear', "Clear current page content") do |val| params['content'] = "" end build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote]) end optparse.parse!(args) if args.count != 1 puts_error "#{Morpheus::Terminal.angry_prompt}wrong number of arguments. Expected 1 and received #{args.count} #{args.inspect}\n#{optparse}" return 1 end connect(options) begin app = find_app_by_name_or_id(args[0]) return 1 if app.nil? # construct payload passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {} payload = nil if options[:payload] payload = options[:payload] payload.deep_merge!({'page' => passed_options}) unless passed_options.empty? else payload = { 'page' => { } } # allow arbitrary -O options payload.deep_merge!({'page' => passed_options}) unless passed_options.empty? # prompt for options #params = Morpheus::Cli::OptionTypes.prompt(update_wiki_page_option_types, options[:options], @api_client, options[:params]) #params = passed_options params.deep_merge!(passed_options) if params.empty? raise_command_error "Specify at least one option to update.\n#{optparse}" end payload.deep_merge!({'page' => params}) unless params.empty? end @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.update_wiki(app["id"], payload) return end json_response = @apps_interface.update_wiki(app["id"], payload) if options[:json] puts as_json(json_response, options) else print_green_success "Updated wiki page for app #{app['name']}" wiki([app['id']]) end return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 2542 def update_wiki_page_option_types [ {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => false, 'displayOrder' => 1, 'description' => 'The name of the wiki page for this instance. Default is the instance name.'}, #{'fieldName' => 'category', 'fieldLabel' => 'Category', 'type' => 'text', 'required' => false, 'displayOrder' => 2}, {'fieldName' => 'content', 'fieldLabel' => 'Content', 'type' => 'textarea', 'required' => false, 'displayOrder' => 3, 'description' => 'The content (markdown) of the wiki page.'} ] end
Source
# File lib/morpheus/cli/commands/apps.rb, line 2106 def view(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app]") opts.on('-w','--wiki', "Open the wiki tab for this app") do options[:link_tab] = "wiki" end opts.on('--tab VALUE', String, "Open a specific tab") do |val| options[:link_tab] = val.to_s end build_common_options(opts, options, [:dry_run, :remote]) opts.footer = "View an app in a web browser" + "\n" + "[app] is required. This is the name or id of an app. Supports 1-N [app] arguments." end optparse.parse!(args) if args.count < 1 raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}" end connect(options) id_list = parse_id_list(args) return run_command_for_each_arg(id_list) do |arg| _view(arg, options) end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 2230 def view_wiki(args) params = {} options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id]") build_common_options(opts, options, [:dry_run, :remote]) opts.footer = "View app wiki page in a web browser" + "\n" + "[app] is required. This is the name or id of an app." end optparse.parse!(args) if args.count != 1 raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}" end connect(options) begin app = find_app_by_name_or_id(args[0]) return 1 if app.nil? link = "#{@appliance_url}/login/oauth-redirect?access_token=#{@access_token}\\&redirectUri=/provisioning/apps/#{app['id']}#!wiki" if options[:dry_run] puts Morpheus::Util.open_url_command(link) return 0 end return Morpheus::Util.open_url(link) rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Source
# File lib/morpheus/cli/commands/apps.rb, line 2152 def wiki(args) options = {} params = {} open_wiki_link = false optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app]") opts.on('--view', '--view', "View wiki page in web browser.") do open_wiki_link = true end build_common_options(opts, options, [:json, :dry_run, :remote]) opts.footer = "View wiki page details for an app." + "\n" + "[app] is required. This is the name or id of an app." end optparse.parse!(args) if args.count != 1 puts_error "#{Morpheus::Terminal.angry_prompt}wrong number of arguments. Expected 1 and received #{args.count} #{args.inspect}\n#{optparse}" return 1 end connect(options) begin app = find_app_by_name_or_id(args[0]) return 1 if app.nil? @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.wiki(app["id"], params) return end json_response = @apps_interface.wiki(app["id"], params) page = json_response['page'] render_result = render_with_format(json_response, options, 'page') return 0 if render_result if page # my_terminal.exec("wiki get #{page['id']}") print_h1 "App Wiki Page: #{app['name']}" # print_h1 "Wiki Page Details" print cyan print_description_list({ "Page ID" => 'id', "Name" => 'name', #"Category" => 'category', #"Ref Type" => 'refType', #"Ref ID" => 'refId', #"Owner" => lambda {|it| it['account'] ? it['account']['name'] : '' }, "Created" => lambda {|it| format_local_dt(it['dateCreated']) }, "Created By" => lambda {|it| it['createdBy'] ? it['createdBy']['username'] : '' }, "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }, "Updated By" => lambda {|it| it['updatedBy'] ? it['updatedBy']['username'] : '' } }, page) print reset,"\n" print_h2 "Page Content" print cyan, page['content'], reset, "\n" else print "\n" print cyan, "No wiki page found.", reset, "\n" end print reset,"\n" if open_wiki_link return view_wiki([args[0]]) end return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end