lib/cli/commands/apps.rb in vmc-0.3.16.beta.2 vs lib/cli/commands/apps.rb in vmc-0.3.16.beta.3

- old
+ new

@@ -2,16 +2,20 @@ require 'fileutils' require 'pathname' require 'tempfile' require 'tmpdir' require 'set' +require "uuidtools" +require 'socket' module VMC::Cli::Command class Apps < Base include VMC::Cli::ServicesHelper include VMC::Cli::ManifestHelper + include VMC::Cli::TunnelHelper + include VMC::Cli::ConsoleHelper def list apps = client.apps apps.sort! {|a, b| a[:name] <=> b[:name] } return display JSON.pretty_generate(apps || []) if @options[:json] @@ -41,10 +45,56 @@ def info(what, default=nil) @options[what] || (@app_info && @app_info[what.to_s]) || default end + def console(appname, interactive=true) + unless defined? Caldecott + display "To use `vmc rails-console', you must first install Caldecott:" + display "" + display "\tgem install caldecott" + display "" + display "Note that you'll need a C compiler. If you're on OS X, Xcode" + display "will provide one. If you're on Windows, try DevKit." + display "" + display "This manual step will be removed in the future." + display "" + err "Caldecott is not installed." + end + + #Make sure there is a console we can connect to first + conn_info = console_connection_info appname + + port = pick_tunnel_port(@options[:port] || 20000) + + raise VMC::Client::AuthError unless client.logged_in? + + if not tunnel_pushed? + display "Deploying tunnel application '#{tunnel_appname}'." + auth = UUIDTools::UUID.random_create.to_s + push_caldecott(auth) + start_caldecott + else + auth = tunnel_auth + end + + if not tunnel_healthy?(auth) + display "Redeploying tunnel application '#{tunnel_appname}'." + # We don't expect caldecott not to be running, so take the + # most aggressive restart method.. delete/re-push + client.delete_app(tunnel_appname) + invalidate_tunnel_app_info + push_caldecott(auth) + start_caldecott + end + + start_tunnel(port, conn_info, auth) + wait_for_tunnel_start(port) + start_local_console(port, appname) if interactive + port + end + def start(appname=nil, push=false) if appname do_start(appname, push) else each_app do |name| @@ -71,18 +121,10 @@ def restart(appname=nil) stop(appname) start(appname) end - def rename(appname, newname) - app = client.app_info(appname) - app[:name] = newname - display 'Renaming Appliction: ' - client.update_app(newname, app) - display 'OK'.green - end - def mem(appname, memsize=nil) app = client.app_info(appname) mem = current_mem = mem_quota_to_choice(app[:resources][:memory]) memsize = normalize_mem(memsize) if memsize @@ -134,11 +176,11 @@ end def delete(appname=nil) force = @options[:force] if @options[:all] - if no_prompt || force || ask("Delete ALL applications and services?", :default => false) + if no_prompt || force || ask("Delete ALL applications?", :default => false) apps = client.apps apps.each { |app| delete_app(app[:name], force) } end else err 'No valid appname given' unless appname @@ -149,11 +191,11 @@ def files(appname, path='/') return all_files(appname, path) if @options[:all] && !@options[:instance] instance = @options[:instance] || '0' content = client.app_files(appname, path, instance) display content - rescue VMC::Client::NotFound => e + rescue VMC::Client::TargetError err 'No such file or directory' end def logs(appname) # Check if we have an app before progressing further @@ -649,11 +691,11 @@ def grab_logs(appname, instance) log_file_paths.each do |path| begin content = client.app_files(appname, path, instance) display_logfile(path, content, instance) - rescue VMC::Client::NotFound + rescue VMC::Client::TargetError end end end def grab_crash_logs(appname, instance, was_staged=false) @@ -663,17 +705,18 @@ instance ||= '0' map = VMC::Cli::Config.instances instance = map[instance] if map[instance] %w{ - /logs/err.log /logs/staging.log /app/logs/stderr.log - /app/logs/stdout.log /app/logs/startup.log /app/logs/migration.log + /logs/err.log /logs/staging.log /logs/migration.log + /app/logs/stderr.log /app/logs/stdout.log /app/logs/startup.log + /app/logs/migration.log }.each do |path| begin content = client.app_files(appname, path, instance) display_logfile(path, content, instance) - rescue VMC::Client::NotFound + rescue VMC::Client::TargetError end end end def grab_startup_tail(appname, since = 0) @@ -687,10 +730,12 @@ tail = response_lines[since, lines] || [] new_lines = tail.size display tail.join("\n") if new_lines > 0 end since + new_lines + rescue VMC::Client::TargetError + 0 end def provisioned_services_apps_hash apps = client.apps services_apps_hash = {} @@ -742,14 +787,15 @@ end end def do_start(appname, push=false) app = client.app_info(appname) - return display "Application '#{appname}' could not be found".red if app.nil? return display "Application '#{appname}' already started".yellow if app[:state] == 'STARTED' + + if @options[:debug] runtimes = client.runtimes_info return display "Cannot get runtime information." unless runtimes runtime = runtimes[app[:staging][:stack].to_sym] @@ -782,10 +828,11 @@ end end app[:state] = 'STARTED' app[:debug] = @options[:debug] + app[:console] = VMC::Cli::Framework.lookup_by_framework(app[:staging][:model]).console client.update_app(appname, app) Thread.kill(t) clear(LINE_LENGTH) display "#{banner}#{'OK'.green}" @@ -798,28 +845,27 @@ start_time = Time.now.to_i loop do display '.', false unless count > TICKER_TICKS sleep SLEEP_TIME - begin - break if app_started_properly(appname, count > HEALTH_TICKS) - if !crashes(appname, false, start_time).empty? - # Check for the existance of crashes - display "\nError: Application [#{appname}] failed to start, logs information below.\n".red - grab_crash_logs(appname, '0', true) - if push and !no_prompt - display "\n" - delete_app(appname, false) if ask "Delete the application?", :default => true - end - failed = true - break - elsif count > TAIL_TICKS - log_lines_displayed = grab_startup_tail(appname, log_lines_displayed) + + break if app_started_properly(appname, count > HEALTH_TICKS) + + if !crashes(appname, false, start_time).empty? + # Check for the existance of crashes + display "\nError: Application [#{appname}] failed to start, logs information below.\n".red + grab_crash_logs(appname, '0', true) + if push and !no_prompt + display "\n" + delete_app(appname, false) if ask "Delete the application?", :default => true end - rescue => e - err(e.message, '') + failed = true + break + elsif count > TAIL_TICKS + log_lines_displayed = grab_startup_tail(appname, log_lines_displayed) end + count += 1 if count > GIVEUP_TICKS # 2 minutes display "\nApplication is taking too long to start, check your logs".yellow break end @@ -887,11 +933,11 @@ if !app_checked and app_exists?(appname) err "Application '#{appname}' already exists, use update or delete." end - default_url = "#{appname}.#{VMC::Cli::Config.suggest_url}" + default_url = "#{appname}.#{target_base}" unless no_prompt || url url = ask( "Application Deployed URL", :default => default_url @@ -1016,10 +1062,10 @@ path, content, entry[:index], "====> [#{entry[:index]}: #{path}] <====\n".bold ) - rescue VMC::Client::NotFound + rescue VMC::Client::TargetError end end end end