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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- N2Y4ZmE1ZGQ5MDEzMWJiZDhlZWI0NmJjNGM5MGUyYjE2YjRlNTVjNw==
4
+ MWMzMTAwYWJkYWMyYjcxNjFhZjc0OThjZDM5M2E1MTJkMzIwNTg4Yg==
5
5
  data.tar.gz: !binary |-
6
- NTA2OWMyYmY4MTUwZjU1MTI4MDkwMDY4MTk1ZTNhNGQ4YWUxNTM3NA==
6
+ NGM3OWVjYTI2ZWJmOGM5MzI3MjdiMjc3NDMzMTRiMmM3YTA4ZDFiNg==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- MTc2NTMzNWI1ODNiYzRkYzQ4MWJiOTMzMzY4NTAyMjdkMGQ0ZTc3MGYxM2Nh
10
- MzRjYWQ1ODFlZTY4Y2VkN2M2M2EzYjBmNzJiNzNiMjJjM2JlMzFiYmNjNTM5
11
- OGM3ODZiNTQxZjIwZjM2NTRkNjc4ODcxN2U1OTBhNmIxZjQ4MzQ=
9
+ ZGI4ZWRlNWE3NWIzZWE0MTc4ODBlMDcxNjllZTk3M2Y3NTE3ZmE3MDNjMzVk
10
+ ODgyOTc1ZjUzMjI2OGRhYTNmZmM4OGU3YzQzMGQxZmFiNGQ4ZTg5MWI4NzJi
11
+ NGY1M2Q1MWM4ODRhZWUyY2RkZjI2MzhjOTlhYTQzNzBjODgwMmM=
12
12
  data.tar.gz: !binary |-
13
- ODQ0OTY5NDQwZTVjMzc4N2ZmOGU1Y2E0YTMzMmJlYjgwOGUxZGQyZDc1MGUx
14
- ZWNiNjQ3NWE3NzIyMGYzNmNmNWU0ZThmNDMxZWZmYWRiNGFiZDBiNzQ3ZGFm
15
- NGE5NjA1OTliMDNiNDA1ZDVjZGZlODIxMGM3ODllNGU0ZjU1ZTI=
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. Here's an example ey.yml file in `ROOT/config/ey.yml`:
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
- bundle_without: test development mygroup # exclude groups on bundle install (leave blank to remove --without)
28
- bundle_options: --local # add extra options to the bundle install command line (does not override bundle_without)
29
- copy_exclude: # don't rsync the following dirs
30
- - .git
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: false # show maintenance page during migrations (default: true)
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: true # precompiles assets even if no changes would be detected (does not check for changes at all).
36
- asset_dependencies: app/assets # a list of relative paths to search for asset changes during each deploy.
37
- assets_strategy: shifting # choose an alternet asset management strategy (shifting, cleaning, private, shared)
38
- asset_roles: :all # specify on which roles to compile assets (default: [:app, :app_master, :solo] - must be an Array)
39
- asset_roles: # (Array input for multiple roles) - Use hook deploy/before_compile_assets.rb for finer grained control.
40
- - :app
41
- - :app_master
42
- - :util
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
- assets_strategy: shifting # choose an alternet asset management strategy (shifting, cleaning, private, shared)
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
- assets_strategy: private # Use an asset management that always refreshes, so staging enviroments don't get conflicts
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], defaults to 'rake db:migrate'; use --no-migrate to avoid running migrations
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
 
@@ -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'
@@ -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 API-TOKEN to authenticate this command"
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], defaults to '#{EY::DeployConfig::Migrate::DEFAULT}'; use --no-migrate to avoid running migrations"
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
- Option --all requires a command to be supplied and runs it on all servers.
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
- hosts = ssh_hosts(options, environment)
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
- raise NoCommandError.new if cmd.nil? and hosts.size != 1
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
- if options[:shell] && cmd
376
- cmd = Escape.shell_command([options[:shell],'-lc',cmd])
481
+ if options[:bind_address]
482
+ ssh_opts = ["-L", options[:bind_address]]
483
+ end
377
484
  end
378
485
 
379
- exits = hosts.map do |host|
380
- system Escape.shell_command(['ssh', "#{environment.username}@#{host}", cmd].compact)
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
- exit exits.detect {|status| !status.zero?} || 0
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.map { |instance| instance.public_hostname }
530
+ return instances
411
531
  end
412
532
  end
413
533
 
@@ -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
@@ -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
- attr_reader :path
12
+ def self.pathname_for_write
13
+ pathname || CONFIG_FILES.find{|pathname| pathname.dirname.exist? }
14
+ end
11
15
 
12
- def initialize(file = nil)
13
- @path = file ? Pathname.new(file) : CONFIG_FILES.find{|pathname| pathname.exist? }
14
- @config = @path ? YAML.load_file(@path.to_s) : {}
15
- @config ||= {} # load_file returns `false' when the file is empty
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
- unless Hash === @config
18
- raise "ey.yml load error: Expected a Hash but a #{@config.class.name} was returned."
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 fetch(key, default = nil, &block)
166
- @config.fetch(key.to_s) do
167
- @parent.fetch_from_defaults(key.to_s, default, &block)
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 set(key, val)
172
- if @config.empty? || !@config.has_key?(key.to_s)
173
- @parent.set_default_option(key, val)
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
- fetch('migrate')
195
- end
196
-
197
- def migrate=(mig)
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
- fetch('migration_command', nil)
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)