engineyard 1.4.29 → 1.7.0.pre2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +139 -4
- data/bin/ey +1 -7
- data/lib/engineyard.rb +1 -22
- data/lib/engineyard/cli.rb +192 -94
- data/lib/engineyard/cli/#recipes.rb# +32 -0
- data/lib/engineyard/cli/api.rb +42 -28
- data/lib/engineyard/cli/recipes.rb +13 -6
- data/lib/engineyard/cli/ui.rb +103 -42
- data/lib/engineyard/cli/web.rb +16 -10
- data/lib/engineyard/config.rb +92 -18
- data/lib/engineyard/deploy_config.rb +66 -0
- data/lib/engineyard/deploy_config/migrate.rb +125 -0
- data/lib/engineyard/deploy_config/ref.rb +56 -0
- data/lib/engineyard/error.rb +38 -78
- data/lib/engineyard/repo.rb +75 -27
- data/lib/engineyard/serverside_runner.rb +133 -0
- data/lib/engineyard/thor.rb +110 -18
- data/lib/engineyard/version.rb +1 -1
- data/spec/engineyard/cli/api_spec.rb +10 -16
- data/spec/engineyard/cli_spec.rb +0 -11
- data/spec/engineyard/config_spec.rb +1 -8
- data/spec/engineyard/deploy_config_spec.rb +203 -0
- data/spec/engineyard/eyrc_spec.rb +2 -0
- data/spec/engineyard/repo_spec.rb +57 -34
- data/spec/ey/deploy_spec.rb +102 -52
- data/spec/ey/list_environments_spec.rb +69 -14
- data/spec/ey/login_spec.rb +11 -7
- data/spec/ey/logout_spec.rb +4 -4
- data/spec/ey/logs_spec.rb +6 -6
- data/spec/ey/recipes/apply_spec.rb +1 -1
- data/spec/ey/recipes/download_spec.rb +1 -1
- data/spec/ey/recipes/upload_spec.rb +6 -6
- data/spec/ey/rollback_spec.rb +3 -3
- data/spec/ey/ssh_spec.rb +9 -9
- data/spec/ey/status_spec.rb +2 -2
- data/spec/ey/whoami_spec.rb +9 -8
- data/spec/spec_helper.rb +18 -15
- data/spec/support/{fake_awsm.rb → git_repos.rb} +0 -14
- data/spec/support/helpers.rb +84 -28
- data/spec/support/matchers.rb +0 -16
- data/spec/support/shared_behavior.rb +83 -103
- metadata +65 -51
- data/lib/engineyard/api.rb +0 -117
- data/lib/engineyard/collection.rb +0 -7
- data/lib/engineyard/collection/abstract.rb +0 -71
- data/lib/engineyard/collection/apps.rb +0 -8
- data/lib/engineyard/collection/environments.rb +0 -8
- data/lib/engineyard/model.rb +0 -12
- data/lib/engineyard/model/account.rb +0 -8
- data/lib/engineyard/model/api_struct.rb +0 -33
- data/lib/engineyard/model/app.rb +0 -32
- data/lib/engineyard/model/deployment.rb +0 -90
- data/lib/engineyard/model/environment.rb +0 -194
- data/lib/engineyard/model/instance.rb +0 -166
- data/lib/engineyard/model/log.rb +0 -9
- data/lib/engineyard/model/user.rb +0 -6
- data/lib/engineyard/resolver.rb +0 -134
- data/lib/engineyard/rest_client_ext.rb +0 -9
- data/lib/engineyard/ruby_ext.rb +0 -9
- data/spec/engineyard/api_spec.rb +0 -39
- data/spec/engineyard/collection/apps_spec.rb +0 -16
- data/spec/engineyard/collection/environments_spec.rb +0 -16
- data/spec/engineyard/model/api_struct_spec.rb +0 -41
- data/spec/engineyard/model/environment_spec.rb +0 -198
- data/spec/engineyard/model/instance_spec.rb +0 -27
- data/spec/engineyard/resolver_spec.rb +0 -112
- data/spec/support/fake_awsm.ru +0 -245
- data/spec/support/scenarios.rb +0 -417
| @@ -1,33 +0,0 @@ | |
| 1 | 
            -
            module EY
         | 
| 2 | 
            -
              module Model
         | 
| 3 | 
            -
                class ApiStruct < Struct
         | 
| 4 | 
            -
             | 
| 5 | 
            -
                  def self.new(*args, &block)
         | 
| 6 | 
            -
                    super(*args) do |*block_args|
         | 
| 7 | 
            -
                      block.call(*block_args) if block
         | 
| 8 | 
            -
             | 
| 9 | 
            -
                      def self.from_array(array, common_values = {})
         | 
| 10 | 
            -
                        array.map do |values|
         | 
| 11 | 
            -
                          from_hash(values.merge(common_values))
         | 
| 12 | 
            -
                        end if array
         | 
| 13 | 
            -
                      end
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                      def self.from_hash(hash)
         | 
| 16 | 
            -
                        return nil unless hash
         | 
| 17 | 
            -
                        # in ruby 1.8, #members is an array of strings
         | 
| 18 | 
            -
                        # in ruby 1.9, #members is an array of symbols
         | 
| 19 | 
            -
                        members = new.members.map {|m| m.to_sym}
         | 
| 20 | 
            -
                        values = members.map{|a| hash.has_key?(a) ? hash[a] : hash[a.to_s] }
         | 
| 21 | 
            -
                        new(*values)
         | 
| 22 | 
            -
                      end
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                    end
         | 
| 25 | 
            -
                  end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                  def api_get(uri, options = {})
         | 
| 28 | 
            -
                    api.request(uri, options.merge(:method => :get))
         | 
| 29 | 
            -
                  end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                end
         | 
| 32 | 
            -
              end
         | 
| 33 | 
            -
            end
         | 
    
        data/lib/engineyard/model/app.rb
    DELETED
    
    | @@ -1,32 +0,0 @@ | |
| 1 | 
            -
            module EY
         | 
| 2 | 
            -
              module Model
         | 
| 3 | 
            -
                class App < ApiStruct.new(:id, :account, :name, :repository_uri, :environments, :api)
         | 
| 4 | 
            -
             | 
| 5 | 
            -
                  def self.from_hash(hash)
         | 
| 6 | 
            -
                    super.tap do |app|
         | 
| 7 | 
            -
                      app.environments = Environment.from_array(app.environments, :api => app.api)
         | 
| 8 | 
            -
                      app.account = Account.from_hash(app.account)
         | 
| 9 | 
            -
                    end
         | 
| 10 | 
            -
                  end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                  def self.from_array(*)
         | 
| 13 | 
            -
                    Collection::Apps.new(super)
         | 
| 14 | 
            -
                  end
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                  def sole_environment
         | 
| 17 | 
            -
                    if environments.size == 1
         | 
| 18 | 
            -
                      environments.first
         | 
| 19 | 
            -
                    end
         | 
| 20 | 
            -
                  end
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                  def sole_environment!
         | 
| 23 | 
            -
                    sole_environment or raise NoSingleEnvironmentError.new(self)
         | 
| 24 | 
            -
                  end
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                  def last_deployment_on(environment)
         | 
| 27 | 
            -
                    Deployment.last(self, environment, api)
         | 
| 28 | 
            -
                  end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                end
         | 
| 31 | 
            -
              end
         | 
| 32 | 
            -
            end
         | 
| @@ -1,90 +0,0 @@ | |
| 1 | 
            -
            require 'escape'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module EY
         | 
| 4 | 
            -
              module Model
         | 
| 5 | 
            -
                class Deployment < ApiStruct.new(:id, :app, :created_at, :commit, :environment, :finished_at, :migrate_command, :output, :ref, :resolved_ref, :successful, :user_name)
         | 
| 6 | 
            -
                  def self.api_root(app_id, environment_id)
         | 
| 7 | 
            -
                    "/apps/#{app_id}/environments/#{environment_id}/deployments"
         | 
| 8 | 
            -
                  end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                  def self.last(app, environment, api)
         | 
| 11 | 
            -
                    get(app, environment, 'last', api)
         | 
| 12 | 
            -
                  end
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                  def self.get(app, environment, id, api)
         | 
| 15 | 
            -
                    response = api.request(api_root(app.id, environment.id) + "/#{id}", :method => :get)
         | 
| 16 | 
            -
                    load_from_response app, environment, response
         | 
| 17 | 
            -
                  rescue EY::API::ResourceNotFound
         | 
| 18 | 
            -
                    nil
         | 
| 19 | 
            -
                  end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                  def self.load_from_response(app, environment, response)
         | 
| 22 | 
            -
                    dep = new
         | 
| 23 | 
            -
                    dep.app = app
         | 
| 24 | 
            -
                    dep.environment = environment
         | 
| 25 | 
            -
                    dep.update_with_response(response)
         | 
| 26 | 
            -
                    dep
         | 
| 27 | 
            -
                  end
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                  def self.started(environment, app, ref, migrate_command)
         | 
| 30 | 
            -
                    deployment = from_hash({
         | 
| 31 | 
            -
                      :app             => app,
         | 
| 32 | 
            -
                      :environment     => environment,
         | 
| 33 | 
            -
                      :migrate_command => migrate_command,
         | 
| 34 | 
            -
                      :ref             => ref,
         | 
| 35 | 
            -
                    })
         | 
| 36 | 
            -
                    deployment.start
         | 
| 37 | 
            -
                    deployment
         | 
| 38 | 
            -
                  end
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                  def migrate
         | 
| 41 | 
            -
                    !!migrate_command
         | 
| 42 | 
            -
                  end
         | 
| 43 | 
            -
             | 
| 44 | 
            -
                  alias successful? successful
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                  def start
         | 
| 47 | 
            -
                    post_to_api({
         | 
| 48 | 
            -
                      :migrate         => migrate,
         | 
| 49 | 
            -
                      :migrate_command => migrate_command,
         | 
| 50 | 
            -
                      :output          => output,
         | 
| 51 | 
            -
                      :ref             => ref,
         | 
| 52 | 
            -
                    })
         | 
| 53 | 
            -
                  end
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                  def finished(successful, output)
         | 
| 56 | 
            -
                    self.successful = successful
         | 
| 57 | 
            -
                    self.output = output
         | 
| 58 | 
            -
                    put_to_api({:successful => successful, :output => output})
         | 
| 59 | 
            -
                  end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                  def update_with_response(response)
         | 
| 62 | 
            -
                    response['deployment'].each do |key,val|
         | 
| 63 | 
            -
                      send("#{key}=", val) if respond_to?("#{key}=")
         | 
| 64 | 
            -
                    end
         | 
| 65 | 
            -
                  end
         | 
| 66 | 
            -
             | 
| 67 | 
            -
                  private
         | 
| 68 | 
            -
             | 
| 69 | 
            -
                  def post_to_api(params)
         | 
| 70 | 
            -
                    update_with_response api.request(collection_uri, :method => :post, :params => {:deployment => params})
         | 
| 71 | 
            -
                  end
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                  def put_to_api(params)
         | 
| 74 | 
            -
                    update_with_response api.request(member_uri("/finished"), :method => :put, :params => {:deployment => params})
         | 
| 75 | 
            -
                  end
         | 
| 76 | 
            -
             | 
| 77 | 
            -
                  def collection_uri
         | 
| 78 | 
            -
                    self.class.api_root(app.id, environment.id)
         | 
| 79 | 
            -
                  end
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                  def member_uri(path = nil)
         | 
| 82 | 
            -
                    collection_uri + "/#{id}#{path}"
         | 
| 83 | 
            -
                  end
         | 
| 84 | 
            -
             | 
| 85 | 
            -
                  def api
         | 
| 86 | 
            -
                    app.api
         | 
| 87 | 
            -
                  end
         | 
| 88 | 
            -
                end
         | 
| 89 | 
            -
              end
         | 
| 90 | 
            -
            end
         | 
| @@ -1,194 +0,0 @@ | |
| 1 | 
            -
            module EY
         | 
| 2 | 
            -
              module Model
         | 
| 3 | 
            -
                class Environment < ApiStruct.new(:id, :account, :name, :framework_env, :instances, :instances_count,
         | 
| 4 | 
            -
                                                  :apps, :app_master, :username, :app_server_stack_name, :deployment_configurations,
         | 
| 5 | 
            -
                                                  :load_balancer_ip_address, :api)
         | 
| 6 | 
            -
                  require 'launchy'
         | 
| 7 | 
            -
             | 
| 8 | 
            -
                  attr_accessor :ignore_bad_master
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                  def self.from_hash(hash)
         | 
| 11 | 
            -
                    super.tap do |env|
         | 
| 12 | 
            -
                      env.username = hash['ssh_username']
         | 
| 13 | 
            -
                      env.apps = App.from_array(env.apps, :api => env.api)
         | 
| 14 | 
            -
                      env.account = Account.from_hash(env.account)
         | 
| 15 | 
            -
                      env.instances = Instance.from_array(hash['instances'], :environment => env)
         | 
| 16 | 
            -
                      env.app_master = Instance.from_hash(env.app_master.merge(:environment => env)) if env.app_master
         | 
| 17 | 
            -
                    end
         | 
| 18 | 
            -
                  end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                  def self.from_array(*)
         | 
| 21 | 
            -
                    Collection::Environments.new(super)
         | 
| 22 | 
            -
                  end
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                  def logs
         | 
| 25 | 
            -
                    Log.from_array(api_get("/environments/#{id}/logs")["logs"])
         | 
| 26 | 
            -
                  end
         | 
| 27 | 
            -
             | 
| 28 | 
            -
                  def app_master!
         | 
| 29 | 
            -
                    master = app_master
         | 
| 30 | 
            -
                    if master.nil?
         | 
| 31 | 
            -
                      raise NoAppMasterError.new(name)
         | 
| 32 | 
            -
                    elsif !ignore_bad_master && master.status != "running"
         | 
| 33 | 
            -
                      raise BadAppMasterStatusError.new(master.status)
         | 
| 34 | 
            -
                    end
         | 
| 35 | 
            -
                    master
         | 
| 36 | 
            -
                  end
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                  def deploy(app, ref, deploy_options={})
         | 
| 39 | 
            -
                    app_master!.deploy(app,
         | 
| 40 | 
            -
                      ref,
         | 
| 41 | 
            -
                      migration_command(app, deploy_options),
         | 
| 42 | 
            -
                      config.merge(deploy_options['extras']),
         | 
| 43 | 
            -
                      deploy_options['verbose'])
         | 
| 44 | 
            -
                  end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                  def rollback(app, extra_deploy_hook_options={}, verbose=false)
         | 
| 47 | 
            -
                    app_master!.rollback(app,
         | 
| 48 | 
            -
                      config.merge(extra_deploy_hook_options),
         | 
| 49 | 
            -
                      verbose)
         | 
| 50 | 
            -
                  end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                  def take_down_maintenance_page(app, verbose=false)
         | 
| 53 | 
            -
                    app_master!.take_down_maintenance_page(app, verbose)
         | 
| 54 | 
            -
                  end
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                  def put_up_maintenance_page(app, verbose=false)
         | 
| 57 | 
            -
                    app_master!.put_up_maintenance_page(app, verbose)
         | 
| 58 | 
            -
                  end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                  def rebuild
         | 
| 61 | 
            -
                    api.request("/environments/#{id}/update_instances", :method => :put)
         | 
| 62 | 
            -
                  end
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                  def run_custom_recipes
         | 
| 65 | 
            -
                    api.request("/environments/#{id}/run_custom_recipes", :method => :put)
         | 
| 66 | 
            -
                  end
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                  def download_recipes
         | 
| 69 | 
            -
                    if File.exist?('cookbooks')
         | 
| 70 | 
            -
                      raise EY::Error, "Could not download, cookbooks already exists"
         | 
| 71 | 
            -
                    end
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                    require 'tempfile'
         | 
| 74 | 
            -
                    tmp = Tempfile.new("recipes")
         | 
| 75 | 
            -
                    tmp.write(api.request("/environments/#{id}/recipes"))
         | 
| 76 | 
            -
                    tmp.flush
         | 
| 77 | 
            -
                    tmp.close
         | 
| 78 | 
            -
             | 
| 79 | 
            -
                    cmd = "tar xzf '#{tmp.path}' cookbooks"
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                    unless system(cmd)
         | 
| 82 | 
            -
                      raise EY::Error, "Could not unarchive recipes.\nCommand `#{cmd}` exited with an error."
         | 
| 83 | 
            -
                    end
         | 
| 84 | 
            -
                  end
         | 
| 85 | 
            -
             | 
| 86 | 
            -
                  def upload_recipes_at_path(recipes_path)
         | 
| 87 | 
            -
                    recipes_path = Pathname.new(recipes_path)
         | 
| 88 | 
            -
                    if recipes_path.exist?
         | 
| 89 | 
            -
                      upload_recipes recipes_path.open('rb')
         | 
| 90 | 
            -
                    else
         | 
| 91 | 
            -
                      raise EY::Error, "Recipes file not found: #{recipes_path}"
         | 
| 92 | 
            -
                    end
         | 
| 93 | 
            -
                  end
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                  def tar_and_upload_recipes_in_cookbooks_dir
         | 
| 96 | 
            -
                    require 'tempfile'
         | 
| 97 | 
            -
                    unless File.exist?("cookbooks")
         | 
| 98 | 
            -
                      raise EY::Error, "Could not find chef recipes. Please run from the root of your recipes repo."
         | 
| 99 | 
            -
                    end
         | 
| 100 | 
            -
             | 
| 101 | 
            -
                    recipes_file = Tempfile.new("recipes")
         | 
| 102 | 
            -
                    cmd = "tar czf '#{recipes_file.path}' cookbooks/"
         | 
| 103 | 
            -
             | 
| 104 | 
            -
                    unless system(cmd)
         | 
| 105 | 
            -
                      raise EY::Error, "Could not archive recipes.\nCommand `#{cmd}` exited with an error."
         | 
| 106 | 
            -
                    end
         | 
| 107 | 
            -
             | 
| 108 | 
            -
                    upload_recipes(recipes_file)
         | 
| 109 | 
            -
                  end
         | 
| 110 | 
            -
             | 
| 111 | 
            -
                  def upload_recipes(file_to_upload)
         | 
| 112 | 
            -
                    api.request("/environments/#{id}/recipes", {
         | 
| 113 | 
            -
                      :method => :post,
         | 
| 114 | 
            -
                      :params => {:file => file_to_upload}
         | 
| 115 | 
            -
                    })
         | 
| 116 | 
            -
                  end
         | 
| 117 | 
            -
             | 
| 118 | 
            -
                  # If force_ref is a string, use it as the ref, otherwise use it as a boolean.
         | 
| 119 | 
            -
                  def resolve_branch(ref, force_ref=false)
         | 
| 120 | 
            -
                    if String === force_ref
         | 
| 121 | 
            -
                      ref, force_ref = force_ref, true
         | 
| 122 | 
            -
                    end
         | 
| 123 | 
            -
             | 
| 124 | 
            -
                    if !ref
         | 
| 125 | 
            -
                      default_branch
         | 
| 126 | 
            -
                    elsif force_ref || !default_branch || ref == default_branch
         | 
| 127 | 
            -
                      ref
         | 
| 128 | 
            -
                    else
         | 
| 129 | 
            -
                      raise BranchMismatchError.new(default_branch, ref)
         | 
| 130 | 
            -
                    end
         | 
| 131 | 
            -
                  end
         | 
| 132 | 
            -
             | 
| 133 | 
            -
                  def configuration
         | 
| 134 | 
            -
                    EY.config.environments[self.name] || {}
         | 
| 135 | 
            -
                  end
         | 
| 136 | 
            -
                  alias_method :config, :configuration
         | 
| 137 | 
            -
             | 
| 138 | 
            -
                  def default_branch
         | 
| 139 | 
            -
                    EY.config.default_branch(name)
         | 
| 140 | 
            -
                  end
         | 
| 141 | 
            -
             | 
| 142 | 
            -
                  def shorten_name_for(app)
         | 
| 143 | 
            -
                    name.gsub(/^#{Regexp.quote(app.name)}_/, '')
         | 
| 144 | 
            -
                  end
         | 
| 145 | 
            -
             | 
| 146 | 
            -
                  def launch
         | 
| 147 | 
            -
                    Launchy.open(app_master!.hostname_url)
         | 
| 148 | 
            -
                  end
         | 
| 149 | 
            -
             | 
| 150 | 
            -
                  def migration_command(app, deploy_options)
         | 
| 151 | 
            -
                    # regarding deploy_options['migrate']:
         | 
| 152 | 
            -
                    #
         | 
| 153 | 
            -
                    # missing means migrate how the yaml file says to
         | 
| 154 | 
            -
                    # nil means don't migrate
         | 
| 155 | 
            -
                    # true means migrate w/custom command (if present) or default
         | 
| 156 | 
            -
                    # a string means migrate with this specific command
         | 
| 157 | 
            -
                    return nil if no_migrate?(deploy_options)
         | 
| 158 | 
            -
                    command = migration_command_from_command_line(deploy_options)
         | 
| 159 | 
            -
                    unless command
         | 
| 160 | 
            -
                      return nil if no_migrate?(config)
         | 
| 161 | 
            -
                      command = migration_command_from_config
         | 
| 162 | 
            -
                    end
         | 
| 163 | 
            -
                    command = migration_command_from_environment(app) unless command
         | 
| 164 | 
            -
                    command
         | 
| 165 | 
            -
                  end
         | 
| 166 | 
            -
             | 
| 167 | 
            -
                  private
         | 
| 168 | 
            -
             | 
| 169 | 
            -
                  def no_migrate?(hash)
         | 
| 170 | 
            -
                    hash.key?('migrate') && hash['migrate'] == false
         | 
| 171 | 
            -
                  end
         | 
| 172 | 
            -
             | 
| 173 | 
            -
                  def migration_command_from_config
         | 
| 174 | 
            -
                    config['migration_command'] if config['migrate'] || config['migration_command']
         | 
| 175 | 
            -
                  end
         | 
| 176 | 
            -
             | 
| 177 | 
            -
                  def migration_command_from_command_line(deploy_options)
         | 
| 178 | 
            -
                    if migrate = deploy_options['migrate']
         | 
| 179 | 
            -
                      migrate.respond_to?(:to_str) ? migrate.to_str : (config['migration_command'] || default_migration_command)
         | 
| 180 | 
            -
                    end
         | 
| 181 | 
            -
                  end
         | 
| 182 | 
            -
             | 
| 183 | 
            -
                  def migration_command_from_environment(app)
         | 
| 184 | 
            -
                    if deploy_config = deployment_configurations[app.name]
         | 
| 185 | 
            -
                      deploy_config['migrate']['command'] if deploy_config['migrate']['perform']
         | 
| 186 | 
            -
                    end
         | 
| 187 | 
            -
                  end
         | 
| 188 | 
            -
             | 
| 189 | 
            -
                  def default_migration_command
         | 
| 190 | 
            -
                    'rake db:migrate'
         | 
| 191 | 
            -
                  end
         | 
| 192 | 
            -
                end
         | 
| 193 | 
            -
              end
         | 
| 194 | 
            -
            end
         | 
| @@ -1,166 +0,0 @@ | |
| 1 | 
            -
            require 'escape'
         | 
| 2 | 
            -
            require 'net/ssh'
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            module EY
         | 
| 5 | 
            -
              module Model
         | 
| 6 | 
            -
                class Instance < ApiStruct.new(:id, :role, :name, :status, :amazon_id, :public_hostname, :environment)
         | 
| 7 | 
            -
                  alias :hostname :public_hostname
         | 
| 8 | 
            -
             | 
| 9 | 
            -
                  def adapter(app, verbose)
         | 
| 10 | 
            -
                    require 'engineyard-serverside-adapter'
         | 
| 11 | 
            -
                    EY::Serverside::Adapter.new("/usr/local/ey_resin/ruby/bin") do |args|
         | 
| 12 | 
            -
                      args.app           = app.name
         | 
| 13 | 
            -
                      args.repo          = app.repository_uri
         | 
| 14 | 
            -
                      args.instances     = instances_data
         | 
| 15 | 
            -
                      args.verbose       = verbose || ENV['DEBUG']
         | 
| 16 | 
            -
                      args.stack         = environment.app_server_stack_name
         | 
| 17 | 
            -
                      args.framework_env = environment.framework_env
         | 
| 18 | 
            -
                    end
         | 
| 19 | 
            -
                  end
         | 
| 20 | 
            -
                  private :adapter
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                  def deploy(app, ref, migration_command=nil, extra_configuration=nil, verbose=false)
         | 
| 23 | 
            -
                    successful, output = false, "Deploy initiated.\n"
         | 
| 24 | 
            -
                    deployment = Deployment.started(environment, app, ref, migration_command)
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                    deploy_command = adapter(app, verbose).deploy do |args|
         | 
| 27 | 
            -
                      args.config  = extra_configuration if extra_configuration
         | 
| 28 | 
            -
                      args.migrate = migration_command if migration_command
         | 
| 29 | 
            -
                      args.ref     = deployment.resolved_ref
         | 
| 30 | 
            -
                    end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                    successful = invoke(deploy_command) { |chunk| output << chunk }
         | 
| 33 | 
            -
                  rescue Interrupt
         | 
| 34 | 
            -
                    output << "Interrupted. Deployment halted.\n"
         | 
| 35 | 
            -
                    EY.ui.warn "Interrupted."
         | 
| 36 | 
            -
                    EY.ui.warn "Recording canceled deployment and exiting..."
         | 
| 37 | 
            -
                    EY.ui.warn "WARNING: Interrupting again may result in a never-finished deployment in the deployment history on EY Cloud."
         | 
| 38 | 
            -
                    raise
         | 
| 39 | 
            -
                  rescue StandardError => e
         | 
| 40 | 
            -
                    EY.ui.info "Error encountered during deploy."
         | 
| 41 | 
            -
                    output <<  "Error encountered during deploy.\n#{e.class} #{e}\n"
         | 
| 42 | 
            -
                    raise
         | 
| 43 | 
            -
                  ensure
         | 
| 44 | 
            -
                    if deployment
         | 
| 45 | 
            -
                      deployment.finished(successful, output)
         | 
| 46 | 
            -
                      EY.ui.info "#{successful ? 'Successful' : 'Failed'} deployment recorded in EY Cloud"
         | 
| 47 | 
            -
                    end
         | 
| 48 | 
            -
                  end
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                  def rollback(app, extra_configuration=nil, verbose=false)
         | 
| 51 | 
            -
                    rollback = adapter(app, verbose).rollback do |args|
         | 
| 52 | 
            -
                      args.config = extra_configuration if extra_configuration
         | 
| 53 | 
            -
                    end
         | 
| 54 | 
            -
                    invoke rollback
         | 
| 55 | 
            -
                  end
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                  def put_up_maintenance_page(app, verbose=false)
         | 
| 58 | 
            -
                    invoke adapter(app, verbose).enable_maintenance_page
         | 
| 59 | 
            -
                  end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                  def take_down_maintenance_page(app, verbose=false)
         | 
| 62 | 
            -
                    invoke adapter(app, verbose).disable_maintenance_page
         | 
| 63 | 
            -
                  end
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                  def has_app_code?
         | 
| 66 | 
            -
                    !["db_master", "db_slave"].include?(role.to_s)
         | 
| 67 | 
            -
                  end
         | 
| 68 | 
            -
             | 
| 69 | 
            -
                  def hostname_url
         | 
| 70 | 
            -
                    "http://#{hostname}" if hostname
         | 
| 71 | 
            -
                  end
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                protected
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                  def engineyard_serverside_hostname
         | 
| 76 | 
            -
                    # If we tell engineyard-serverside to use 'localhost', it'll run
         | 
| 77 | 
            -
                    # commands on the instance directly (#system). If we give it the
         | 
| 78 | 
            -
                    # instance's actual hostname, it'll SSH to itself.
         | 
| 79 | 
            -
                    #
         | 
| 80 | 
            -
                    # Using 'localhost' instead of its EC2 hostname speeds up
         | 
| 81 | 
            -
                    # deploys on solos and single-app-server clusters significantly.
         | 
| 82 | 
            -
                    app_master? ? 'localhost' : hostname
         | 
| 83 | 
            -
                  end
         | 
| 84 | 
            -
             | 
| 85 | 
            -
                private
         | 
| 86 | 
            -
             | 
| 87 | 
            -
                  def ssh(remote_command, verbose, &block)
         | 
| 88 | 
            -
                    raise(ArgumentError, "Block required!") unless block
         | 
| 89 | 
            -
             | 
| 90 | 
            -
                    exit_code = nil
         | 
| 91 | 
            -
                    cmd = Escape.shell_command(['bash', '-lc', remote_command])
         | 
| 92 | 
            -
                    block.call("Running command on #{environment.username}@#{hostname}.\n")
         | 
| 93 | 
            -
                    if cmd.respond_to?(:encoding) && cmd.respond_to?(:force_encoding)
         | 
| 94 | 
            -
                      block.call("Encoding: #{cmd.encoding.name}") if verbose
         | 
| 95 | 
            -
                      cmd.force_encoding('binary')
         | 
| 96 | 
            -
                      block.call(" => #{cmd.encoding.name}; __ENCODING__: #{__ENCODING__.name}; LANG: #{ENV['LANG']}; LC_CTYPE: #{ENV['LC_CTYPE']}\n") if verbose
         | 
| 97 | 
            -
                    end
         | 
| 98 | 
            -
                    EY.ui.debug(cmd)
         | 
| 99 | 
            -
                    block.call("Command: #{cmd}\n") if verbose
         | 
| 100 | 
            -
                    if ENV["NO_SSH"]
         | 
| 101 | 
            -
                      block.call("NO_SSH is set. No output.")
         | 
| 102 | 
            -
                      true
         | 
| 103 | 
            -
                    else
         | 
| 104 | 
            -
                      begin
         | 
| 105 | 
            -
                        options_for_ssh = {:paranoid => false}
         | 
| 106 | 
            -
                        options_for_ssh[:verbose] = ENV["DEBUG"].downcase.to_sym if ENV["DEBUG"]
         | 
| 107 | 
            -
                        Net::SSH.start(hostname, environment.username, options_for_ssh) do |net_ssh|
         | 
| 108 | 
            -
                          net_ssh.open_channel do |channel|
         | 
| 109 | 
            -
                            channel.exec cmd do |_, success|
         | 
| 110 | 
            -
                              unless success
         | 
| 111 | 
            -
                                block.call "Remote command execution failed"
         | 
| 112 | 
            -
                                return false
         | 
| 113 | 
            -
                              end
         | 
| 114 | 
            -
             | 
| 115 | 
            -
                              channel.on_data do |_, data|
         | 
| 116 | 
            -
                                block.call data
         | 
| 117 | 
            -
                              end
         | 
| 118 | 
            -
             | 
| 119 | 
            -
                              channel.on_extended_data do |_, _, data|
         | 
| 120 | 
            -
                                block.call data
         | 
| 121 | 
            -
                              end
         | 
| 122 | 
            -
             | 
| 123 | 
            -
                              channel.on_request("exit-status") do |_, data|
         | 
| 124 | 
            -
                                exit_code = data.read_long
         | 
| 125 | 
            -
                              end
         | 
| 126 | 
            -
             | 
| 127 | 
            -
                              channel.on_request("exit-signal") do |_, data|
         | 
| 128 | 
            -
                                exit_code = 255
         | 
| 129 | 
            -
                              end
         | 
| 130 | 
            -
                            end
         | 
| 131 | 
            -
                          end
         | 
| 132 | 
            -
             | 
| 133 | 
            -
                          net_ssh.loop
         | 
| 134 | 
            -
                        end
         | 
| 135 | 
            -
                        exit_code.zero?
         | 
| 136 | 
            -
                      rescue Net::SSH::AuthenticationFailed
         | 
| 137 | 
            -
                        raise EY::Error, "Authentication Failed: Please add your environment's ssh key with: ssh-add path/to/key"
         | 
| 138 | 
            -
                      end
         | 
| 139 | 
            -
                    end
         | 
| 140 | 
            -
                  end
         | 
| 141 | 
            -
             | 
| 142 | 
            -
                  def invoke(action, &block)
         | 
| 143 | 
            -
                    action.call do |cmd|
         | 
| 144 | 
            -
                      ssh cmd, action.verbose do |chunk|
         | 
| 145 | 
            -
                        $stdout << chunk
         | 
| 146 | 
            -
                        block.call(chunk) if block
         | 
| 147 | 
            -
                      end
         | 
| 148 | 
            -
                    end
         | 
| 149 | 
            -
                  end
         | 
| 150 | 
            -
             | 
| 151 | 
            -
                  def instances_data
         | 
| 152 | 
            -
                    environment.instances.select { |inst| inst.has_app_code? }.map do |i|
         | 
| 153 | 
            -
                      {
         | 
| 154 | 
            -
                        :hostname => i.engineyard_serverside_hostname,
         | 
| 155 | 
            -
                        :roles    => [i.role],
         | 
| 156 | 
            -
                        :name     => i.name,
         | 
| 157 | 
            -
                      }
         | 
| 158 | 
            -
                    end
         | 
| 159 | 
            -
                  end
         | 
| 160 | 
            -
             | 
| 161 | 
            -
                  def app_master?
         | 
| 162 | 
            -
                    environment.app_master == self
         | 
| 163 | 
            -
                  end
         | 
| 164 | 
            -
                end
         | 
| 165 | 
            -
              end
         | 
| 166 | 
            -
            end
         |