engineyard-serverside 2.0.0.pre3 → 2.0.0.pre4
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-serverside/cli.rb +46 -153
- data/lib/engineyard-serverside/cli_helpers.rb +53 -0
- data/lib/engineyard-serverside/configuration.rb +131 -161
- data/lib/engineyard-serverside/deploy.rb +69 -37
- data/lib/engineyard-serverside/deploy_hook.rb +31 -6
- data/lib/engineyard-serverside/paths.rb +106 -0
- data/lib/engineyard-serverside/server.rb +7 -59
- data/lib/engineyard-serverside/servers.rb +93 -0
- data/lib/engineyard-serverside/task.rb +4 -3
- data/lib/engineyard-serverside/version.rb +1 -1
- data/spec/basic_deploy_spec.rb +2 -2
- data/spec/bundler_deploy_spec.rb +6 -6
- data/spec/configuration_spec.rb +2 -1
- data/spec/custom_deploy_spec.rb +9 -4
- data/spec/deploy_hook_spec.rb +31 -15
- data/spec/ey_yml_customized_deploy_spec.rb +17 -15
- data/spec/fixtures/repos/assets_disabled/app/assets/empty +0 -0
- data/spec/fixtures/repos/assets_disabled_in_ey_yml/app/assets/empty +0 -0
- data/spec/fixtures/repos/assets_enabled/app/assets/empty +0 -0
- data/spec/fixtures/repos/assets_in_hook/app/assets/empty +0 -0
- data/spec/rails31_deploy_spec.rb +8 -8
- data/spec/restart_spec.rb +3 -2
- data/spec/rollback_spec.rb +61 -0
- data/spec/server_spec.rb +44 -50
- data/spec/spec_helper.rb +19 -12
- metadata +17 -4
@@ -2,11 +2,13 @@ require 'thor'
|
|
2
2
|
require 'pathname'
|
3
3
|
require 'engineyard-serverside/deploy'
|
4
4
|
require 'engineyard-serverside/shell'
|
5
|
-
require 'engineyard-serverside/
|
5
|
+
require 'engineyard-serverside/servers'
|
6
|
+
require 'engineyard-serverside/cli_helpers'
|
6
7
|
|
7
8
|
module EY
|
8
9
|
module Serverside
|
9
10
|
class CLI < Thor
|
11
|
+
extend CLIHelpers
|
10
12
|
|
11
13
|
method_option :migrate, :type => :string,
|
12
14
|
:desc => "Run migrations with this deploy",
|
@@ -19,63 +21,20 @@ module EY
|
|
19
21
|
method_option :repo, :type => :string,
|
20
22
|
:desc => "Remote repo to deploy",
|
21
23
|
:aliases => ["-r"]
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
method_option :environment_name,:type => :string,
|
29
|
-
:required => true,
|
30
|
-
:desc => "Environment name"
|
31
|
-
|
32
|
-
method_option :account_name, :type => :string,
|
33
|
-
:required => true,
|
34
|
-
:desc => "Account name"
|
35
|
-
|
36
|
-
method_option :framework_env, :type => :string,
|
37
|
-
:desc => "Ruby web framework environment",
|
38
|
-
:aliases => ["-e"]
|
39
|
-
|
40
|
-
method_option :config, :type => :string,
|
41
|
-
:desc => "Additional configuration"
|
42
|
-
|
43
|
-
method_option :stack, :type => :string,
|
44
|
-
:desc => "Web stack (so we can restart it correctly)"
|
45
|
-
|
46
|
-
method_option :instances, :type => :array,
|
47
|
-
:desc => "Hostnames of instances to deploy to, e.g. --instances localhost app1 app2"
|
48
|
-
|
49
|
-
method_option :instance_roles, :type => :hash,
|
50
|
-
:default => {},
|
51
|
-
:desc => "Roles of instances, keyed on hostname, comma-separated. e.g. instance1:app_master,etc instance2:db,memcached ..."
|
52
|
-
|
53
|
-
method_option :instance_names, :type => :hash,
|
54
|
-
:default => {},
|
55
|
-
:desc => "Instance names, keyed on hostname. e.g. instance1:name1 instance2:name2"
|
56
|
-
|
57
|
-
method_option :verbose, :type => :boolean,
|
58
|
-
:desc => "Verbose output",
|
59
|
-
:aliases => ["-v"]
|
24
|
+
account_app_env_options
|
25
|
+
config_option
|
26
|
+
framework_env_option
|
27
|
+
instances_options
|
28
|
+
stack_option
|
29
|
+
verbose_option
|
60
30
|
|
61
31
|
desc "deploy", "Deploy code from /data/<app>"
|
62
32
|
def deploy(default_task=:deploy)
|
63
|
-
config, shell = init_and_propagate(options,
|
64
|
-
EY::Serverside::Deploy.new(config, shell).send(default_task)
|
33
|
+
servers, config, shell = init_and_propagate(options, default_task.to_s)
|
34
|
+
EY::Serverside::Deploy.new(servers, config, shell).send(default_task)
|
65
35
|
end
|
66
36
|
|
67
|
-
method_option :app, :type => :string,
|
68
|
-
:required => true,
|
69
|
-
:desc => "Which application's hooks to run",
|
70
|
-
:aliases => ["-a"]
|
71
|
-
|
72
|
-
method_option :environment_name, :type => :string,
|
73
|
-
:required => true,
|
74
|
-
:desc => "Environment name"
|
75
37
|
|
76
|
-
method_option :account_name, :type => :string,
|
77
|
-
:required => true,
|
78
|
-
:desc => "Account name"
|
79
38
|
|
80
39
|
method_option :release_path, :type => :string,
|
81
40
|
:desc => "Value for #release_path in hooks (mostly for internal coordination)",
|
@@ -84,126 +43,60 @@ module EY
|
|
84
43
|
method_option :current_roles, :type => :array,
|
85
44
|
:desc => "Value for #current_roles in hooks"
|
86
45
|
|
87
|
-
method_option :framework_env, :type => :string,
|
88
|
-
:required => true,
|
89
|
-
:desc => "Ruby web framework environment",
|
90
|
-
:aliases => ["-e"]
|
91
|
-
|
92
|
-
method_option :config, :type => :string,
|
93
|
-
:desc => "Additional configuration"
|
94
|
-
|
95
46
|
method_option :current_name, :type => :string,
|
96
47
|
:desc => "Value for #current_name in hooks"
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
48
|
+
account_app_env_options
|
49
|
+
config_option
|
50
|
+
framework_env_option
|
51
|
+
verbose_option
|
102
52
|
desc "hook [NAME]", "Run a particular deploy hook"
|
103
53
|
def hook(hook_name)
|
104
54
|
config, shell = init(options, "hook-#{hook_name}")
|
105
|
-
EY::Serverside::DeployHook.new(config, shell).
|
55
|
+
EY::Serverside::DeployHook.new(config, shell, hook_name).call
|
106
56
|
end
|
107
57
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
method_option :environment_name,:type => :string,
|
115
|
-
:required => true,
|
116
|
-
:desc => "Environment name"
|
117
|
-
|
118
|
-
method_option :account_name, :type => :string,
|
119
|
-
:required => true,
|
120
|
-
:desc => "Account name"
|
121
|
-
|
122
|
-
method_option :framework_env, :type => :string,
|
123
|
-
:required => true,
|
124
|
-
:desc => "Ruby web framework environment",
|
125
|
-
:aliases => ["-e"]
|
126
|
-
|
127
|
-
method_option :stack, :type => :string,
|
128
|
-
:desc => "Web stack (so we can restart it correctly)"
|
129
|
-
|
130
|
-
method_option :instances, :type => :array,
|
131
|
-
:desc => "Hostnames of instances to deploy to, e.g. --instances localhost app1 app2"
|
132
|
-
|
133
|
-
method_option :instance_roles, :type => :hash,
|
134
|
-
:default => {},
|
135
|
-
:desc => "Roles of instances, keyed on hostname, comma-separated. e.g. instance1:app_master,etc instance2:db,memcached ..."
|
136
|
-
|
137
|
-
method_option :instance_names, :type => :hash,
|
138
|
-
:default => {},
|
139
|
-
:desc => "Instance names, keyed on hostname. e.g. instance1:name1 instance2:name2"
|
140
|
-
|
141
|
-
method_option :verbose, :type => :boolean,
|
142
|
-
:desc => "Verbose output",
|
143
|
-
:aliases => ["-v"]
|
58
|
+
account_app_env_options
|
59
|
+
config_option
|
60
|
+
framework_env_option
|
61
|
+
instances_options
|
62
|
+
stack_option
|
63
|
+
verbose_option
|
144
64
|
desc "integrate", "Integrate other instances into this cluster"
|
145
65
|
def integrate
|
146
|
-
|
147
66
|
app_dir = Pathname.new "/data/#{options[:app]}"
|
148
|
-
current_app_dir = app_dir
|
67
|
+
current_app_dir = app_dir.join("current")
|
149
68
|
|
150
69
|
# so that we deploy to the same place there that we have here
|
151
70
|
integrate_options = options.dup
|
152
71
|
integrate_options[:release_path] = current_app_dir.realpath.to_s
|
153
72
|
|
154
73
|
# we have to deploy the same SHA there as here
|
155
|
-
integrate_options[:branch] = (
|
74
|
+
integrate_options[:branch] = current_app_dir.join('REVISION').read.strip
|
156
75
|
|
157
|
-
config, shell = init_and_propagate(integrate_options, 'integrate')
|
76
|
+
servers, config, shell = init_and_propagate(integrate_options, 'integrate')
|
158
77
|
|
159
|
-
|
78
|
+
servers.each do |server|
|
160
79
|
shell.logged_system server.sync_directory_command(app_dir)
|
161
80
|
# we're just about to recreate this, so it has to be gone
|
162
81
|
# first. otherwise, non-idempotent deploy hooks could screw
|
163
82
|
# things up, and since we don't control deploy hooks, we must
|
164
83
|
# assume the worst.
|
165
|
-
|
84
|
+
shell.logged_system server.command_on_server('sh -l -c', "rm -rf #{current_app_dir}")
|
166
85
|
end
|
167
86
|
|
168
87
|
# deploy local-ref to other instances into /data/$app/local-current
|
169
|
-
EY::Serverside::Deploy.new(config, shell).cached_deploy
|
88
|
+
EY::Serverside::Deploy.new(servers, config, shell).cached_deploy
|
170
89
|
end
|
171
90
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
method_option :environment_name,:type => :string,
|
178
|
-
:required => true,
|
179
|
-
:desc => "Environment name"
|
180
|
-
|
181
|
-
method_option :account_name, :type => :string,
|
182
|
-
:required => true,
|
183
|
-
:desc => "Account name"
|
184
|
-
|
185
|
-
method_option :stack, :type => :string,
|
186
|
-
:desc => "Web stack (so we can restart it correctly)"
|
187
|
-
|
188
|
-
method_option :instances, :type => :array,
|
189
|
-
:desc => "Hostnames of instances to deploy to, e.g. --instances localhost app1 app2"
|
190
|
-
|
191
|
-
method_option :instance_roles, :type => :hash,
|
192
|
-
:default => {},
|
193
|
-
:desc => "Roles of instances, keyed on hostname, comma-separated. e.g. instance1:app_master,etc instance2:db,memcached ..."
|
194
|
-
|
195
|
-
method_option :instance_names, :type => :hash,
|
196
|
-
:default => {},
|
197
|
-
:desc => "Instance names, keyed on hostname. e.g. instance1:name1 instance2:name2"
|
198
|
-
|
199
|
-
method_option :verbose, :type => :boolean,
|
200
|
-
:desc => "Verbose output",
|
201
|
-
:aliases => ["-v"]
|
91
|
+
account_app_env_options
|
92
|
+
instances_options
|
93
|
+
stack_option
|
94
|
+
verbose_option
|
202
95
|
desc "restart", "Restart app servers, conditionally enabling maintenance page"
|
203
96
|
def restart
|
204
|
-
config, shell = init_and_propagate(options, 'restart')
|
97
|
+
servers, config, shell = init_and_propagate(options, 'restart')
|
205
98
|
|
206
|
-
EY::Serverside::Deploy.new(config, shell).restart_with_maintenance_page
|
99
|
+
EY::Serverside::Deploy.new(servers, config, shell).restart_with_maintenance_page
|
207
100
|
end
|
208
101
|
|
209
102
|
desc "install_bundler [VERSION]", "Make sure VERSION of bundler is installed (in system ruby)"
|
@@ -224,14 +117,15 @@ module EY
|
|
224
117
|
private
|
225
118
|
|
226
119
|
# Put the same engineyard-serverside on all the servers (Used to be public but is unused as an actual CLI command now)
|
227
|
-
def propagate(shell)
|
228
|
-
config = EY::Serverside::Deploy::Configuration.new
|
120
|
+
def propagate(servers, config, shell)
|
229
121
|
gem_filename = "engineyard-serverside-#{EY::Serverside::VERSION}.gem"
|
230
122
|
local_gem_file = File.join(Gem.dir, 'cache', gem_filename)
|
231
123
|
remote_gem_file = File.join(Dir.tmpdir, gem_filename)
|
232
124
|
gem_binary = File.join(Gem.default_bindir, 'gem')
|
233
125
|
|
234
|
-
servers =
|
126
|
+
servers = servers.remote
|
127
|
+
|
128
|
+
return if servers.empty?
|
235
129
|
|
236
130
|
shell.status "Propagating engineyard-serverside #{EY::Serverside::VERSION} to #{servers.size} server#{servers.size == 1 ? '' : 's' }."
|
237
131
|
|
@@ -271,24 +165,23 @@ module EY
|
|
271
165
|
|
272
166
|
def init_and_propagate(*args)
|
273
167
|
config, shell = init(*args)
|
274
|
-
load_servers(config)
|
275
|
-
propagate(shell)
|
276
|
-
[config, shell]
|
168
|
+
servers = load_servers(config)
|
169
|
+
propagate(servers, config, shell)
|
170
|
+
[servers, config, shell]
|
277
171
|
end
|
278
172
|
|
279
173
|
def init(options, action)
|
280
174
|
config = EY::Serverside::Deploy::Configuration.new(options)
|
281
|
-
shell = EY::Serverside::Shell.new(
|
175
|
+
shell = EY::Serverside::Shell.new(
|
176
|
+
:verbose => config.verbose,
|
177
|
+
:log_path => File.join(ENV['HOME'], "#{config.app}-#{action}.log")
|
178
|
+
)
|
282
179
|
shell.debug "Initializing engineyard-serverside #{EY::Serverside::VERSION}."
|
283
180
|
[config, shell]
|
284
181
|
end
|
285
182
|
|
286
|
-
def run_on_server(server, command)
|
287
|
-
shell.logged_system(server.command_on_server('sh -l -c', command))
|
288
|
-
end
|
289
|
-
|
290
183
|
def load_servers(config)
|
291
|
-
EY::Serverside::
|
184
|
+
EY::Serverside::Servers.from_hashes(assemble_instance_hashes(config))
|
292
185
|
end
|
293
186
|
|
294
187
|
def assemble_instance_hashes(config)
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module EY
|
2
|
+
module Serverside
|
3
|
+
module CLIHelpers
|
4
|
+
def account_app_env_options
|
5
|
+
method_option :app, :type => :string,
|
6
|
+
:required => true,
|
7
|
+
:desc => "Application to deploy",
|
8
|
+
:aliases => %w[-a --app-name]
|
9
|
+
method_option :environment_name, :type => :string,
|
10
|
+
:required => true,
|
11
|
+
:desc => "Environment name"
|
12
|
+
method_option :account_name, :type => :string,
|
13
|
+
:required => true,
|
14
|
+
:desc => "Account name"
|
15
|
+
end
|
16
|
+
|
17
|
+
def framework_env_option
|
18
|
+
method_option :framework_env, :type => :string,
|
19
|
+
:required => true,
|
20
|
+
:desc => "Ruby web framework environment",
|
21
|
+
:aliases => ["-e"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def stack_option
|
25
|
+
method_option :stack, :type => :string,
|
26
|
+
:desc => "Web stack (so we can restart it correctly)"
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def config_option
|
31
|
+
method_option :config, :type => :string,
|
32
|
+
:desc => "Additional configuration"
|
33
|
+
end
|
34
|
+
|
35
|
+
def instances_options
|
36
|
+
method_option :instances, :type => :array,
|
37
|
+
:desc => "Hostnames of instances to deploy to, e.g. --instances localhost app1 app2"
|
38
|
+
method_option :instance_roles, :type => :hash,
|
39
|
+
:default => {},
|
40
|
+
:desc => "Roles of instances, keyed on hostname, comma-separated. e.g. instance1:app_master,etc instance2:db,memcached ..."
|
41
|
+
method_option :instance_names, :type => :hash,
|
42
|
+
:default => {},
|
43
|
+
:desc => "Instance names, keyed on hostname. e.g. instance1:name1 instance2:name2"
|
44
|
+
end
|
45
|
+
|
46
|
+
def verbose_option
|
47
|
+
method_option :verbose, :type => :boolean,
|
48
|
+
:desc => "Verbose output",
|
49
|
+
:aliases => ["-v"]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -1,46 +1,108 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'thor'
|
3
3
|
require 'pp'
|
4
|
+
require 'engineyard-serverside/paths'
|
4
5
|
|
5
6
|
module EY
|
6
7
|
module Serverside
|
7
8
|
class Deploy::Configuration
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
include Paths::LegacyHelpers
|
10
|
+
|
11
|
+
# Defines a fetch method for the specified key.
|
12
|
+
# If no default and no block is specified, it means the key is required
|
13
|
+
# and if it's accessed without a value, it should raise.
|
14
|
+
def self.def_option(name, default=nil, key=nil, &block)
|
15
|
+
key ||= name.to_s
|
16
|
+
if block_given?
|
17
|
+
define_method(name) { fetch(key) {instance_eval(&block)} }
|
18
|
+
else
|
19
|
+
define_method(name) { fetch(key, default) }
|
20
|
+
end
|
21
|
+
end
|
13
22
|
|
14
|
-
|
23
|
+
# Calls def_option and adds a name? predicate method
|
24
|
+
def self.def_boolean_option(name, default=nil, &block)
|
25
|
+
def_option(name, default, &block)
|
26
|
+
alias_method(:"#{name}?", name)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Required options do not have a default value.
|
30
|
+
# An option being required does not mean that it is always supplied,
|
31
|
+
# it just means that if it is accessed and it does not exist, an error
|
32
|
+
# will be raised instead of returning a nil default value.
|
33
|
+
def self.def_required_option(name, key=nil)
|
34
|
+
key ||= name.to_s
|
35
|
+
define_method(name) do
|
36
|
+
fetch(key) { raise "Required configuration option not found: #{key.inspect}" }
|
37
|
+
end
|
38
|
+
end
|
15
39
|
|
16
|
-
|
17
|
-
|
18
|
-
|
40
|
+
def_required_option :app
|
41
|
+
def_required_option :environment_name
|
42
|
+
def_required_option :account_name
|
43
|
+
def_required_option :framework_env
|
44
|
+
def_required_option :instances
|
45
|
+
def_required_option :instance_roles
|
46
|
+
def_required_option :instance_names
|
47
|
+
|
48
|
+
def_option :repo, nil
|
49
|
+
def_option :migrate, nil
|
50
|
+
def_option :precompile_assets, nil
|
51
|
+
def_option :stack, nil
|
52
|
+
def_option :strategy, 'Git'
|
53
|
+
def_option :branch, 'master'
|
54
|
+
def_option :bundle_without, 'test development'
|
55
|
+
def_option :current_roles, []
|
56
|
+
def_option :copy_exclude, []
|
57
|
+
def_option(:user) { ENV['USER'] }
|
58
|
+
def_option(:group) { user }
|
59
|
+
|
60
|
+
def_boolean_option :verbose, false
|
61
|
+
def_boolean_option :ignore_database_adapter_warning, false
|
62
|
+
def_boolean_option :maintenance_on_migrate, true
|
63
|
+
def_boolean_option(:maintenance_on_restart) { required_downtime_stack? }
|
64
|
+
|
65
|
+
alias app_name app
|
66
|
+
alias environment framework_env # legacy because it would be nice to have less confusion around "environment"
|
67
|
+
alias migration_command migrate
|
68
|
+
|
69
|
+
def initialize(options)
|
70
|
+
opts = string_keys(options)
|
19
71
|
config = JSON.parse(opts.delete("config") || "{}")
|
20
|
-
|
72
|
+
append_config_source opts # high priority
|
73
|
+
append_config_source config # lower priority
|
21
74
|
end
|
22
75
|
|
23
|
-
def
|
24
|
-
|
76
|
+
def string_keys(hsh)
|
77
|
+
hsh.inject({}) { |h,(k,v)| h[k.to_s] = v; h }
|
25
78
|
end
|
26
|
-
alias :c :configuration # FIXME: awful, but someone is probably using it :(
|
27
79
|
|
28
|
-
|
29
|
-
|
30
|
-
|
80
|
+
def append_config_source(config_source)
|
81
|
+
@config_sources ||= []
|
82
|
+
@config_sources.unshift(config_source.dup)
|
83
|
+
reload_configuration!
|
31
84
|
end
|
32
85
|
|
33
|
-
def
|
34
|
-
configuration.
|
86
|
+
def configuration
|
87
|
+
@configuration ||= @config_sources.inject({}) {|low,high| low.merge(high)}
|
88
|
+
end
|
89
|
+
# FIXME: single letter variable is of very questionable value
|
90
|
+
alias :c :configuration
|
91
|
+
|
92
|
+
# reset cached configuration hash
|
93
|
+
def reload_configuration!
|
94
|
+
@configuration = nil
|
35
95
|
end
|
36
96
|
|
37
97
|
def load_ey_yml_data(data, shell)
|
38
98
|
environments = data['environments']
|
39
|
-
if environments &&
|
99
|
+
if environments && environments[environment_name]
|
40
100
|
shell.substatus "ey.yml configuration loaded for environment #{environment_name.inspect}."
|
41
|
-
|
42
|
-
|
43
|
-
|
101
|
+
|
102
|
+
env_data = string_keys(environments[environment_name])
|
103
|
+
shell.debug "#{environment_name}:\n#{env_data.pretty_inspect}"
|
104
|
+
|
105
|
+
append_config_source(string_keys(env_data)) # insert at lowest priority so as not to disturb important config
|
44
106
|
true
|
45
107
|
else
|
46
108
|
shell.info "No matching ey.yml configuration found for environment #{environment_name.inspect}."
|
@@ -49,6 +111,12 @@ module EY
|
|
49
111
|
end
|
50
112
|
end
|
51
113
|
|
114
|
+
# Fetch a key from the config.
|
115
|
+
# You must supply either a default second argument, or a default block
|
116
|
+
def fetch(key, *args, &block)
|
117
|
+
configuration.fetch(key.to_s, *args, &block)
|
118
|
+
end
|
119
|
+
|
52
120
|
def [](key)
|
53
121
|
if respond_to?(key.to_sym)
|
54
122
|
send(key.to_sym)
|
@@ -61,202 +129,104 @@ module EY
|
|
61
129
|
respond_to?(key.to_sym) || configuration.has_key?(key)
|
62
130
|
end
|
63
131
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
def node
|
69
|
-
EY::Serverside.node
|
70
|
-
end
|
71
|
-
|
72
|
-
def verbose
|
73
|
-
configuration['verbose']
|
132
|
+
# Delegate to the configuration objects
|
133
|
+
def method_missing(meth, *args, &blk)
|
134
|
+
configuration.key?(meth.to_s) ? configuration.fetch(meth.to_s) : super
|
74
135
|
end
|
75
136
|
|
76
|
-
def
|
77
|
-
configuration
|
78
|
-
end
|
79
|
-
alias app_name app
|
80
|
-
|
81
|
-
def environment_name
|
82
|
-
configuration['environment_name'].to_s
|
137
|
+
def respond_to?(meth, include_private=false)
|
138
|
+
configuration.key?(meth.to_s) || super
|
83
139
|
end
|
84
140
|
|
85
|
-
def
|
86
|
-
configuration
|
141
|
+
def to_json
|
142
|
+
configuration.to_json
|
87
143
|
end
|
88
144
|
|
89
|
-
def
|
90
|
-
|
145
|
+
def node
|
146
|
+
EY::Serverside.node
|
91
147
|
end
|
92
148
|
|
93
149
|
def strategy_class
|
94
150
|
EY::Serverside::Strategies.const_get(strategy)
|
95
151
|
end
|
96
152
|
|
97
|
-
def
|
98
|
-
|
153
|
+
def paths
|
154
|
+
@paths ||= Paths.new({
|
155
|
+
:home => configuration['home_path'],
|
156
|
+
:app_name => app_name,
|
157
|
+
:deploy_root => configuration['deploy_to'],
|
158
|
+
:active_release => configuration['release_path'],
|
159
|
+
:repository_cache => configuration['repository_cache'],
|
160
|
+
})
|
99
161
|
end
|
100
162
|
|
101
|
-
def
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
def migrate?
|
110
|
-
!!configuration['migrate']
|
111
|
-
end
|
112
|
-
|
113
|
-
def migration_command
|
114
|
-
configuration['migrate'] == "migrate" ? DEFAULT_CONFIG["migrate"] : configuration['migrate']
|
163
|
+
def rollback_paths!
|
164
|
+
rollback_paths = paths.rollback
|
165
|
+
if rollback_paths
|
166
|
+
@paths = rollback_paths
|
167
|
+
true
|
168
|
+
else
|
169
|
+
false
|
170
|
+
end
|
115
171
|
end
|
116
172
|
|
117
|
-
def
|
118
|
-
|
173
|
+
def ruby_version_command
|
174
|
+
"ruby -v"
|
119
175
|
end
|
120
176
|
|
121
|
-
def
|
122
|
-
|
177
|
+
def system_version_command
|
178
|
+
"uname -m"
|
123
179
|
end
|
124
180
|
|
125
|
-
def
|
126
|
-
|
181
|
+
def migrate?
|
182
|
+
!!migration_command
|
127
183
|
end
|
128
184
|
|
129
185
|
def role
|
130
186
|
node['instance_role']
|
131
187
|
end
|
132
188
|
|
133
|
-
def current_roles
|
134
|
-
configuration['current_roles'] || []
|
135
|
-
end
|
136
|
-
|
137
189
|
def current_role
|
138
190
|
current_roles.first
|
139
191
|
end
|
140
192
|
|
141
|
-
def copy_exclude
|
142
|
-
@copy_exclude ||= Array(configuration.fetch("copy_exclude", []))
|
143
|
-
end
|
144
|
-
|
145
|
-
def environment
|
146
|
-
configuration['framework_env']
|
147
|
-
end
|
148
|
-
|
149
|
-
def latest_release
|
150
|
-
all_releases.last
|
151
|
-
end
|
152
|
-
|
153
|
-
def previous_release(current=latest_release)
|
154
|
-
index = all_releases.index(current)
|
155
|
-
all_releases[index-1]
|
156
|
-
end
|
157
|
-
|
158
|
-
def all_releases
|
159
|
-
Dir.glob("#{release_dir}/*").sort
|
160
|
-
end
|
161
|
-
|
162
|
-
def binstubs_path
|
163
|
-
release_path + '/ey_bundler_binstubs'
|
164
|
-
end
|
165
|
-
|
166
193
|
def framework_env_names
|
167
194
|
%w[RAILS_ENV RACK_ENV NODE_ENV MERB_ENV]
|
168
195
|
end
|
169
196
|
|
170
197
|
def framework_envs
|
171
|
-
framework_env_names.map { |e| "#{e}=#{
|
198
|
+
framework_env_names.map { |e| "#{e}=#{framework_env}" }.join(' ')
|
172
199
|
end
|
173
200
|
|
174
201
|
def set_framework_envs
|
175
202
|
framework_env_names.each { |e| ENV[e] = environment }
|
176
203
|
end
|
177
204
|
|
178
|
-
def current_path
|
179
|
-
File.join(deploy_to, "current")
|
180
|
-
end
|
181
|
-
|
182
|
-
def shared_path
|
183
|
-
File.join(deploy_to, "shared")
|
184
|
-
end
|
185
|
-
|
186
|
-
def bundled_gems_path
|
187
|
-
File.join(shared_path, "bundled_gems")
|
188
|
-
end
|
189
|
-
|
190
|
-
def gemfile_path
|
191
|
-
File.join(release_path, "Gemfile")
|
192
|
-
end
|
193
|
-
|
194
|
-
def ruby_version_file
|
195
|
-
File.join(bundled_gems_path, "RUBY_VERSION")
|
196
|
-
end
|
197
|
-
|
198
|
-
def ruby_version_command
|
199
|
-
"ruby -v"
|
200
|
-
end
|
201
|
-
|
202
|
-
def system_version_file
|
203
|
-
File.join(bundled_gems_path, "SYSTEM_VERSION")
|
204
|
-
end
|
205
|
-
|
206
|
-
def system_version_command
|
207
|
-
"uname -m"
|
208
|
-
end
|
209
|
-
|
210
|
-
def release_dir
|
211
|
-
File.join(deploy_to, "releases")
|
212
|
-
end
|
213
|
-
|
214
|
-
def failed_release_dir
|
215
|
-
File.join(deploy_to, "releases_failed")
|
216
|
-
end
|
217
|
-
|
218
|
-
def release_path
|
219
|
-
@release_path ||= File.join(release_dir, Time.now.utc.strftime("%Y%m%d%H%M%S"))
|
220
|
-
end
|
221
|
-
|
222
205
|
def precompile_assets_inferred?
|
223
206
|
!precompile_assets? && !skip_precompile_assets?
|
224
207
|
end
|
225
208
|
|
226
209
|
def precompile_assets?
|
227
|
-
|
210
|
+
precompile_assets == true
|
228
211
|
end
|
229
212
|
|
230
213
|
def skip_precompile_assets?
|
231
|
-
|
214
|
+
precompile_assets == false
|
232
215
|
end
|
233
216
|
|
217
|
+
# Assume downtime required if stack is not specified (nil) just in case.
|
234
218
|
def required_downtime_stack?
|
235
|
-
|
236
|
-
end
|
237
|
-
|
238
|
-
def enable_maintenance_page_on_restart?
|
239
|
-
configuration.fetch('maintenance_on_restart', required_downtime_stack?)
|
240
|
-
end
|
241
|
-
|
242
|
-
def enable_maintenance_page_on_migrate?
|
243
|
-
configuration.fetch('maintenance_on_migrate', true)
|
219
|
+
[nil, 'nginx_mongrel', 'glassfish'].include? stack
|
244
220
|
end
|
245
221
|
|
222
|
+
# Enable if stack requires it or if overridden in the ey.yml config.
|
246
223
|
def enable_maintenance_page?
|
247
|
-
|
248
|
-
end
|
249
|
-
|
250
|
-
def maintenance_page_enabled_path
|
251
|
-
File.join(shared_path, "system", "maintenance.html")
|
252
|
-
end
|
253
|
-
|
254
|
-
def exclusions
|
255
|
-
copy_exclude.map { |e| %|--exclude="#{e}"| }.join(' ')
|
224
|
+
maintenance_on_restart? || (migrate? && maintenance_on_migrate?)
|
256
225
|
end
|
257
226
|
|
258
|
-
|
259
|
-
|
227
|
+
# We disable the maintenance page if we would have enabled.
|
228
|
+
def disable_maintenance_page?
|
229
|
+
enable_maintenance_page?
|
260
230
|
end
|
261
231
|
|
262
232
|
end
|