engineyard 2.2.1 → 2.3.0
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.
- checksums.yaml +8 -8
- data/README.md +75 -18
- data/lib/engineyard.rb +6 -6
- data/lib/engineyard/cli.rb +131 -11
- data/lib/engineyard/cli/ui.rb +42 -0
- data/lib/engineyard/config.rb +39 -105
- data/lib/engineyard/deploy_config.rb +19 -16
- data/lib/engineyard/error.rb +1 -1
- data/lib/engineyard/serverside_runner.rb +1 -1
- data/lib/engineyard/templates.rb +6 -0
- data/lib/engineyard/templates/ey.yml.erb +193 -0
- data/lib/engineyard/templates/ey_yml.rb +119 -0
- data/lib/engineyard/version.rb +2 -2
- data/spec/engineyard/deploy_config_spec.rb +33 -67
- data/spec/ey/deploy_spec.rb +54 -94
- data/spec/ey/init_spec.rb +123 -0
- data/spec/ey/rebuild_spec.rb +1 -1
- data/spec/ey/servers_spec.rb +143 -0
- data/spec/ey/timeout_deploy_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -7
- data/spec/support/helpers.rb +43 -1
- data/spec/support/shared_behavior.rb +4 -1
- metadata +19 -11
- data/lib/engineyard/deploy_config/migrate.rb +0 -129
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MWMzMTAwYWJkYWMyYjcxNjFhZjc0OThjZDM5M2E1MTJkMzIwNTg4Yg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NGM3OWVjYTI2ZWJmOGM5MzI3MjdiMjc3NDMzMTRiMmM3YTA4ZDFiNg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZGI4ZWRlNWE3NWIzZWE0MTc4ODBlMDcxNjllZTk3M2Y3NTE3ZmE3MDNjMzVk
|
10
|
+
ODgyOTc1ZjUzMjI2OGRhYTNmZmM4OGU3YzQzMGQxZmFiNGQ4ZTg5MWI4NzJi
|
11
|
+
NGY1M2Q1MWM4ODRhZWUyY2RkZjI2MzhjOTlhYTQzNzBjODgwMmM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OTY4OWZhOGZjZDdhYjY4NDc5OWE4ZjA5OTJhMjg4ZDFhNjVjMDFmMzM1ZjRj
|
14
|
+
ODJhMjNiYWY3MzBhZGMyNWI2MzFmNDkyNTliZmY1MzVhNWM5OGE2NjIzY2U1
|
15
|
+
YzU5OTU5Y2RjMjk4MDBlYTI5ZGM3ZDRmZDQxZmRjZGFiN2I4YmI=
|
data/README.md
CHANGED
@@ -18,38 +18,56 @@ you for your Engine Yard email and password.
|
|
18
18
|
### Configuration
|
19
19
|
|
20
20
|
The `ey.yml` file allows options to be saved for each environment to which an
|
21
|
-
application is deployed.
|
21
|
+
application is deployed.
|
22
|
+
|
23
|
+
A typical Rails application will have a `config/ey.yml` like this:
|
24
|
+
|
25
|
+
---
|
26
|
+
# This is all you need for a typical rails application.
|
27
|
+
defaults:
|
28
|
+
migrate: true
|
29
|
+
migration_command: rake db:migrate
|
30
|
+
precompile_assets: true
|
31
|
+
|
32
|
+
The following `ey.yml` file shows other things that can be customized.
|
33
|
+
A typical application will not need most of these options.
|
22
34
|
|
23
|
-
$ cat config/ey.yml
|
24
35
|
---
|
25
36
|
# 'defaults' applies to all environments running this application.
|
37
|
+
# Only set these options if needed. The defaults are correct for most applications.
|
26
38
|
defaults:
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
39
|
+
bundler: detect # By default, bundler is detected via Gemfile. Options: true: always run bundler; false: never run bundler
|
40
|
+
composer: detect # By default, composer is detected via composer.lock. Options: true: always run composer; false: never run composer
|
41
|
+
npm: detect # By default, npm is detected via package.json. Options: true: always run npm; false: never run npm
|
42
|
+
bundle_without: GROUP1 GROUP2 # exclude groups on bundle install (default: test development)
|
43
|
+
bundle_options: --OPTION # extra bundle install options (--local, --quiet, etc; does not override bundle_without)
|
44
|
+
copy_exclude: # don't rsync the following dirs (some people like to skip .git)
|
45
|
+
- SOME_LARGE_DIR
|
31
46
|
maintenance_on_restart: false # show maintenance page during app restart (default: false except for glassfish and mongrel)
|
32
|
-
maintenance_on_migrate:
|
47
|
+
maintenance_on_migrate: true # show maintenance page during migrations (default: true)
|
33
48
|
precompile_assets: true # enables rails assets precompilation (default: inferred using app/assets and config/application.rb)
|
34
49
|
precomplie_assets_task: assets:precompile # override the assets:precompile rake task
|
35
|
-
precompile_unchanged_assets:
|
36
|
-
asset_dependencies:
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
-
|
41
|
-
-
|
42
|
-
-
|
50
|
+
precompile_unchanged_assets: false # if true, does not check git for changes before precompiling assets.
|
51
|
+
asset_dependencies: # a list of relative paths to search for asset changes during each deploy.
|
52
|
+
- app/assets # default
|
53
|
+
- lib/assets # default
|
54
|
+
- vendor/assets # default
|
55
|
+
- Gemfile.lock # default
|
56
|
+
- config/routes.rb # default
|
57
|
+
- config/application.rb # default
|
58
|
+
- config/requirejs.yml # custom option (be sure to include defaults if you specify this option)
|
59
|
+
asset_strategy: shifting # choose an alternet asset management strategy. See rails_assets/strategy.rb for more info.
|
60
|
+
asset_roles: :all # specify on which roles to compile assets (default: [:app, :app_master, :solo])
|
43
61
|
ignore_database_adapter_warning: true # hide database adapter warning if you don't use MySQL or PostgreSQL (default: false)
|
44
62
|
|
45
63
|
# Environment specific options apply only to a single environment and override settings in defaults.
|
46
64
|
environments:
|
47
65
|
env_production:
|
48
66
|
precompile_unchanged_assets: true # precompiles assets even if no changes would be detected (does not check for changes at all).
|
49
|
-
|
67
|
+
asset_strategy: shifting # choose an alternet asset management strategy (shifting, cleaning, private, shared)
|
50
68
|
asset_roles: :all # specify on which roles to compile assets (default: [:app, :app_master, :solo] - must be an Array)
|
51
69
|
env_staging
|
52
|
-
|
70
|
+
asset_strategy: private # Use an asset management that always refreshes, so staging enviroments don't get conflicts
|
53
71
|
|
54
72
|
These options in `ey.yml` will only work if the file is committed to your
|
55
73
|
application repository. Make sure to commit this file. Different branches
|
@@ -59,6 +77,19 @@ found in the deploying commit will be used for the current deploy.
|
|
59
77
|
|
60
78
|
### Commands
|
61
79
|
|
80
|
+
#### ey init
|
81
|
+
|
82
|
+
Initialize a repository for deployment on Engine Yard Cloud.
|
83
|
+
|
84
|
+
This command writes or updates an ey.yml file which explains options available
|
85
|
+
for customizing the deployment process.
|
86
|
+
|
87
|
+
`ey init` can be run in existing applications to update the ey.yml file
|
88
|
+
without losing existing settings.
|
89
|
+
|
90
|
+
NOTE: Please verify all settings and changes after running ey init for
|
91
|
+
the first time.
|
92
|
+
|
62
93
|
#### ey deploy
|
63
94
|
|
64
95
|
This command must be run within the current directory containing the app to be
|
@@ -78,7 +109,7 @@ Options:
|
|
78
109
|
-c, [--account=ACCOUNT] # Name of the account in which the environment can be found
|
79
110
|
-a, [--app=APP] # Name of the application to deploy
|
80
111
|
-e, [--environment=ENVIRONMENT] # Environment in which to deploy this application
|
81
|
-
-m, [--migrate=MIGRATE] # Run migrations via [MIGRATE]
|
112
|
+
-m, [--migrate=MIGRATE] # Run migrations via [MIGRATE]; use --no-migrate to avoid running migrations
|
82
113
|
-v, [--verbose] # Be verbose
|
83
114
|
[--ignore-default-branch] # Force a deploy of the specified branch even if a default is set
|
84
115
|
[--ignore-bad-master] # Force a deploy even if the master is in a bad state
|
@@ -129,6 +160,32 @@ Options:
|
|
129
160
|
-s, [--simple] # Print each environment name on its own on a new line
|
130
161
|
-a, [--all] # Show all environments, not just ones associated with this application.
|
131
162
|
|
163
|
+
#### ey servers
|
164
|
+
|
165
|
+
List all servers on an environment.
|
166
|
+
|
167
|
+
Options:
|
168
|
+
|
169
|
+
-c, [--account=ACCOUNT] # Name of the account in which the environment can be found
|
170
|
+
-e, [--environment=ENVIRONMENT] # Show only servers in the named environment
|
171
|
+
-u, [--user] # Print the user@ in front of the server hostname to make ssh connections simpler
|
172
|
+
-s, [--simple] # Print each server on a new line with hostname, role, and name separated by tabs
|
173
|
+
-S, [--host] # Print each server on a new line with hostname only. Use -Su for 'user@host'
|
174
|
+
|
175
|
+
Example output:
|
176
|
+
|
177
|
+
$ ey servers -s
|
178
|
+
ec2-10-0-0-0.us-west-2.compute.amazonaws.com i-aabbccdd app_master
|
179
|
+
ec2-10-0-0-1.us-west-2.compute.amazonaws.com i-bbccddee app
|
180
|
+
ec2-10-0-0-2.us-west-2.compute.amazonaws.com i-ccddeeff db_master
|
181
|
+
ec2-10-0-0-3.us-west-2.compute.amazonaws.com i-ddeeffaa util resque
|
182
|
+
|
183
|
+
$ ey servers -Su
|
184
|
+
deploy@ec2-10-0-0-0.us-west-2.compute.amazonaws.com
|
185
|
+
deploy@ec2-10-0-0-1.us-west-2.compute.amazonaws.com
|
186
|
+
deploy@ec2-10-0-0-2.us-west-2.compute.amazonaws.com
|
187
|
+
deploy@ec2-10-0-0-3.us-west-2.compute.amazonaws.com
|
188
|
+
|
132
189
|
|
133
190
|
#### ey logs
|
134
191
|
|
data/lib/engineyard.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'engineyard-cloud-client'
|
2
|
-
|
3
1
|
module EY
|
4
|
-
require 'engineyard/version'
|
5
|
-
require 'engineyard/error'
|
6
|
-
require 'engineyard/config'
|
7
|
-
|
8
2
|
autoload :Repo, 'engineyard/repo'
|
3
|
+
autoload :Templates, 'engineyard/templates'
|
9
4
|
end
|
5
|
+
|
6
|
+
require 'engineyard-cloud-client'
|
7
|
+
require 'engineyard/version'
|
8
|
+
require 'engineyard/error'
|
9
|
+
require 'engineyard/config'
|
data/lib/engineyard/cli.rb
CHANGED
@@ -4,6 +4,7 @@ require 'engineyard/thor'
|
|
4
4
|
require 'engineyard/deploy_config'
|
5
5
|
require 'engineyard/serverside_runner'
|
6
6
|
require 'launchy'
|
7
|
+
require 'fileutils'
|
7
8
|
|
8
9
|
module EY
|
9
10
|
class CLI < EY::Thor
|
@@ -36,10 +37,52 @@ module EY
|
|
36
37
|
raise
|
37
38
|
end
|
38
39
|
|
39
|
-
class_option :api_token, :type => :string, :desc => "Use
|
40
|
+
class_option :api_token, :type => :string, :desc => "Use API_TOKEN to authenticate this command"
|
40
41
|
class_option :serverside_version, :type => :string, :desc => "Please use with care! Override deploy system version (same as ENV variable ENGINEYARD_SERVERSIDE_VERSION)"
|
41
42
|
class_option :quiet, :aliases => %w[-q], :type => :boolean, :desc => "Quieter CLI output."
|
42
43
|
|
44
|
+
desc "init",
|
45
|
+
"Initialize the current directory with an ey.yml configuration file."
|
46
|
+
long_desc <<-DESC
|
47
|
+
Initialize the current directory with an ey.yml configuration file.
|
48
|
+
|
49
|
+
Please read the generated file and make adjustments.
|
50
|
+
Many applications will need only the default behavior.
|
51
|
+
For reference, many available options are explained in the generated file.
|
52
|
+
|
53
|
+
IMPORTANT: THE GENERATED FILE '#{EY::Config.pathname_for_write}'
|
54
|
+
MUST BE COMMITTED TO YOUR REPOSITORY OR OPTIONS WILL NOT BE LOADED.
|
55
|
+
DESC
|
56
|
+
method_option :path, :type => :string, :aliases => %w(-p),
|
57
|
+
:desc => "Path for ey.yml (supported paths: #{EY::Config::CONFIG_FILES.join(', ')})"
|
58
|
+
def init
|
59
|
+
unless EY::Repo.exist?
|
60
|
+
raise EY::Error, "Working directory is not a repository. Aborting."
|
61
|
+
end
|
62
|
+
|
63
|
+
path = Pathname.new(options['path'] || EY::Config.pathname_for_write)
|
64
|
+
|
65
|
+
existing = {}
|
66
|
+
if path.exist?
|
67
|
+
ui.warn "Reinitializing existing file: #{path}"
|
68
|
+
existing = EY::Config.load_config
|
69
|
+
end
|
70
|
+
|
71
|
+
template = EY::Templates::EyYml.new(existing)
|
72
|
+
template.write(path)
|
73
|
+
|
74
|
+
ui.info <<-GIT
|
75
|
+
|
76
|
+
Configuration generated: #{path}
|
77
|
+
Go look at it, then add it to your repository!
|
78
|
+
|
79
|
+
\tgit add #{path}
|
80
|
+
\tgit commit -m "Add generated #{path} from ey init"
|
81
|
+
|
82
|
+
GIT
|
83
|
+
end
|
84
|
+
|
85
|
+
|
43
86
|
desc "deploy [--environment ENVIRONMENT] [--ref GIT-REF]",
|
44
87
|
"Deploy specified branch, tag, or sha to specified environment."
|
45
88
|
long_desc <<-DESC
|
@@ -57,7 +100,7 @@ module EY
|
|
57
100
|
:desc => "Force a deploy even if the master is in a bad state"
|
58
101
|
method_option :migrate, :type => :string, :aliases => %w(-m),
|
59
102
|
:lazy_default => true,
|
60
|
-
:desc => "Run migrations via [MIGRATE]
|
103
|
+
:desc => "Run migrations via [MIGRATE]; use --no-migrate to avoid running migrations"
|
61
104
|
method_option :ref, :type => :string, :aliases => %w(-r --branch --tag),
|
62
105
|
:required => true, :default => '',
|
63
106
|
:desc => "Git ref to deploy. May be a branch, a tag, or a SHA. Use -R to deploy a different ref if a default is set."
|
@@ -272,6 +315,47 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
|
|
272
315
|
end
|
273
316
|
map "envs" => :environments
|
274
317
|
|
318
|
+
desc "servers", "List servers for an environment."
|
319
|
+
long_desc <<-DESC
|
320
|
+
Display a list of all servers on an environment.
|
321
|
+
Specify -s (--simple) to make parsing the output easier
|
322
|
+
or -uS (--user --host) to output bash loop friendly "user@hostname"
|
323
|
+
DESC
|
324
|
+
|
325
|
+
method_option :simple, :type => :boolean, :aliases => %(-s),
|
326
|
+
:desc => "Display all information in a simplified format without extra text or column alignment"
|
327
|
+
method_option :host, :type => :boolean, :aliases => %(-S),
|
328
|
+
:desc => "Display only hostnames, one per newline (use options -uS (--user --host) for user@hostname)"
|
329
|
+
method_option :user, :type => :boolean, :aliases => %w(-u),
|
330
|
+
:desc => "Include the ssh username in front of the hostname for easy SSH scripting"
|
331
|
+
method_option :account, :type => :string, :aliases => %w(-c),
|
332
|
+
:required => true, :default => '',
|
333
|
+
:desc => "Find environment in this account"
|
334
|
+
method_option :environment, :type => :string, :aliases => %w(-e),
|
335
|
+
:required => true, :default => '',
|
336
|
+
:desc => "Show servers in environment matching environment name"
|
337
|
+
def servers
|
338
|
+
if options[:environment] == '' && options[:account] == ''
|
339
|
+
repo.fail_on_no_remotes!
|
340
|
+
end
|
341
|
+
|
342
|
+
environment = nil
|
343
|
+
ui.mute_if(options[:simple] || options[:host]) do
|
344
|
+
environment = fetch_environment(options[:environment], options[:account])
|
345
|
+
end
|
346
|
+
|
347
|
+
username = options[:user] && environment.username
|
348
|
+
servers = environment.instances
|
349
|
+
|
350
|
+
if options[:host]
|
351
|
+
ui.print_hostnames(servers, username)
|
352
|
+
elsif options[:simple]
|
353
|
+
ui.print_simple_servers(servers, username)
|
354
|
+
else
|
355
|
+
ui.print_servers(servers, environment.hierarchy_name, username)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
275
359
|
desc "rebuild [--environment ENVIRONMENT]", "Rebuild specified environment."
|
276
360
|
long_desc <<-DESC
|
277
361
|
Engine Yard's main configuration run occurs on all servers. Mainly used to fix
|
@@ -338,7 +422,9 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
|
|
338
422
|
long_desc <<-DESC
|
339
423
|
If a command is supplied, it will be run, otherwise a session will be
|
340
424
|
opened. The application master is used for environments with clusters.
|
341
|
-
|
425
|
+
|
426
|
+
Option --all requires a command to be supplied and runs it on all servers or
|
427
|
+
pass --each to connect to each server one after another.
|
342
428
|
|
343
429
|
Note: this command is a bit picky about its ordering. To run a command with arguments on
|
344
430
|
all servers, like "rm -f /some/file", you need to order it like so:
|
@@ -365,22 +451,56 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
|
|
365
451
|
:desc => "Run command on the utility servers with the given names. If no names are given, run on all utility servers."
|
366
452
|
method_option :shell, :type => :string, :default => 'bash', :aliases => %w(-s),
|
367
453
|
:desc => "Run command in a shell other than bash. Use --no-shell to run the command without a shell."
|
454
|
+
method_option :pty, :type => :boolean, :default => false, :aliases => %w(-t),
|
455
|
+
:desc => "If a command is given, run in a pty. Required for interactive commands like sudo."
|
456
|
+
method_option :bind_address, :type => :string, :aliases => %w(-L),
|
457
|
+
:desc => "When a command is not given, pass -L to the ssh command."
|
458
|
+
method_option :each, :type => :boolean, :default => false,
|
459
|
+
:desc => "If no command is given, connect to multiple servers each one after another, instead of exiting with an error."
|
368
460
|
|
369
461
|
def ssh(cmd=nil)
|
370
462
|
environment = fetch_environment(options[:environment], options[:account])
|
371
|
-
|
463
|
+
instances = ssh_hosts(options, environment)
|
464
|
+
ssh_opts = []
|
465
|
+
|
466
|
+
if cmd
|
467
|
+
if options[:shell]
|
468
|
+
cmd = Escape.shell_command([options[:shell],'-lc',cmd])
|
469
|
+
end
|
372
470
|
|
373
|
-
|
471
|
+
if options[:pty]
|
472
|
+
ssh_opts = ["-t"]
|
473
|
+
elsif cmd =~ /sudo/
|
474
|
+
ui.warn "sudo commands often need a tty to run correctly. Use -t option to spawn a tty."
|
475
|
+
end
|
476
|
+
else
|
477
|
+
if instances.size != 1 && options[:each] == false
|
478
|
+
raise NoCommandError.new
|
479
|
+
end
|
374
480
|
|
375
|
-
|
376
|
-
|
481
|
+
if options[:bind_address]
|
482
|
+
ssh_opts = ["-L", options[:bind_address]]
|
483
|
+
end
|
377
484
|
end
|
378
485
|
|
379
|
-
|
380
|
-
|
486
|
+
ssh_cmd = ["ssh"]
|
487
|
+
ssh_cmd += ssh_opts
|
488
|
+
|
489
|
+
trap(:INT) { abort "Aborting..." }
|
490
|
+
|
491
|
+
exits = instances.map do |instance|
|
492
|
+
host = instance.public_hostname
|
493
|
+
name = instance.name ? "#{instance.role} (#{instance.name})" : instance.role
|
494
|
+
ui.info "\nConnecting to #{name} #{host}..."
|
495
|
+
unless cmd
|
496
|
+
ui.info "Ctrl + C to abort"
|
497
|
+
sleep 1.3
|
498
|
+
end
|
499
|
+
system Escape.shell_command((ssh_cmd + ["#{environment.username}@#{host}"] + [cmd]).compact)
|
381
500
|
$?.exitstatus
|
382
501
|
end
|
383
|
-
|
502
|
+
|
503
|
+
exit exits.detect {|status| status != 0 } || 0
|
384
504
|
end
|
385
505
|
|
386
506
|
no_tasks do
|
@@ -407,7 +527,7 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
|
|
407
527
|
|
408
528
|
instances = environment.instances.select {|instance| filter[instance] }
|
409
529
|
raise NoInstancesError.new(environment.name) if instances.empty?
|
410
|
-
return instances
|
530
|
+
return instances
|
411
531
|
end
|
412
532
|
end
|
413
533
|
|
data/lib/engineyard/cli/ui.rb
CHANGED
@@ -128,6 +128,48 @@ module EY
|
|
128
128
|
return ''
|
129
129
|
end
|
130
130
|
|
131
|
+
def mute_if(bool, &block)
|
132
|
+
bool ? mute(&block) : yield
|
133
|
+
end
|
134
|
+
|
135
|
+
def server_tuples(servers, username=nil)
|
136
|
+
user = username && "#{username}@"
|
137
|
+
|
138
|
+
servers.map do |server|
|
139
|
+
host = "#{user}#{server.hostname}"
|
140
|
+
[host, server.amazon_id, server.role, server.name]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
private :server_tuples
|
144
|
+
|
145
|
+
def print_hostnames(servers, username=nil)
|
146
|
+
server_tuples(servers, username).each do |server_tuple|
|
147
|
+
puts server_tuple.first
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def print_simple_servers(servers, username=nil)
|
152
|
+
server_tuples(servers, username).each do |server_tuple|
|
153
|
+
puts server_tuple.join("\t")
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def print_servers(servers, name, username=nil)
|
158
|
+
tuples = server_tuples(servers, username)
|
159
|
+
count = tuples.size
|
160
|
+
puts "# #{count} server#{count == 1 ? '' : 's'} on #{name}"
|
161
|
+
|
162
|
+
host_width = tuples.map {|s| s[0].length }.max
|
163
|
+
host_format = "%-#{host_width}s" # "%-10s" left align
|
164
|
+
|
165
|
+
role_width = tuples.map {|s| s[2].length }.max
|
166
|
+
role_format = "%-#{role_width}s" # "%-10s" left align
|
167
|
+
|
168
|
+
tuples.each do |server_tuple|
|
169
|
+
puts "#{host_format}\t%s\t#{role_format}\t%s" % server_tuple
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
131
173
|
def print_simple_envs(envs)
|
132
174
|
puts envs.map{|env| env.name }.uniq.sort
|
133
175
|
end
|
data/lib/engineyard/config.rb
CHANGED
@@ -5,19 +5,37 @@ require 'engineyard/error'
|
|
5
5
|
|
6
6
|
module EY
|
7
7
|
class Config
|
8
|
+
# This order is important.
|
8
9
|
CONFIG_FILES = ["config/ey.yml", "ey.yml"].map {|path| Pathname.new(path)}.freeze
|
10
|
+
TEMPLATE_PATHNAME = Pathname.new(__FILE__).dirname.join('templates','ey.yml').freeze
|
9
11
|
|
10
|
-
|
12
|
+
def self.pathname_for_write
|
13
|
+
pathname || CONFIG_FILES.find{|pathname| pathname.dirname.exist? }
|
14
|
+
end
|
11
15
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
+
def self.pathname
|
17
|
+
CONFIG_FILES.find{|pathname| pathname.exist? }
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.template_pathname
|
21
|
+
TEMPLATE_PATHNAME
|
22
|
+
end
|
16
23
|
|
17
|
-
|
18
|
-
|
24
|
+
def self.load_config(path = pathname)
|
25
|
+
config = YAML.load_file(path.to_s) if path && path.exist?
|
26
|
+
config ||= {} # load_file returns `false' when the file is empty
|
27
|
+
|
28
|
+
unless Hash === config
|
29
|
+
raise "ey.yml load error: Expected a Hash but a #{config.class.name} was returned."
|
19
30
|
end
|
31
|
+
config
|
32
|
+
end
|
20
33
|
|
34
|
+
attr_reader :path
|
35
|
+
|
36
|
+
def initialize(file = nil)
|
37
|
+
@path = file ? Pathname.new(file) : self.class.pathname
|
38
|
+
@config = self.class.load_config(@path)
|
21
39
|
@config["environments"] ||= {}
|
22
40
|
end
|
23
41
|
|
@@ -79,76 +97,6 @@ module EY
|
|
79
97
|
EnvironmentConfig.new(environments[environment_name], environment_name, self)
|
80
98
|
end
|
81
99
|
|
82
|
-
def set_environment_option(environment_name, key, value)
|
83
|
-
environments[environment_name] ||= {}
|
84
|
-
environments[environment_name][key] = value
|
85
|
-
write_ey_yaml
|
86
|
-
end
|
87
|
-
|
88
|
-
def write_ey_yaml
|
89
|
-
ensure_path
|
90
|
-
comments = ey_yml_comments
|
91
|
-
@path.open('w') do |f|
|
92
|
-
f.puts comments
|
93
|
-
f.puts YAML.dump(@config)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def set_default_option(key, value)
|
98
|
-
defaults[key] = value
|
99
|
-
write_ey_yaml
|
100
|
-
end
|
101
|
-
|
102
|
-
EY_YML_HINTS = <<-HINTS
|
103
|
-
# ey.yml supports many deploy configuration options when committed in an
|
104
|
-
# application's repository.
|
105
|
-
#
|
106
|
-
# Valid locations: REPO_ROOT/ey.yml or REPO_ROOT/config/ey.yml.
|
107
|
-
#
|
108
|
-
# Examples options (defaults apply to all environments for this application):
|
109
|
-
#
|
110
|
-
# defaults:
|
111
|
-
# migrate: true # Default --migrate choice for ey deploy
|
112
|
-
# migration_command: 'rake migrate' # Default migrate command to run when migrations are enabled
|
113
|
-
# branch: default_deploy_branch # Branch/ref to be deployed by default during ey deploy
|
114
|
-
# bundle_without: development test # The string to pass to bundle install --without ''
|
115
|
-
# maintenance_on_migrate: true # Enable maintenance page during migrate action (use with caution) (default: true)
|
116
|
-
# maintenance_on_restart: false # Enable maintanence page during every deploy (default: false for unicorn & passenger)
|
117
|
-
# ignore_database_adapter_warning: false # Hide the warning shown when the Gemfile does not contain a recognized database adapter (mongodb for example)
|
118
|
-
# your_own_custom_key: 'any attribute you put in ey.yml is available in deploy hooks'
|
119
|
-
# environments:
|
120
|
-
# YOUR_ENVIRONMENT_NAME: # All options pertain only to the named environment
|
121
|
-
# any_option: 'override any of the options above with specific options for certain environments'
|
122
|
-
# migrate: false
|
123
|
-
#
|
124
|
-
# Further information available here:
|
125
|
-
# https://support.cloud.engineyard.com/entries/20996661-customize-your-deployment-on-engine-yard-cloud
|
126
|
-
#
|
127
|
-
# NOTE: Please commit this file into your git repository.
|
128
|
-
#
|
129
|
-
HINTS
|
130
|
-
|
131
|
-
def ey_yml_comments
|
132
|
-
if @path.exist?
|
133
|
-
existing = @path.readlines.grep(/^#/).map {|line| line.strip }.join("\n")
|
134
|
-
else
|
135
|
-
EY_YML_HINTS
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def ensure_path
|
140
|
-
return if @path && @path.exist?
|
141
|
-
unless EY::Repo.exist?
|
142
|
-
raise "Not in application directory. Unable to save configuration."
|
143
|
-
end
|
144
|
-
if Pathname.new('config').exist?
|
145
|
-
@path = Pathname.new('config/ey.yml')
|
146
|
-
else
|
147
|
-
@path = Pathname.new('ey.yml')
|
148
|
-
end
|
149
|
-
@path
|
150
|
-
end
|
151
|
-
|
152
100
|
class EnvironmentConfig
|
153
101
|
attr_reader :name
|
154
102
|
|
@@ -162,28 +110,16 @@ module EY
|
|
162
110
|
@parent.path
|
163
111
|
end
|
164
112
|
|
165
|
-
def
|
166
|
-
|
167
|
-
|
113
|
+
def ensure_exists
|
114
|
+
unless path && path.exist?
|
115
|
+
raise EY::Error, "Please initialize this application with the following command:\n\tey init"
|
168
116
|
end
|
169
117
|
end
|
170
118
|
|
171
|
-
def
|
172
|
-
|
173
|
-
@parent.
|
174
|
-
else
|
175
|
-
@config[key.to_s] = val
|
176
|
-
@parent.set_environment_option(@name, key, val)
|
119
|
+
def fetch(key, default = nil, &block)
|
120
|
+
@config.fetch(key.to_s) do
|
121
|
+
@parent.fetch_from_defaults(key.to_s, default, &block)
|
177
122
|
end
|
178
|
-
val
|
179
|
-
end
|
180
|
-
|
181
|
-
def merge(other)
|
182
|
-
to_clean_hash.merge(other)
|
183
|
-
end
|
184
|
-
|
185
|
-
def to_clean_hash
|
186
|
-
@config.reject { |k,v| %w[branch migrate migration_command verbose].include?(k) }
|
187
123
|
end
|
188
124
|
|
189
125
|
def branch
|
@@ -191,22 +127,20 @@ module EY
|
|
191
127
|
end
|
192
128
|
|
193
129
|
def migrate
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
set('migrate', mig)
|
130
|
+
ensure_exists
|
131
|
+
fetch('migrate') do
|
132
|
+
raise EY::Error, "'migrate' not found in #{path}. Reinitialize with:\n\tey init"
|
133
|
+
end
|
199
134
|
end
|
200
135
|
|
201
136
|
def migration_command
|
202
|
-
|
137
|
+
ensure_exists
|
138
|
+
fetch('migration_command') do
|
139
|
+
raise EY::Error, "'migration_command' not found in #{path}. Reinitialize with:\n\tey init"
|
140
|
+
end
|
203
141
|
end
|
204
142
|
|
205
|
-
def migration_command=(cmd)
|
206
|
-
set('migration_command', cmd)
|
207
|
-
end
|
208
143
|
alias migrate_command migration_command
|
209
|
-
alias migrate_command= migration_command=
|
210
144
|
|
211
145
|
def verbose
|
212
146
|
fetch('verbose', false)
|