engineyard 0.3.1 → 0.3.2
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/lib/engineyard.rb +2 -2
- data/lib/engineyard/api.rb +19 -0
- data/lib/engineyard/cli.rb +24 -12
- data/lib/engineyard/cli/action/deploy.rb +112 -0
- data/lib/engineyard/cli/api.rb +14 -1
- data/lib/engineyard/error.rb +27 -0
- data/lib/engineyard/model.rb +9 -0
- data/lib/engineyard/{account → model}/api_struct.rb +8 -3
- data/lib/engineyard/{account → model}/app.rb +3 -3
- data/lib/engineyard/{account → model}/environment.rb +14 -7
- data/lib/engineyard/model/instance.rb +91 -0
- data/lib/engineyard/{account → model}/log.rb +1 -1
- data/lib/engineyard/repo.rb +3 -3
- data/spec/engineyard/{account → model}/api_struct_spec.rb +11 -7
- data/spec/engineyard/model/environment_spec.rb +45 -0
- data/spec/engineyard/model/instance_spec.rb +70 -0
- data/spec/engineyard/repo_spec.rb +17 -14
- data/spec/ey/deploy_spec.rb +95 -45
- data/spec/ey/list_environments_spec.rb +11 -1
- data/spec/ey/logs_spec.rb +18 -0
- data/spec/ey/rebuild_spec.rb +21 -4
- data/spec/ey/ssh_spec.rb +28 -3
- data/spec/spec_helper.rb +37 -12
- data/spec/support/fake_awsm.ru +139 -4
- data/spec/support/helpers.rb +19 -8
- metadata +31 -20
- data/lib/engineyard/account.rb +0 -63
- data/lib/engineyard/account/app_master.rb +0 -6
- data/lib/engineyard/account/instance.rb +0 -6
- data/lib/engineyard/action/deploy.rb +0 -138
- data/lib/engineyard/action/rebuild.rb +0 -31
- data/lib/engineyard/action/util.rb +0 -19
- data/spec/engineyard/account/environment_spec.rb +0 -20
- data/spec/engineyard/account_spec.rb +0 -18
data/lib/engineyard/account.rb
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
require 'engineyard/account/api_struct'
|
2
|
-
require 'engineyard/account/app'
|
3
|
-
require 'engineyard/account/app_master'
|
4
|
-
require 'engineyard/account/environment'
|
5
|
-
require 'engineyard/account/log'
|
6
|
-
require 'engineyard/account/instance'
|
7
|
-
|
8
|
-
module EY
|
9
|
-
class Account
|
10
|
-
|
11
|
-
def initialize(api)
|
12
|
-
@api = api
|
13
|
-
end
|
14
|
-
|
15
|
-
def environments
|
16
|
-
@environments ||= begin
|
17
|
-
data = @api.request('/environments')["environments"]
|
18
|
-
Environment.from_array(data, self)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def apps
|
23
|
-
@apps ||= App.from_array(@api.request('/apps')["apps"], self)
|
24
|
-
end
|
25
|
-
|
26
|
-
def environment_named(name)
|
27
|
-
environments.find{|e| e.name == name }
|
28
|
-
end
|
29
|
-
|
30
|
-
def logs_for(env)
|
31
|
-
data = @api.request("/environments/#{env.id}/logs")["logs"]
|
32
|
-
Log.from_array(data)
|
33
|
-
end
|
34
|
-
|
35
|
-
def instances_for(env)
|
36
|
-
@instances ||= begin
|
37
|
-
data = @api.request("/environments/#{env.id}/instances")["instances"]
|
38
|
-
Instance.from_array(data)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def upload_recipes_for(env)
|
43
|
-
@api.request("/environments/#{env.id}/recipes",
|
44
|
-
:method => :post,
|
45
|
-
:params => {:file => env.recipe_file}
|
46
|
-
)
|
47
|
-
end
|
48
|
-
|
49
|
-
def rebuild(env)
|
50
|
-
@api.request("/environments/#{env.id}/rebuild",
|
51
|
-
:method => :put)
|
52
|
-
end
|
53
|
-
|
54
|
-
def app_named(name)
|
55
|
-
apps.find{|a| a.name == name }
|
56
|
-
end
|
57
|
-
|
58
|
-
def app_for_repo(repo)
|
59
|
-
apps.find{|a| repo.urls.include?(a.repository_uri) }
|
60
|
-
end
|
61
|
-
|
62
|
-
end # Account
|
63
|
-
end # EY
|
@@ -1,138 +0,0 @@
|
|
1
|
-
require 'engineyard/action/util'
|
2
|
-
|
3
|
-
module EY
|
4
|
-
module Action
|
5
|
-
class Deploy
|
6
|
-
extend Util
|
7
|
-
|
8
|
-
EYSD_VERSION = "~>0.3.1"
|
9
|
-
|
10
|
-
def self.call(env_name, branch, options)
|
11
|
-
env_name ||= EY.config.default_environment
|
12
|
-
|
13
|
-
app = fetch_app
|
14
|
-
env = fetch_environment(env_name, app)
|
15
|
-
branch = fetch_branch(env.name, branch, options[:force])
|
16
|
-
|
17
|
-
running = env.app_master && env.app_master.status == "running"
|
18
|
-
raise EnvironmentError, "No running instances for environment #{env.name}\nStart one at #{EY.config.endpoint}" unless running
|
19
|
-
|
20
|
-
hostname = env.app_master.public_hostname
|
21
|
-
username = env.username
|
22
|
-
|
23
|
-
EY.ui.info "Connecting to the server..."
|
24
|
-
ensure_eysd_present(hostname, username, options[:install_eysd])
|
25
|
-
|
26
|
-
deploy_cmd = "#{eysd_path} deploy --app #{app.name} --branch #{branch}"
|
27
|
-
if env.config
|
28
|
-
escaped_config_option = env.config.to_json.gsub(/"/, "\\\"")
|
29
|
-
deploy_cmd << " --config '#{escaped_config_option}'"
|
30
|
-
end
|
31
|
-
|
32
|
-
if options['migrate']
|
33
|
-
deploy_cmd << " --migrate='#{options[:migrate]}'"
|
34
|
-
end
|
35
|
-
|
36
|
-
EY.ui.info "Running deploy on server..."
|
37
|
-
deployed = ssh_to(hostname, deploy_cmd, username)
|
38
|
-
|
39
|
-
if deployed
|
40
|
-
EY.ui.info "Deploy complete"
|
41
|
-
else
|
42
|
-
raise EY::Error, "Deploy failed"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def self.fetch_app
|
49
|
-
app = account.app_for_repo(repo)
|
50
|
-
raise NoAppError.new(repo) unless app
|
51
|
-
app
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.fetch_environment(env_name, app)
|
55
|
-
# if the name's not specified and there's not exactly one
|
56
|
-
# environment, we can't figure out which environment to deploy
|
57
|
-
raise DeployArgumentError if !env_name && app.environments.size != 1
|
58
|
-
|
59
|
-
env = if env_name
|
60
|
-
# environment names are unique per-customer, so
|
61
|
-
# there's no danger of finding two here
|
62
|
-
app.environments.find{|e| e.name == env_name }
|
63
|
-
else
|
64
|
-
app.environments.first
|
65
|
-
end
|
66
|
-
|
67
|
-
# the environment exists, but doesn't have this app
|
68
|
-
if !env && account.environment_named(env_name)
|
69
|
-
raise EnvironmentError, "Environment '#{env_name}' doesn't run this application\nYou can add it at #{EY.config.endpoint}"
|
70
|
-
end
|
71
|
-
|
72
|
-
if !env
|
73
|
-
raise NoEnvironmentError.new(env_name)
|
74
|
-
end
|
75
|
-
|
76
|
-
env
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.fetch_branch(env_name, user_specified_branch, force)
|
80
|
-
default_branch = EY.config.default_branch(env_name)
|
81
|
-
|
82
|
-
branch = if user_specified_branch
|
83
|
-
if default_branch && (user_specified_branch != default_branch) && !force
|
84
|
-
raise BranchMismatch.new(default_branch, user_specified_branch)
|
85
|
-
end
|
86
|
-
user_specified_branch
|
87
|
-
else
|
88
|
-
default_branch || repo.current_branch
|
89
|
-
end
|
90
|
-
|
91
|
-
raise DeployArgumentError unless branch
|
92
|
-
branch
|
93
|
-
end
|
94
|
-
|
95
|
-
def self.ensure_eysd_present(hostname, username, install_eysd)
|
96
|
-
ssh_to(hostname, "#{eysd_path} check '#{EY::VERSION}' '#{EYSD_VERSION}'", username, false)
|
97
|
-
case $?.exitstatus
|
98
|
-
when 255
|
99
|
-
raise EnvironmentError, "SSH connection to #{hostname} failed"
|
100
|
-
when 127
|
101
|
-
EY.ui.warn "Server does not have ey-deploy gem installed"
|
102
|
-
eysd_installed = false
|
103
|
-
when 0
|
104
|
-
eysd_installed = true
|
105
|
-
else
|
106
|
-
raise EnvironmentError, "ey-deploy version not compatible"
|
107
|
-
end
|
108
|
-
|
109
|
-
if !eysd_installed || install_eysd
|
110
|
-
EY.ui.info "Installing ey-deploy gem..."
|
111
|
-
ssh_to(hostname,
|
112
|
-
"sudo #{gem_path} install ey-deploy -v '#{EYSD_VERSION}'",
|
113
|
-
username)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def self.eysd_path
|
118
|
-
"/usr/local/ey_resin/ruby/bin/eysd"
|
119
|
-
end
|
120
|
-
|
121
|
-
def self.gem_path
|
122
|
-
"/usr/local/ey_resin/ruby/bin/gem"
|
123
|
-
end
|
124
|
-
|
125
|
-
def self.ssh_to(hostname, remote_cmd, user, output = true)
|
126
|
-
cmd = %{ssh -o StrictHostKeyChecking=no -q #{user}@#{hostname} "#{remote_cmd}"}
|
127
|
-
cmd << %{ &> /dev/null} unless output
|
128
|
-
output ? puts(cmd) : EY.ui.debug(cmd)
|
129
|
-
unless ENV["NO_SSH"]
|
130
|
-
system cmd
|
131
|
-
else
|
132
|
-
true
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'engineyard/action/util'
|
2
|
-
|
3
|
-
module EY
|
4
|
-
module Action
|
5
|
-
class Rebuild
|
6
|
-
extend Util
|
7
|
-
|
8
|
-
def self.call(name)
|
9
|
-
env = fetch_environment_by_name(name) || fetch_environment_from_app
|
10
|
-
EY.ui.debug("Rebuilding #{env.name}")
|
11
|
-
env.rebuild
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
def self.fetch_environment_by_name(name)
|
16
|
-
if name
|
17
|
-
env = account.environment_named(name)
|
18
|
-
return env if env
|
19
|
-
raise NoEnvironmentError.new(name)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.fetch_environment_from_app
|
24
|
-
repo = Repo.new
|
25
|
-
app = account.app_for_repo(repo) or raise NoAppError.new(repo)
|
26
|
-
env = app.one_and_only_environment or raise EnvironmentError, "Unable to determine a single environment for the current application (found #{app.environments.size} environments)"
|
27
|
-
env
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module EY
|
2
|
-
module Action
|
3
|
-
module Util
|
4
|
-
|
5
|
-
protected
|
6
|
-
|
7
|
-
def account
|
8
|
-
# XXX it stinks that we have to use EY::CLI::API explicitly
|
9
|
-
# here; I don't want to have this lateral Action --> CLI reference
|
10
|
-
@account ||= EY::Account.new(EY::CLI::API.new)
|
11
|
-
end
|
12
|
-
|
13
|
-
def repo
|
14
|
-
@repo ||= EY::Repo.new
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe "EY::Account::Environment#rebuild" do
|
4
|
-
it_should_behave_like "it has an account"
|
5
|
-
|
6
|
-
it "hits the rebuild action in the API" do
|
7
|
-
env = EY::Account::Environment.from_hash({
|
8
|
-
"id" => 46534,
|
9
|
-
"account" => @account
|
10
|
-
})
|
11
|
-
|
12
|
-
FakeWeb.register_uri(:put,
|
13
|
-
"https://cloud.engineyard.com/api/v2/environments/#{env.id}/rebuild",
|
14
|
-
:body => {}.to_json)
|
15
|
-
|
16
|
-
env.rebuild
|
17
|
-
|
18
|
-
FakeWeb.should have_requested(:put, "https://cloud.engineyard.com/api/v2/environments/#{env.id}/rebuild")
|
19
|
-
end
|
20
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe EY::Account do
|
4
|
-
it_should_behave_like "it has an account"
|
5
|
-
|
6
|
-
it "returns instances" do
|
7
|
-
@env = EY::Account::Environment.from_hash({
|
8
|
-
"id" => 1, "name" => "banana", "instances_count" => 3,
|
9
|
-
"ssh_username" => "monkey", "apps" => {}, "account" => @account
|
10
|
-
})
|
11
|
-
@instance_data = {"id" => "1", "role" => "app_master",
|
12
|
-
"amazon_id" => "amazon_1", "public_hostname" => "banana_master"}
|
13
|
-
FakeWeb.register_uri(:get, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/instances",
|
14
|
-
:body => {"instances" => [@instance_data]}.to_json)
|
15
|
-
|
16
|
-
@account.instances_for(@env).first.should == EY::Account::Instance.from_hash(@instance_data)
|
17
|
-
end
|
18
|
-
end
|