if ENV["TEST"] == 'true' require 'awesome_print' require 'pry' end $:.unshift(File.dirname(__FILE__) + '/vendor/core') require 'colorize' require 'thor' require File.expand_path(File.dirname(__FILE__) + '/ey_pro_cli/version') require File.expand_path(File.dirname(__FILE__) + '/vendor/core/ey-core') class EyProCli < Thor class << self attr_accessor :core_file def core_file @core_file ||= File.expand_path("~/.ey-core") end end desc "login", "Retrieve API token from Engine Yard PRO" def login email = ENV["EMAIL"] || ask("Email:") password = ENV["PASSWORD"] || ask("Password:", echo: false) token = unauthenticated_core_client.get_api_token(email, password).body["api_token"] existing_token = core_yaml[core_url] write_token = if existing_token && existing_token != token puts "New token does not match existing token. Overwriting".yellow true elsif existing_token == token puts "Token already exists".green false else puts "Writing token".green true end write_core_yaml(token) if write_token rescue Ey::Core::Response::Unauthorized abort "Invalid email or password".yellow end desc "logout", "Remove your Engine Yard PRO API token" def logout if core_yaml[core_url] core_yaml.delete(core_url) write_core_yaml puts "Successfully removed API token from credentials file".green else puts "No API token found".yellow end end desc "deploy [OPTIONS]", "Deploy your EY PRO application." option :environment, desc: "Name of the environment to deploy to.", required: true, aliases: "-e" option :account, desc: "Name or ID of the account that the environment resides in. If no account is specified, the app will deploy to the first environment that meets the criteria, in the accounts you have access to.", aliases: "-c" option :ref, desc: "A git reference to deploy." option :migrate, desc: "The migration command to run." option :app, desc: "Application name or ID to deploy. If :account is not specified, this will be the first app that matches the criteria in the accounts you have access to.", required: true, aliases: "-a" option :stream, desc: "Stream deploy output to console." option "no-migrate", desc: "Do not run migration command." option "no-update-check", desc: "Do not check for updates." def deploy check_for_updates unless options["no-update-check"] environment = core_environment_for(options) app = core_application_for(options) deploy_options = {} deploy_options.merge!(ref: options[:ref]) if options[:ref] deploy_options.merge!(migrate_command: options[:migrate]) if options[:migrate] deploy_options.merge!(migrate_command: '') if options["no-migrate"] request = environment.deploy(app, deploy_options) puts "Deploy started to environment: #{environment.name} with application: #{app.name}" if options[:stream] request.subscribe { |m| print m["message"] if m.is_a?(Hash) } puts "" # fix console output from stream else request.ready! end if request.successful puts "Deploy successful!" else abort "Deploy failed!" end end no_commands do def unauthenticated_core_client @unauthenticated_core_client ||= Ey::Core::Client.new(token: nil, url: core_url) end def core_client @core_client ||= Ey::Core::Client.new(url: core_url, config_file: self.class.core_file) rescue RuntimeError => e if e.message.match(/missing token/i) abort "Missing credentials. Run 'ey-pro login' to retrieve your Engine Yard PRO API token".yellow else raise e end end def core_url (ENV["CORE_URL"] && File.join(ENV["CORE_URL"], '/')) || "https://api.engineyard.com/" end end private def check_for_updates gem = core_client.gems.get("ey-pro-cli") unless gem puts "Unable to find current version of CLI utility".yellow return end current_version = gem.current_version if Gem::Version.new(EyProCliVersion::VERSION) < Gem::Version.new(current_version) print <<-EOF ey-pro-cli gem outdated, consider updating! Installed version: #{EyProCliVersion::VERSION} Current Version: #{current_version} EOF .yellow end end def write_core_yaml(token=nil) core_yaml[core_url] = token if token File.open(self.class.core_file, "w") { |f| f.puts core_yaml.to_yaml } end def core_yaml @core_yaml ||= YAML.load_file(self.class.core_file) || {} end def core_account_for(options={}) @core_account ||= core_client.accounts.get(options[:account]) @core_account ||= core_client.accounts.first(name: options[:account]) end def operator(options) options[:account] ? core_account_for(options) : core_client end def core_environment_for(options={}) operator(options).environments.first(name: options[:environment]) end def core_application_for(options={}) return nil unless options[:app] app = begin Integer(options[:app]) rescue options[:app] end if app.is_a?(Integer) operator(options).applications.get(app) else operator(options).applications.first(name: app) end end end