class Morpheus::Cli::ContainersCommand
Public Instance Methods
_eject(container_id, options)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 351 def _eject(container_id, options) container = find_container_by_id(container_id) # could skip this since only id is supported return 1 if container.nil? @containers_interface.setopts(options) if options[:dry_run] print_dry_run @containers_interface.dry.eject(container['id']) return 0 end json_response = @containers_interface.eject(container['id']) render_response(json_response, options) do print green, "Ejecting container #{container['id']}", reset, "\n" end return 0, nil end
_get(arg, options)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 69 def _get(arg, options) @containers_interface.setopts(options) if options[:dry_run] print_dry_run @containers_interface.dry.get(arg.to_i) return end #container = find_container_by_id(arg) #return 1 if container.nil? json_response = @containers_interface.get(arg.to_i) container = json_response['container'] render_response(json_response, options, "container") do # stats = json_response['stats'] || {} stats = container['stats'] || {} # load_balancers = stats = json_response['loadBalancers'] || {} # todo: show as 'VM' instead of 'Container' maybe..err # may need to fetch instance by id too.. # ${[null,'docker'].contains(instance?.layout?.provisionType?.code) ? 'CONTAINERS' : 'VMs'} print_h1 "Container Details" print cyan description_cols = { "ID" => 'id', #"Name" => 'name', "Name" => lambda {|it| it['server'] ? it['server']['name'] : '(no server)' }, # there is a server.displayName too? "Type" => lambda {|it| it['containerType'] ? it['containerType']['name'] : '' }, "Plan" => lambda {|it| it['plan'] ? it['plan']['name'] : '' }, # "Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' }, # "Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' }, "Instance" => lambda {|it| it['instance'] ? it['instance']['name'] : '' }, "Host" => lambda {|it| it['server'] ? it['server']['name'] : '' }, "Cloud" => lambda {|it| it['cloud'] ? it['cloud']['name'] : '' }, "Location" => lambda {|it| format_container_connection_string(it) }, # "Description" => 'description', # "Group" => lambda {|it| it['group'] ? it['group']['name'] : '' }, # "Cloud" => lambda {|it| it['cloud'] ? it['cloud']['name'] : '' }, # "Type" => lambda {|it| it['instanceType']['name'] }, # "Plan" => lambda {|it| it['plan'] ? it['plan']['name'] : '' }, # "Environment" => 'instanceContext', # "Nodes" => lambda {|it| it['containers'] ? it['containers'].count : 0 }, # "Connection" => lambda {|it| format_container_connection_string(it) }, #"Account" => lambda {|it| it['account'] ? it['account']['name'] : '' }, "Created" => lambda {|it| format_local_dt(it['dateCreated']) }, "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }, "Status" => lambda {|it| format_container_status(it) } } print_description_list(description_cols, container) if (stats) print_h2 "Container Usage" print_stats_usage(stats) end if options[:include_available_actions] if (container["availableActions"]) print_h2 "Available Actions" print as_pretty_table(container["availableActions"], [:name, :code]) print reset, "\n" else print "#{yellow}No available actions#{reset}\n\n" end end if options[:include_costs] print_h2 "Container Cost" cost_columns = { "Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' }, "Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' }, } print_description_list(cost_columns, container) end print reset, "\n" end # 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?(container['status']) print cyan 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(arg, options) end end return 0, nil end
_restart(container_id, options)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 269 def _restart(container_id, options) container = find_container_by_id(container_id) # could skip this since only id is supported return 1 if container.nil? @containers_interface.setopts(options) if options[:dry_run] print_dry_run @containers_interface.dry.restart(container['id']) return 0 end json_response = @containers_interface.restart(container['id']) render_response(json_response, options) do print green, "Restarting container #{container['id']}", reset, "\n" end return 0, nil end
_start(container_id, options)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 228 def _start(container_id, options) container = find_container_by_id(container_id) # could skip this since only id is supported return 1 if container.nil? @containers_interface.setopts(options) if options[:dry_run] print_dry_run @containers_interface.dry.start(container['id']) return 0 end json_response = @containers_interface.start(container['id']) render_response(json_response, options) do print green, "Starting container #{container['id']}", reset, "\n" end return 0, nil end
_stop(container_id, options)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 187 def _stop(container_id, options) container = find_container_by_id(container_id) # could skip this since only id is supported return 1 if container.nil? @containers_interface.setopts(options) if options[:dry_run] print_dry_run @containers_interface.dry.stop(container['id']) return 0 end json_response = @containers_interface.stop(container['id']) render_response(json_response, options) do print green, "Stopping container #{container['id']}", reset, "\n" end return 0, nil end
_suspend(container_id, options)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 310 def _suspend(container_id, options) container = find_container_by_id(container_id) # could skip this since only id is supported return 1 if container.nil? @containers_interface.setopts(options) if options[:dry_run] print_dry_run @containers_interface.dry.suspend(container['id']) return 0 end json_response = @containers_interface.suspend(container['id']) render_response(json_response, options) do print green, "Suspending container #{container['id']}", reset, "\n" end return 0, nil end
action(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 424 def action(args) options = {} action_id = nil optparse = Morpheus::Cli::OptionParser.new do|opts| opts.banner = subcommand_usage("[id] -a CODE") opts.on('-a', '--action CODE', "Container Action CODE to execute") do |val| action_id = val.to_s end build_standard_update_options(opts, options, [:auto_confirm]) opts.footer = <<-EOT Execute an action for a container or containers [id] is required. This is the id of a container. Supports multiple [id] arguments. Examples: containers action 42 -a docker-remove-node EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, min:1) connect(options) id_list = parse_id_list(args) validate_container_ids!(id_list) containers = [] id_list.each do |container_id| container = find_container_by_id(container_id) if container.nil? # return 1 else containers << container end end if containers.size != id_list.size #puts_error "containers not found" return 1 end container_ids = containers.collect {|container| container["id"] } # figure out what action to run # assume that the action is available for all the containers.. available_actions = containers.first['availableActions'] if available_actions.empty? print_red_alert "Container #{container['id']} has no available actions" if container_ids.size > 1 print_red_alert "The specified containers have no available actions in common" else print_red_alert "The specified container has no available actions" end return 1 end container_action = nil if action_id.nil? available_actions_dropdown = available_actions.collect {|act| {'name' => act["name"], 'value' => act["code"]} } # already sorted v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'code', 'type' => 'select', 'fieldLabel' => 'Container Action', 'selectOptions' => available_actions_dropdown, 'required' => true, 'description' => 'Choose the container action to execute'}], options[:options]) action_id = v_prompt['code'] container_action = available_actions.find {|act| act['code'].to_s == action_id.to_s } else container_action = available_actions.find {|act| act['code'].to_s == action_id.to_s || act['name'].to_s.downcase == action_id.to_s.downcase } action_id = container_action["code"] if container_action end if !container_action # for testing bogus actions.. # container_action = {"id" => action_id, "name" => "Unknown"} raise_command_error "Container Action '#{action_id}' not found." end action_display_name = "#{container_action['name']} [#{container_action['code']}]" confirm!("Are you sure you would like to perform action #{action_display_name} on #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}?", options) # return run_command_for_each_arg(containers) do |arg| # _action(arg, action_id, options) # end @containers_interface.setopts(options) if options[:dry_run] print_dry_run @containers_interface.dry.action(container_ids.size == 1 ? container_ids[0] : container_ids, action_id) return 0 end json_response = @containers_interface.action(container_ids.size == 1 ? container_ids[0] : container_ids, action_id) render_response(json_response, options) do print green, "Action #{action_display_name} performed on #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}", reset, "\n" end return 0, nil end
actions(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 366 def actions(args) options = {} optparse = Morpheus::Cli::OptionParser.new do|opts| opts.banner = subcommand_usage("[id]") build_standard_get_options(opts, options) opts.footer = <<-EOT List the actions available to specified container(s). [id] is required. This is the id of a container. Supports multiple [id] arguments. Examples: containers actions 42 containers actions 1 2 3 EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, min:1) connect(options) id_list = parse_id_list(args) validate_container_ids!(id_list) containers = [] id_list.each do |container_id| container = find_container_by_id(container_id) if container.nil? # return 1 else containers << container end end if containers.size != id_list.size #puts_error "containers not found" return 1 end container_ids = containers.collect {|container| container["id"] } # container = find_container_by_name_or_id(args[0]) @containers_interface.setopts(options) if options[:dry_run] print_dry_run @containers_interface.dry.available_actions(container_ids.size == 1 ? container_ids[0] : container_ids) return 0 end json_response = @containers_interface.available_actions(container_ids.size == 1 ? container_ids[0] : container_ids) render_response(json_response, options) do title = "Container Actions: #{anded_list(id_list)}" print_h1 title available_actions = json_response["actions"] if (available_actions && available_actions.size > 0) print as_pretty_table(available_actions, [:name, :code]) print reset, "\n" else if container_ids.size > 1 print "#{yellow}The specified containers have no available actions in common.#{reset}\n\n" else print "#{yellow}No available actions#{reset}\n\n" end end end return 0, nil end
attach_floating_ip(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 777 def attach_floating_ip(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id]") opts.on('--ip ID', String, "Floating IP Address, in the format 'ip-ID'.") do |val| options[:ip] = val end opts.on('--pool ID', String, "Floating IP Pool Identifier, in the format 'pool-ID'.") do |val| options[:pool] = val end opts.on('--bandwidth VALUE', String, "Floating IP Bandidth (Mbit/s). Only cloud types Huawei and OpenTelekom support this option.") do |val| options[:bandwidth] = val end build_standard_update_options(opts, options, [:auto_confirm]) opts.footer = <<-EOT Attach a floating IP to a container. [id] is required. This is the id of a container. Only the following cloud types support this command: OpenStack, Huawei and OpenTelekom EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, count:1) connect(options) container = find_container_by_id(args[0]) return 1 if container.nil? cloud_type = load_container_cloud_type(container) if !cloud_type['hasFloatingIps'] raise_command_error "Cloud Type #{cloud_type['name']} does support floating IPs." end payload = parse_payload(options) if payload.nil? payload = parse_passed_options(options) attach_floating_ip_option_types = cloud_type['floatingIpTypes'] if attach_floating_ip_option_types && !attach_floating_ip_option_types.empty? if options[:ip] floating_ip = options[:ip].to_s.sub(/\Aip\-/i, '') floating_ip = (floating_ip =~ /\A\d{1,}\Z/) ? "ip-#{floating_ip.to_s}" : floating_ip options[:options]['config'] ||= {} options[:options]['config']['osExternalNetworkId'] = floating_ip elsif options[:pool] floating_ip = options[:pool].to_s.sub(/\Apool\-/i, '') floating_ip = (floating_ip =~ /\A\d{1,}\Z/) ? "pool-#{floating_ip.to_s}" : floating_ip options[:options]['config'] ||= {} options[:options]['config']['osExternalNetworkId'] = floating_ip end if options[:bandwidth] options[:options]['config'] ||= {} options[:options]['config']['floatingIpBandwidth'] = options[:bandwidth].to_i end #api_params = {zoneId: container['cloud'] ? container['cloud']['id'] : nil, resourcePoolId: container['resourcePool'] ? container['resourcePool']['id'] : nil} api_params = {containerId: container['id']} v_prompt = Morpheus::Cli::OptionTypes.prompt(attach_floating_ip_option_types, options[:options], @api_client, api_params) # payload.deep_merge!({'container' => v_prompt}) payload.deep_merge!(v_prompt) else # raise_command_error "Cloud Type #{cloud_type['name']} does not defined any floating IP inputs." end end confirm!("Are you sure you would like to attach this floating IP to container #{container['id']}?", options) @containers_interface.setopts(options) if options[:dry_run] print_dry_run @containers_interface.dry.attach_floating_ip(container['id'], payload) return end json_response = @containers_interface.attach_floating_ip(container['id'], payload) render_response(json_response, options) do print_green_success "Attaching floating IP to container #{container['id']}" end return 0, nil end
clone_image(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 705 def clone_image(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id]") opts.on( '--name VALUE', String, "Image Name (Template Name). Default is server name + timestamp" ) do |val| options[:options]['templateName'] = val end opts.on( '--folder VALUE', String, "Folder externalId or '/' to use the root folder" ) do |val| options[:options]['zoneFolder'] = val end build_standard_update_options(opts, options, [:auto_confirm]) opts.footer = <<-EOT Clone to image (template) for a container. [id] is required. This is the id of a container. EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, count:1) connect(options) container = find_container_by_id(args[0]) return 1 if container.nil? # need to GET provision type for hasFolders == true and cloneTemplte == true instance = find_instance_by_name_or_id(container['instance']['id']) return 1 if instance.nil? provision_type = load_container_provision_type(container, instance) # todo: add this cloneTemplate check to the api too obviously # if provision_type['cloneTemplate'] != true # raise_command_error "clone-image is not supported by provision type #{provision_type['name']}" # end payload = parse_payload(options) if payload.nil? payload = parse_passed_options(options) if payload['templateName'].nil? v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'templateName', 'type' => 'text', 'fieldLabel' => 'Image Name', 'description' => 'Choose a name for the new image template. Default is the server name + timestamp'}], options[:options]) if v_prompt['templateName'].to_s != '' payload['templateName'] = v_prompt['templateName'] end end #if provision_type['code'] == 'vmware' if provision_type && provision_type["hasFolders"] if payload['zoneFolder'].nil? # vmwareFolders moved from /api/options/vmwareFolders to /api/options/vmware/vmwareFolders folder_prompt = nil begin folder_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'zoneFolder', 'type' => 'select', 'optionSource' => 'vmwareFolders', 'optionSourceType' => 'vmware', 'fieldLabel' => 'Folder', 'description' => "Folder externalId or '/' to use the root folder", 'required' => true}], options[:options], @api_client, {siteId: instance['group']['id'], zoneId: instance['cloud']['id']}) rescue RestClient::Exception => e Morpheus::Logging::DarkPrinter.puts "Failed to load folder options" if Morpheus::Logging.debug? begin folder_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'zoneFolder', 'type' => 'select', 'optionSource' => 'vmwareFolders', 'fieldLabel' => 'Folder', 'description' => "Folder externalId or '/' to use the root folder", 'required' => true}], options[:options], @api_client, {siteId: instance['group']['id'], zoneId: instance['cloud']['id']}) rescue RestClient::Exception => e2 Morpheus::Logging::DarkPrinter.puts "Failed to load folder options from alternative endpoint too" if Morpheus::Logging.debug? end end if folder_prompt && folder_prompt['zoneFolder'].to_s != '' payload['zoneFolder'] = folder_prompt['zoneFolder'] end end end end confirm!("Are you sure you would like to clone as image container #{container['id']}?", options) @containers_interface.setopts(options) if options[:dry_run] print_dry_run @containers_interface.dry.clone_image(container['id'], payload) return end json_response = @containers_interface.clone_image(container['id'], payload) render_response(json_response, options) do print_green_success "Clone Image initiated for container #{container['id']}" end return 0, nil end
connect(opts)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 13 def connect(opts) @api_client = establish_remote_appliance_connection(opts) @containers_interface = @api_client.containers @instances_interface = @api_client.instances @provision_types_interface = @api_client.provision_types @logs_interface = @api_client.logs @execution_request_interface = @api_client.execution_request @clouds_interface = @api_client.clouds end
detach_floating_ip(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 848 def detach_floating_ip(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id]") build_standard_update_options(opts, options, [:auto_confirm]) opts.footer = <<-EOT Detach a floating IP from a container. [id] is required. This is the id of a container. Only the following cloud types support this command: OpenStack, Huawei and OpenTelekom EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, count:1) connect(options) container = find_container_by_id(args[0]) return 1 if container.nil? cloud_type = load_container_cloud_type(container) if !cloud_type['hasFloatingIps'] raise_command_error "Cloud Type #{cloud_type['name']} does support floating IPs." end payload = parse_payload(options) if payload.nil? payload = parse_passed_options(options) # prompt end confirm!("Are you sure you would like to detach the floating IP from container #{container['id']}?", options) @containers_interface.setopts(options) if options[:dry_run] print_dry_run @containers_interface.dry.detach_floating_ip(container['id'], payload) return end json_response = @containers_interface.detach_floating_ip(container['id'], payload) render_response(json_response, options) do print_green_success "Detaching floating IP from container #{container['id']}" end return 0, nil end
eject(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 325 def eject(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id]") build_standard_update_options(opts, options, [:auto_confirm]) opts.footer = <<-EOT Eject a container. [id] is required. This is the id of a container. Supports multiple [id] arguments. If more than one [id] is given, the command will execute for each one sequentially. Examples: containers eject 42 containers eject 1 2 3 -y EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, min:1) connect(options) id_list = parse_id_list(args) validate_container_ids!(id_list) confirm!("Are you sure you would like to eject #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}?", options) return run_command_for_each_arg(id_list) do |arg| _eject(arg, options) end end
execution_request(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 584 def execution_request(args) options = {} params = {} script_content = nil do_refresh = true optparse = Morpheus::Cli::OptionParser.new do|opts| opts.banner = subcommand_usage("[id] [options]") opts.on('--script SCRIPT', "Script to be executed" ) do |val| script_content = val end opts.on('--file FILE', "File containing the script. This can be used instead of --script" ) do |filename| full_filename = File.expand_path(filename) if File.exist?(full_filename) script_content = File.read(full_filename) else print_red_alert "File not found: #{full_filename}" exit 1 end end opts.on(nil, '--no-refresh', "Do not refresh until finished" ) do do_refresh = false end #build_option_type_options(opts, options, add_user_source_option_types()) build_standard_update_options(opts, options) opts.footer = <<-EOT Execute an arbitrary command or script on a container. [id] is required. This is the id of a container. [script] is required and can be passed as --script of --file instead. This is the script that is to be executed. Examples: containers exec 42 "uname -a" EOT end optparse.parse!(args) connect(options) verify_args!(args:args, optparse:optparse, count:1) container = find_container_by_id(args[0]) return 1 if container.nil? params['containerId'] = container['id'] # construct payload payload = {} if options[:payload] payload = options[:payload] else payload.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options] # prompt for Script if script_content.nil? v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'script', 'type' => 'code-editor', 'fieldLabel' => 'Script', 'required' => true, 'description' => 'The script content'}], options[:options]) script_content = v_prompt['script'] end payload['script'] = script_content end @execution_request_interface.setopts(options) if options[:dry_run] print_dry_run @execution_request_interface.dry.create(params, payload) return 0 end # do it json_response = @execution_request_interface.create(params, payload) # print and return result render_response(json_response, options) do execution_request = json_response['executionRequest'] print_green_success "Executing request #{execution_request['uniqueId']}" if do_refresh Morpheus::Cli::ExecutionRequestCommand.new.handle(["get", execution_request['uniqueId'], "--refresh"]+ (options[:remote] ? ["-r",options[:remote]] : [])) else Morpheus::Cli::ExecutionRequestCommand.new.handle(["get", execution_request['uniqueId']]+ (options[:remote] ? ["-r",options[:remote]] : [])) end end return 0, nil end
get(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 27 def get(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id]") opts.on( nil, '--actions', "Display Available Actions" ) do options[:include_available_actions] = true end opts.on( nil, '--costs', "Display Cost and Price" ) do options[:include_costs] = true end 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 = <<-EOT Get details about a container. [id] is required. This is the id of a container. Supports multiple [id] arguments. If more than one [id] is given, the command will execute for each one sequentially. Examples: containers get 42 containers get 1 2 3 containers get 42 --refresh containers get 42 --refresh 10 --refresh-until stopped EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, min:1) connect(options) id_list = parse_id_list(args) validate_container_ids!(id_list) 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/containers_command.rb, line 23 def handle(args) handle_subcommand(args) end
import(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 658 def import(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id] [image]") opts.on( '--storage-provider VALUE', String, "Optional storage provider to use" ) do |val| options[:options]['storageProviderId'] = val end build_standard_update_options(opts, options, [:auto_confirm]) opts.footer = <<-EOT Import image template for a container. [id] is required. This is the id of a container. EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, count:1) connect(options) container = find_container_by_id(args[0]) return 1 if container.nil? instance = find_instance_by_name_or_id(container['instance']['id']) return 1 if instance.nil? # need to GET provision type for exportServer == true provision_type = load_container_provision_type(container, instance) # todo: add this exportServer to the api too obviously (oh it is there.. but clone-image is not) # if provision_type['exportServer'] != true # raise_command_error "import is not supported by provision type #{provision_type['name']}" # end payload = parse_payload(options) if payload.nil? payload = parse_passed_options(options) container_import_option_types = [ {'fieldName' => 'storageProviderId', 'type' => 'select', 'fieldLabel' => 'Storage Provider', 'optionSource' => 'storageProviders', 'required' => false, 'description' => 'Select Storage Provider.'} ] payload.deep_merge! Morpheus::Cli::OptionTypes.prompt(container_import_option_types, options[:options], @api_client, {}) end confirm!("Are you sure you would like to import container #{container['id']}?", options) @containers_interface.setopts(options) if options[:dry_run] print_dry_run @containers_interface.dry.import(container['id'], payload) return end json_response = @containers_interface.import(container['id'], payload) render_response(json_response, options) do print_green_success "Import initiated for container #{container['id']}" end return 0, nil end
logs(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 507 def logs(args) options = {} params = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id]") 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('--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_standard_list_options(opts, options) opts.footer = <<-EOT List logs for a container. [id] is required. This is the id of a container. Supports multiple [id] arguments. Examples: containers logs 42 --level ERROR EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, min:1) connect(options) id_list = parse_id_list(args) validate_container_ids!(id_list) containers = id_list # heh 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] @logs_interface.setopts(options) if options[:dry_run] print_dry_run @logs_interface.dry.container_logs(containers, params) return end json_response = @logs_interface.container_logs(containers, params) render_response(json_response, options, "logs") do logs = json_response title = "Container Logs: #{containers.join(', ')}" 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['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" end return 0, nil end
restart(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 243 def restart(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id]") build_standard_update_options(opts, options, [:auto_confirm]) opts.footer = <<-EOT Restart a container. [id] is required. This is the id of a container. Supports multiple [id] arguments. If more than one [id] is given, the command will execute for each one sequentially. Examples: containers restart 42 containers restart 1 2 3 -y EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, min:1) connect(options) id_list = parse_id_list(args) validate_container_ids!(id_list) confirm!("Are you sure you would like to restart #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}?", options) return run_command_for_each_arg(id_list) do |arg| _restart(arg, options) end end
start(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 202 def start(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id]") build_standard_update_options(opts, options, [:auto_confirm]) opts.footer = <<-EOT Start a container. [id] is required. This is the id of a container. Supports multiple [id] arguments. If more than one [id] is given, the command will execute for each one sequentially. Examples: containers start 42 containers start 1 2 3 -y EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, min:1) connect(options) id_list = parse_id_list(args) validate_container_ids!(id_list) confirm!("Are you sure you would like to start #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}?", options) return run_command_for_each_arg(id_list) do |arg| _start(arg, options) end end
stop(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 161 def stop(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id]") build_standard_update_options(opts, options, [:auto_confirm]) opts.footer = <<-EOT Stop a container. [id] is required. This is the id of a container. Supports multiple [id] arguments. If more than one [id] is given, the command will execute for each one sequentially. Examples: containers stop 42 containers stop 1 2 3 -y EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, min:1) connect(options) id_list = parse_id_list(args) validate_container_ids!(id_list) confirm!("Are you sure you would like to stop #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}?", options) return run_command_for_each_arg(id_list) do |arg| _stop(arg, options) end end
suspend(args)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 284 def suspend(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id]") build_standard_update_options(opts, options, [:auto_confirm]) opts.footer = <<-EOT Suspend a container. [id] is required. This is the id of a container. Supports multiple [id] arguments. If more than one [id] is given, the command will execute for each one sequentially. Examples: containers suspend 42 containers suspend 1 2 3 -y EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, min:1) connect(options) id_list = parse_id_list(args) validate_container_ids!(id_list) confirm!("Are you sure you would like to suspend #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}?", options) return run_command_for_each_arg(id_list) do |arg| _suspend(arg, options) end end
Private Instance Methods
find_container_by_id(id)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 888 def find_container_by_id(id) begin json_response = @containers_interface.get(id.to_i) return json_response['container'] rescue RestClient::Exception => e if e.response && e.response.code == 404 print_red_alert "Container not found by id #{id}" return nil else raise e end end end
load_container_cloud_type(container)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 951 def load_container_cloud_type(container) cloud_type_code = container['cloud']['type'] rescue nil cloud_type = nil if cloud_type_code cloud_type = @clouds_interface.cloud_types({code:cloud_type_code})['zoneTypes'][0] if cloud_type.nil? raise_command_error "Cloud Type not found by code #{cloud_type_code}" end else raise_command_error "Unable to determine cloud type for container #{container['id']}" end return cloud_type end
load_container_provision_type(container, instance=nil)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 914 def load_container_provision_type(container, instance=nil) if instance.nil? instance = find_instance_by_name_or_id(container['instance']['id']) return 1 if instance.nil? end # todo: should be returned by containers api too, get from instance for old api versions provision_type_code = container['containerType']['provisionTypeCode'] rescue nil provision_type_code = provision_type_code || container['provisionType']['code'] rescue nil if provision_type_code.nil? return load_instance_provision_type(instance) end provision_type = nil if provision_type_code provision_type = provision_types_interface.list({code:provision_type_code})['provisionTypes'][0] if provision_type.nil? raise_command_error "Provision Type not found by code #{provision_type_code}" end else raise_command_error "Unable to determine provision type for container #{container['id']}" end return provision_type end
load_instance_provision_type(instance)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 937 def load_instance_provision_type(instance) provision_type_code = instance['layout']['provisionTypeCode'] rescue nil provision_type = nil if provision_type_code provision_type = provision_types_interface.list({code:provision_type_code})['provisionTypes'][0] if provision_type.nil? raise_command_error "Provision Type not found by code #{provision_type_code}" end else raise_command_error "Unable to determine provision type for instance #{instance['id']}" end return provision_type end
validate_container_id!(id)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 906 def validate_container_id!(id) if id.to_s =~ /\A\d{1,}\Z/ true else raise_command_error "[id] argument is invalid, expected a number and got '#{id}'" #, args, optparse end end
validate_container_ids!(id_list)
click to toggle source
# File lib/morpheus/cli/commands/containers_command.rb, line 902 def validate_container_ids!(id_list) id_list.each { |id| validate_container_id!(id) } end