class Morpheus::Cli::Apps
Public Class Methods
new()
click to toggle source
# File lib/morpheus/cli/commands/apps.rb, line 26 def initialize() # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance end
Public Instance Methods
_get(id, options={})
click to toggle source
# File lib/morpheus/cli/commands/apps.rb, line 670 def _get(id, options={}) app = nil if id.to_s !~ /\A\d{1,}\Z/ app = find_app_by_name_or_id(id) id = app['id'] end @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.get(id) return end json_response = @apps_interface.get(id.to_i) render_response(json_response, options, 'app') do app = json_response['app'] # API used to only return apps.appTiers including instances with lots of detail # now returns simplified instance list as "instances" for terraform, etc with only id,name # so load the instance details if needed app_tiers = [] instances = [] if app['appTiers'] && !app['appTiers'].empty? # appTiers contains instances with lots of detail app_tiers = app['appTiers'] app_tiers.each do |app_tier| instances += (app_tier['appInstances'] || []).collect {|it| it['instance']}.flatten().compact end elsif app['instances'] && !app['instances'].empty? # need to load instance details which are not returned in this simple list instance_ids = app['instances'].collect {|it| it['id'] } instances = @instances_interface.list({id: instance_ids})['instances'] end print_h1 "App Details", [], options print cyan description_cols = { "ID" => 'id', "Name" => 'name', "Labels" => lambda {|it| format_list(it['labels']) rescue '' }, "Description" => 'description', "Type" => lambda {|it| if it['type'] format_blueprint_type(it['type']) else format_blueprint_type(it['blueprint'] ? it['blueprint']['type'] : nil) end }, "Blueprint" => lambda {|it| it['blueprint'] ? it['blueprint']['name'] : '' }, "Group" => lambda {|it| it['group'] ? it['group']['name'] : it['siteId'] }, "Environment" => lambda {|it| it['appContext'] }, "Owner" => lambda {|it| it['owner'] ? it['owner']['username'] : '' }, #"Tenant" => lambda {|it| it['account'] ? it['account']['name'] : '' }, "Tiers" => lambda {|it| # it['instanceCount'] tiers = [] app_tiers.each do |app_tier| tiers << app_tier['tier'] end "(#{(tiers || []).size()}) #{tiers.collect {|it| it.is_a?(Hash) ? it['name'] : it }.join(',')}" }, "Instances" => lambda {|it| # it['instanceCount'] "(#{instances.count}) #{instances.collect {|it| it['name'] }.join(',')}" }, "Containers" => lambda {|it| #it['containerCount'] containers = [] instances.each do |instance| containers += (instance['containers'] || []) end #"(#{containers.count})" "(#{containers.count}) #{containers.collect {|it| it }.join(',')}" }, "Status" => lambda {|it| format_app_status(it) } } description_cols["Removal Date"] = lambda {|it| format_local_dt(it['removalDate'])} if app['status'] == 'pendingRemoval' # if app['blueprint'].nil? # description_cols.delete("Blueprint") # end # if app['description'].nil? # description_cols.delete("Description") # end print_description_list(description_cols, app) stats = app['stats'] if app['instanceCount'].to_i > 0 print_h2 "App Usage", options print_stats_usage(stats, {include: [:memory, :storage]}) end if app_tiers.empty? print reset,"\n" if instances.empty? print cyan, "This app is empty", reset, "\n\n" else print_h2 "Instances", options instances_rows = instances.collect do |instance| connection_string = '' if !instance['connectionInfo'].nil? && instance['connectionInfo'].empty? == false connection_string = "#{instance['connectionInfo'][0]['ip']}:#{instance['connectionInfo'][0]['port']}" end {id: instance['id'], name: instance['name'], connection: connection_string, environment: instance['instanceContext'], nodes: (instance['containers'] || []).count, status: format_instance_status(instance), type: instance['instanceType']['name'], group: !instance['group'].nil? ? instance['group']['name'] : nil, cloud: !instance['cloud'].nil? ? instance['cloud']['name'] : nil} end instances_rows = instances_rows.sort {|x,y| x[:id] <=> y[:id] } #oldest to newest.. print cyan print as_pretty_table(instances_rows, [:id, :name, :cloud, :type, :environment, :nodes, :connection, :status], {border_style: options[:border_style]}) print reset print "\n" end else app_tiers.each do |app_tier| # print_h2 "Tier: #{app_tier['tier']['name']}", options print_h2 "#{app_tier['tier']['name']}", options print cyan tier_instances = (app_tier['appInstances'] || []).collect {|it| it['instance']} instance_list = tier_instances.collect { |tier_instance| instances.find { |i| i['id'] == tier_instance['id'] } } if instance_list.empty? puts yellow, "This tier is empty", reset else instances_rows = instance_list.collect do |instance| connection_string = '' if !instance['connectionInfo'].nil? && instance['connectionInfo'].empty? == false connection_string = "#{instance['connectionInfo'][0]['ip']}:#{instance['connectionInfo'][0]['port']}" end {id: instance['id'], name: instance['displayName'] ? instance['displayName'] : instance['name'], connection: connection_string, environment: instance['instanceContext'], nodes: (instance['containers'] || []).count, status: format_instance_status(instance), type: instance['instanceType']['name'], group: !instance['group'].nil? ? instance['group']['name'] : nil, cloud: !instance['cloud'].nil? ? instance['cloud']['name'] : nil} end instances_rows = instances_rows.sort {|x,y| x[:id] <=> y[:id] } #oldest to newest.. print cyan print as_pretty_table(instances_rows, [:id, :name, :cloud, :type, :environment, :nodes, :connection, :status], {border_style: options[:border_style]}) print reset print "\n" end end end print cyan # refresh until a status is reached if options[:refresh_until_status] if options[:refresh_interval].nil? || options[:refresh_interval].to_f < 0 options[:refresh_interval] = default_refresh_interval end statuses = options[:refresh_until_status].to_s.downcase.split(",").collect {|s| s.strip }.select {|s| !s.to_s.empty? } if !statuses.include?(app['status']) print cyan, "Refreshing in #{options[:refresh_interval] > 1 ? options[:refresh_interval].to_i : options[:refresh_interval]} seconds" sleep_with_dots(options[:refresh_interval]) print "\n" _get(app['id'], options) end end end
add(args)
click to toggle source
# File lib/morpheus/cli/commands/apps.rb, line 211 def add(args) options = {} params = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[name] [options]") #build_option_type_options(opts, options, add_app_option_types(false)) # these come from build_options_types opts.on( '-b', '--blueprint BLUEPRINT', "Blueprint Name or ID. The default value is 'existing' which means no blueprint, for creating a blank app and adding existing instances." ) do |val| options[:blueprint] = val end opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val| options[:group] = val end opts.on( '-c', '--cloud CLOUD', "Default Cloud Name or ID." ) do |val| options[:cloud] = 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( '-e', '--environment VALUE', "Environment Name" ) do |val| options[:environment] = val.to_s == 'null' ? nil : val end # config is being deprecated in favor of the standard --payload options # opts.add_hidden_option(['config', 'config-dir', 'config-file', 'config-yaml']) opts.on('--validate','--validate', "Validate Only. Validates the configuration and skips creating it.") do options[:validate_only] = true end opts.on('--refresh [SECONDS]', String, "Refresh until status is running,failed. Default interval is #{default_refresh_interval} seconds.") do |val| options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f end build_common_options(opts, options, [:options, :payload, :json, :yaml, :dry_run, :quiet]) opts.footer = "Create a new app.\n" + "[name] is required. This is the name of the new app. It may also be passed as --name or inside your config." end optparse.parse!(args) if args.count > 1 print_error Morpheus::Terminal.angry_prompt puts_error "#{command_name} add expects 0-1 arguments and received #{args.count}: #{args}\n#{optparse}" return 1 end # allow name as first argument if args[0] # && !options[:name] options[:name] = args[0] end connect(options) begin options[:options] ||= {} passed_options = (options[:options] || {}).reject {|k,v| k.is_a?(Symbol) } payload = {} if options[:payload] # payload is from parsed json|yaml files or arguments. payload = options[:payload] # merge -O options payload.deep_merge!(passed_options) unless passed_options.empty? # support some options on top of --payload [:name, :description, :environment].each do |k| if options.key?(k) payload[k.to_s] = options[k] end end else # prompt for payload payload = {} # merge -O options payload.deep_merge!(passed_options) unless passed_options.empty? # this could have some special -O context, like -O tier.Web.0.instance.name # tier_config_options = payload.delete('tier') # Blueprint blueprint_id = 'existing' blueprint = nil if options[:blueprint] blueprint_id = options[:blueprint] options[:options]['blueprint'] = options[:blueprint] end v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'blueprint', 'fieldLabel' => 'Blueprint', 'type' => 'select', 'selectOptions' => get_available_blueprints(), 'required' => true, 'defaultValue' => 'existing', 'description' => "The blueprint to use. The default value is 'existing' which means no template, for creating a blank app and adding existing instances."}], options[:options]) blueprint_id = v_prompt['blueprint'] if blueprint_id.to_s.empty? || blueprint_id == 'existing' blueprint = {"id" => "existing", "name" => "Existing Instances", "value" => "existing", "type" => "morpheus"} else blueprint = find_blueprint_by_name_or_id(blueprint_id) if blueprint.nil? #print_red_alert "Blueprint not found by name or id '#{blueprint_id}'" return 1 end end payload['templateId'] = blueprint['id'] # for pre-3.6 api payload['blueprintId'] = blueprint['id'] payload['blueprintName'] = blueprint['name'] #for future api plz # Name options[:options]['name'] = options[:name] if options.key?(:name) v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Enter a name for this app'}], options[:options]) payload['name'] = v_prompt['name'] # Description options[:options]['description'] = options[:description] if options.key?(:description) v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false}], options[:options]) payload['description'] = v_prompt['description'] # Group group_id = nil options[:options]['group'] = options[:group] if options.key?(:group) v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'group', 'fieldLabel' => 'Group', 'type' => 'select', 'selectOptions' => get_available_groups(), 'required' => true, 'defaultValue' => @active_group_id}], options[:options]) group_id = v_prompt['group'] group = find_group_by_name_or_id_for_provisioning(group_id) return 1 if group.nil? payload['group'] = {'id' => group['id'], 'name' => group['name']} # Default Cloud cloud_id = nil cloud = nil scoped_available_clouds = get_available_clouds(group['id']) if options[:cloud] cloud_id = options[:cloud] else v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'fieldLabel' => 'Default Cloud', 'type' => 'select', 'selectOptions' => scoped_available_clouds}], options[:options]) cloud_id = v_prompt['cloud'] unless v_prompt['cloud'].to_s.empty? end if cloud_id cloud = find_cloud_by_name_or_id_for_provisioning(group['id'], cloud_id) payload['defaultCloud'] = {'id' => cloud ? cloud['id'] : cloud_id} end # Environment selected_environment = nil available_environments = get_available_environments() if options[:environment] payload['environment'] = options[:environment] else v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'environment', 'fieldLabel' => 'Environment', 'type' => 'select', 'selectOptions' => available_environments}], options[:options], @api_client) payload['environment'] = v_prompt['environment'] unless v_prompt['environment'].to_s.empty? end selected_environment = nil if payload['environment'] selected_environment = available_environments.find {|it| it['code'] == payload['environment'] || it['name'] == payload['environment'] } if selected_environment.nil? print_red_alert "Environment not found by name or code '#{payload['environment']}'" return 1 end end # payload['appContext'] = payload['environment'] if payload['environment'] # Labels v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text'}], options[:options]) payload['labels'] = parse_labels(v_prompt['labels']) unless v_prompt['labels'].to_s.empty? # Configure (Tiers and their instances) if !payload['tiers'] if payload['blueprintId'] != 'existing' # fetch the app template blueprint = find_blueprint_by_name_or_id(payload['blueprintId']) return 1 if blueprint.nil? unless options[:quiet] print cyan, "Configuring app with blueprint id: #{blueprint['id']}, name: #{blueprint['name']}, type: #{blueprint['type']}\n" end blueprint_type = blueprint['type'] || 'morpheus' if blueprint_type == 'morpheus' # configure each tier and instance in the blueprint # tiers are a map, heh, sort them by tierIndex tiers = blueprint["config"]["tiers"] ? blueprint["config"]["tiers"] : (blueprint["tiers"] || {}) sorted_tiers = tiers.collect {|k,v| [k,v] }.sort {|a,b| a[1]['tierIndex'] <=> b[1]['tierIndex'] } payload.delete('defaultCloud') sorted_tiers.each do |tier_obj| tier_name = tier_obj[0] tier_config = tier_obj[1] payload['tiers'] ||= {} payload['tiers'][tier_name] ||= tier_config.clone # remove instances, they will be iterated over and merged back in tier_instances = payload['tiers'][tier_name].delete("instances") # remove other blank stuff if payload['tiers'][tier_name]['linkedTiers'] && payload['tiers'][tier_name]['linkedTiers'].empty? payload['tiers'][tier_name].delete('linkedTiers') end # remove extra instance options at tierName.index, probabl need a namespace here like tier.TierName.index tier_extra_options = {} if payload[tier_name] tier_extra_options = payload.delete(tier_name) end tier_instance_types = tier_instances ? tier_instances.collect {|it| (it['instance'] && it['instance']['type']) ? it['instance']['type'].to_s : 'unknown'}.compact : [] unless options[:quiet] # print cyan, "Configuring Tier: #{tier_name} (#{tier_instance_types.empty? ? 'empty' : tier_instance_types.join(', ')})", "\n" print cyan, "Configuring tier #{tier_name}", reset, "\n" end # todo: also prompt for tier settings here, like linkedTiers: [] if tier_instances tier_instances = tier_config['instances'] || [] tier_instances.each_with_index do |instance_config, instance_index| instance_type_code = instance_config['type'] if instance_config['instance'] && instance_config['instance']['type'] instance_type_code = instance_config['instance']['type'] end if instance_type_code.nil? print_red_alert "Unable to determine instance type for tier: #{tier_name} index: #{instance_index}" return 1 else unless options[:quiet] print cyan, "Configuring #{instance_type_code} instance #{tier_name}.#{instance_index}", reset, "\n" end # Cloud # cloud_id = nil # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'fieldLabel' => 'Cloud', 'type' => 'select', 'selectOptions' => scoped_available_clouds, 'defaultValue' => cloud ? cloud['name'] : nil}], options[:options]) # cloud_id = v_prompt['cloud'] unless v_prompt['cloud'].to_s.empty? # if cloud_id # # cloud = find_cloud_by_name_or_id_for_provisioning(group['id'], cloud_id) # cloud = scoped_available_clouds.find {|it| it['name'] == cloud_id.to_s } || scoped_available_clouds.find {|it| it['id'].to_s == cloud_id.to_s } # return 1 if cloud.nil? # else # # prompt still happens inside get_scoped_instance_config # end # prompt for the cloud for this instance # the cloud is part of finding the scoped config in the blueprint scoped_instance_config = get_scoped_instance_config(instance_config.clone, selected_environment ? selected_environment['name'] : nil, group ? group['name'] : nil, cloud ? cloud['name'] : nil) # now configure an instance like normal, use the config as default options with :always_prompt instance_prompt_options = {} instance_prompt_options[:group] = group ? group['id'] : nil #instance_prompt_options[:cloud] = cloud ? cloud['name'] : nil instance_prompt_options[:default_cloud] = cloud ? cloud['name'] : nil instance_prompt_options[:environment] = selected_environment ? selected_environment['code'] : nil instance_prompt_options[:default_security_groups] = scoped_instance_config['securityGroups'] ? scoped_instance_config['securityGroups'] : nil instance_prompt_options[:no_prompt] = options[:no_prompt] #instance_prompt_options[:always_prompt] = options[:no_prompt] != true # options[:always_prompt] instance_prompt_options[:options] = scoped_instance_config # meh, actually need to make these default values instead.. #instance_prompt_options[:options][:always_prompt] = instance_prompt_options[:no_prompt] != true instance_prompt_options[:options][:no_prompt] = instance_prompt_options[:no_prompt] # also allow arbritrary options passed as tierName.instanceIndex like Web.0.instance.layout.id=75 instance_extra_options = {} if tier_extra_options && tier_extra_options[instance_index.to_s] instance_extra_options = tier_extra_options[instance_index.to_s] end instance_prompt_options[:options].deep_merge!(instance_extra_options) #instance_prompt_options[:name_required] = true instance_prompt_options[:instance_type_code] = instance_type_code # todo: an effort to render more useful help eg. -O Web.0.instance.name help_field_prefix = "#{tier_name}.#{instance_index}" instance_prompt_options[:help_field_prefix] = help_field_prefix instance_prompt_options[:options][:help_field_prefix] = help_field_prefix instance_prompt_options[:locked_fields] = scoped_instance_config['lockedFields'] instance_prompt_options[:for_app] = true instance_prompt_options[:skip_labels_prompt] = true # or could do this: instance_prompt_options[:labels] = default_labels # this provisioning helper method handles all (most) of the parsing and prompting scoped_instance_config = Marshal.load( Marshal.dump(scoped_instance_config) ) instance_config_payload = prompt_new_instance(instance_prompt_options) # strip all empty string and nil instance_config_payload.deep_compact! # use the blueprint config as the base final_config = scoped_instance_config.clone # merge the prompted values final_config.deep_merge!(instance_config_payload) final_config.delete('environments') final_config.delete('groups') final_config.delete('clouds') final_config.delete('lockedFields') final_config.delete('userRemovedFields') # should not need this... final_config.delete(:no_prompt) final_config.delete(:help_field_prefix) # add config to payload payload['tiers'][tier_name]['instances'] ||= [] payload['tiers'][tier_name]['instances'] << final_config end end else puts yellow, "Tier '#{tier_name}' is empty", reset end end elsif blueprint_type == 'terraform' # prompt for Terraform config # todo elsif blueprint_type == 'arm' # prompt for ARM config # todo elsif blueprint_type == 'cloudFormation' # prompt for cloudFormation config # todo else print yellow, "Unknown template type: #{template_type})", "\n" end end end end @apps_interface.setopts(options) # Validate Only if options[:validate_only] == true # Validate Only Dry run if options[:dry_run] if options[:json] puts as_json(payload, options) elsif options[:yaml] puts as_yaml(payload, options) else print_dry_run @apps_interface.dry.validate(payload) end return 0 end json_response = @apps_interface.validate(payload) if options[:json] puts as_json(json_response, options) else if !options[:quiet] if json_response['success'] == true print_green_success "New app '#{payload['name']}' validation passed. #{json_response['msg']}".strip else print_red_alert "New app '#{payload['name']}' validation failed. #{json_response['msg']}".strip # looks for special error format like instances.instanceErrors if json_response['errors'] && json_response['errors']['instances'] json_response['errors']['instances'].each do |error_obj| tier_name = error_obj['tier'] instance_index = error_obj['index'] instance_errors = error_obj['instanceErrors'] print_error red, "#{tier_name} : #{instance_index}", reset, "\n" if instance_errors instance_errors.each do |err_key, err_msg| print_error red, " * #{err_key} : #{err_msg}", reset, "\n" end end end else # a default way to print errors (json_response['errors'] || {}).each do |error_key, error_msg| if error_key != 'instances' print_error red, " * #{error_key} : #{error_msg}", reset, "\n" end end end end end end if json_response['success'] == true return 0 else return 1 end end @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.create(payload) return 0 end json_response = @apps_interface.create(payload) if options[:json] puts as_json(json_response, options) print "\n" elsif !options[:quiet] app = json_response["app"] print_green_success "Added app #{app['name']}" # add existing instances to blank app now? if !options[:no_prompt] && !payload['tiers'] && payload['id'] == 'existing' if ::Morpheus::Cli::OptionTypes::confirm("Would you like to add an instance now?", options.merge({default: false})) add_instance([app['id']]) while ::Morpheus::Cli::OptionTypes::confirm("Add another instance?", options.merge({default: false})) do add_instance([app['id']]) end end end # print details get_args = [app['id']] + (options[:remote] ? ["-r",options[:remote]] : []) + (options[:refresh_interval] ? ['--refresh', options[:refresh_interval].to_s] : []) get(get_args) end return 0 rescue RestClient::Exception => e #print_rest_exception(e, options) json_response = nil begin json_response = JSON.parse(e.response.to_s) rescue TypeError, JSON::ParserError => ex print_error red, "Failed to parse JSON response: #{ex}", reset, "\n" end if json_response && (json_response['errors'].nil? || json_response['errors'].empty?) # The default way to print error msg print_rest_exception(e, options) else # print errors and look for special errors.instances # todo: just handle sub lists of errors default error handler (print_rest_exception) (json_response['errors'] || {}).each do |error_key, error_msg| if error_key != 'instances' print_error red, " * #{error_key} : #{error_msg}", reset, "\n" end end # looks for special error format like instances.instanceErrors if json_response['errors'] && json_response['errors']['instances'] json_response['errors']['instances'].each do |error_obj| tier_name = error_obj['tier'] instance_index = error_obj['index'] instance_errors = error_obj['instanceErrors'] print_error red, "#{tier_name} : #{instance_index}", reset, "\n" if instance_errors instance_errors.each do |err_key, err_msg| print_error red, " * #{err_key} : #{err_msg}", reset, "\n" end end end end end exit 1 end end
connect(opts)
click to toggle source
# File lib/morpheus/cli/commands/apps.rb, line 30 def connect(opts) @api_client = establish_remote_appliance_connection(opts) @accounts_interface = @api_client.accounts @account_users_interface = @api_client.account_users @apps_interface = @api_client.apps @blueprints_interface = @api_client.blueprints @instance_types_interface = @api_client.instance_types @library_layouts_interface = @api_client.library_layouts @instances_interface = @api_client.instances @options_interface = @api_client.options @groups_interface = @api_client.groups @clouds_interface = @api_client.clouds @logs_interface = @api_client.logs @processes_interface = @api_client.processes @active_group_id = Morpheus::Cli::Groups.active_groups[@appliance_name] end
count(args)
click to toggle source
# File lib/morpheus/cli/commands/apps.rb, line 163 def count(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[options]") opts.on( '--owner USER', "Owner Username or ID" ) do |val| options[:owner] = val end opts.on( '--created-by USER', "Alias for --owner" ) do |val| options[:owner] = val end opts.add_hidden_option('--created-by') opts.on( '-s', '--search PHRASE', "Search Phrase" ) do |phrase| options[:phrase] = phrase end build_common_options(opts, options, [:query, :remote, :dry_run]) opts.footer = "Get the number of apps." end optparse.parse!(args) connect(options) begin params = {} params.merge!(parse_list_options(options)) account = nil if options[:owner] created_by_ids = find_all_user_ids(account ? account['id'] : nil, options[:owner]) return if created_by_ids.nil? params['createdBy'] = created_by_ids # params['ownerId'] = created_by_ids # 4.2.1+ end @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.list(params) return end json_response = @apps_interface.list(params) # print number only if json_response['meta'] && json_response['meta']['total'] print cyan, json_response['meta']['total'], reset, "\n" else print yellow, "unknown", reset, "\n" end return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
get(args)
click to toggle source
# File lib/morpheus/cli/commands/apps.rb, line 637 def get(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[app]") opts.on('--refresh [SECONDS]', String, "Refresh until status is running,failed. Default interval is #{default_refresh_interval} seconds.") do |val| options[:refresh_until_status] ||= "running,failed" if !val.to_s.empty? options[:refresh_interval] = val.to_f end end opts.on('--refresh-until STATUS', String, "Refresh until a specified status is reached.") do |val| options[:refresh_until_status] = val.to_s.downcase end build_standard_get_options(opts, options) opts.footer = "Get details about 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 print_error Morpheus::Terminal.angry_prompt puts_error "#{command_name} get expects 1 argument and received #{args.count}: #{args}\n#{optparse}" return 1 end connect(options) id_list = parse_id_list(args) return run_command_for_each_arg(id_list) do |arg| _get(arg, options) end end
handle(args)
click to toggle source
# File lib/morpheus/cli/commands/apps.rb, line 47 def handle(args) handle_subcommand(args) end
list(args)
click to toggle source
# File lib/morpheus/cli/commands/apps.rb, line 51 def list(args) params = {} options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage() opts.on( '-t', '--type TYPE', "Filter by type" ) do |val| options[:type] = val end opts.on( '--blueprint BLUEPRINT', "Blueprint Name or ID" ) do |val| options[:blueprint] = val end opts.on( '--owner USER', "Owner Username or ID" ) do |val| options[:owner] = val end opts.on( '--created-by USER', "[DEPRECATED] Alias for --owner" ) do |val| options[:owner] = val end opts.add_hidden_option('--created-by') opts.on('--pending-removal', "Include apps pending removal.") do options[:showDeleted] = true end opts.on('--pending-removal-only', "Only apps pending removal.") do options[:deleted] = true end opts.on('--environment ENV', "Filter by environment code (appContext)") do |val| # environment means appContext params['environment'] = (params['environment'] || []) + val.to_s.split(',').collect {|s| s.strip }.select {|s| s != "" } end opts.on('--status STATUS', "Filter by status.") do |val| params['status'] = (params['status'] || []) + val.to_s.split(',').collect {|s| s.strip }.select {|s| s != "" } end opts.on('-l', '--labels LABEL', String, "Filter by labels, can match any of the values") do |val| add_query_parameter(params, 'labels', parse_labels(val)) end opts.on('--all-labels LABEL', String, "Filter by labels, must match all of the values") do |val| add_query_parameter(params, 'allLabels', parse_labels(val)) end opts.on('-a', '--details', "Display all details: memory and storage usage used / max values." ) do options[:details] = true end build_standard_list_options(opts, options) opts.footer = "List apps." end optparse.parse!(args) # verify_args!(args:args, optparse:optparse, count:0) if args.count > 0 options[:phrase] = args.join(" ") end connect(options) if options[:type] params['type'] = [options[:type]].flatten.collect {|it| it.to_s.strip.split(",") }.flatten.collect {|it| it.to_s.strip } end if options[:blueprint] blueprint_ids = [options[:blueprint]].flatten.collect {|it| it.to_s.strip.split(",") }.flatten.collect {|it| it.to_s.strip } params['blueprintId'] = blueprint_ids.collect do |blueprint_id| if blueprint_id.to_s =~ /\A\d{1,}\Z/ return blueprint_id else blueprint = find_blueprint_by_name_or_id(blueprint_id) return 1 if blueprint.nil? blueprint['id'] end end end if options[:owner] owner_ids = [options[:owner]].flatten.collect {|it| it.to_s.strip.split(",") }.flatten.collect {|it| it.to_s.strip } params['ownerId'] = owner_ids.collect do |owner_id| if owner_id.to_s =~ /\A\d{1,}\Z/ return owner_id else user = find_available_user_option(owner_id) return 1 if user.nil? user['id'] end end end params.merge!(parse_list_options(options)) account = nil if options[:owner] created_by_ids = find_all_user_ids(account ? account['id'] : nil, options[:owner]) return if created_by_ids.nil? params['createdBy'] = created_by_ids # params['ownerId'] = created_by_ids # 4.2.1+ end params['showDeleted'] = options[:showDeleted] if options.key?(:showDeleted) params['deleted'] = options[:deleted] if options.key?(:deleted) @apps_interface.setopts(options) if options[:dry_run] print_dry_run @apps_interface.dry.list(params) return end json_response = @apps_interface.list(params) render_response(json_response, options, "apps") do apps = json_response['apps'] title = "Morpheus Apps" subtitles = [] subtitles += parse_list_subtitles(options) print_h1 title, subtitles, options if apps.empty? print cyan,"No apps found.",reset,"\n" else print_apps_table(apps, options) print_results_pagination(json_response) end print reset,"\n" end return 0, nil end