engineyard 2.3.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MDhjMDU3YzJhYWUzMzRkNjQyZWJlZGJiMjQ1OGQ2MDdmYTZjZDBmNw==
5
- data.tar.gz: !binary |-
6
- NmE3MWNiYjFlYzk1NDE3MmNlY2UxZjFkNTNkNGNlMDNhYTMzYzIzYQ==
2
+ SHA1:
3
+ metadata.gz: a21285072c40633408e1d024bb659a4afe81e032
4
+ data.tar.gz: c08bd05835ef584a8baee421bfd53b78ef4b5767
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- MWE0NjMyMmMzMDAzMzMzYzFjNTdiM2VkNDE2NmYzZWY3NjJmY2I3YzU0YWNi
10
- NWYyMGRhYzVlNThhODY1YWIwZjU2NmI0MGVmNDFlZmFlNDY2YWM5ZGE0ZGI1
11
- MDI1MzM1YTAyZDcxN2MyYjM1MDg3ODZhNzVmNjVkNDI5ZTQ5ZmQ=
12
- data.tar.gz: !binary |-
13
- YmU5ZDc5YzhiNWMzNTU2YWM3MTMyM2JjNDQ4M2ViYmIwNjU1ODE5YzlkZmYz
14
- MTU1ZmRlYTgyOWNhNDAxYzI5YTIyYjc5MTJhOGNiYWIwNDhjMzAyOTNiN2Y2
15
- ZWY1Mjk2Y2VmZmEzOTVhY2FkOTJjYmIzMWY2NWZhZDdjNjE3MjI=
6
+ metadata.gz: 211d35f2316b84133b6603c17ad18febb909f43617d4ce1c31b0fd425d7cd6f78a89c73a49f7f52ffb27c633aa41ad917d6428a012f2872902c8d95767476742
7
+ data.tar.gz: bac2d6e8a5b19a4b54a32f08121cae917540e730e5ddd065394e6f6691d1cbb9dd74d5e154ecdec0800d12181fd7529b790d7aa0444f263923c0880e7e6a3d50
@@ -20,7 +20,7 @@ module EY
20
20
  def self.start(given_args=ARGV, config={})
21
21
  Thor::Base.shell = EY::CLI::UI
22
22
  ui = EY::CLI::UI.new
23
- super(given_args, {:shell => ui}.merge(config))
23
+ super(given_args, {shell: ui}.merge(config))
24
24
  rescue Thor::Error, EY::Error, EY::CloudClient::Error => e
25
25
  ui.print_exception(e)
26
26
  raise
@@ -37,9 +37,9 @@ module EY
37
37
  raise
38
38
  end
39
39
 
40
- class_option :api_token, :type => :string, :desc => "Use API_TOKEN to authenticate this command"
41
- class_option :serverside_version, :type => :string, :desc => "Please use with care! Override deploy system version (same as ENV variable ENGINEYARD_SERVERSIDE_VERSION)"
42
- class_option :quiet, :aliases => %w[-q], :type => :boolean, :desc => "Quieter CLI output."
40
+ class_option :api_token, type: :string, desc: "Use API_TOKEN to authenticate this command"
41
+ class_option :serverside_version, type: :string, desc: "Please use with care! Override deploy system version (same as ENV variable ENGINEYARD_SERVERSIDE_VERSION)"
42
+ class_option :quiet, aliases: %w[-q], type: :boolean, desc: "Quieter CLI output."
43
43
 
44
44
  desc "init",
45
45
  "Initialize the current directory with an ey.yml configuration file."
@@ -53,8 +53,8 @@ module EY
53
53
  IMPORTANT: THE GENERATED FILE '#{EY::Config.pathname_for_write}'
54
54
  MUST BE COMMITTED TO YOUR REPOSITORY OR OPTIONS WILL NOT BE LOADED.
55
55
  DESC
56
- method_option :path, :type => :string, :aliases => %w(-p),
57
- :desc => "Path for ey.yml (supported paths: #{EY::Config::CONFIG_FILES.join(', ')})"
56
+ method_option :path, type: :string, aliases: %w(-p),
57
+ desc: "Path for ey.yml (supported paths: #{EY::Config::CONFIG_FILES.join(', ')})"
58
58
  def init
59
59
  unless EY::Repo.exist?
60
60
  raise EY::Error, "Working directory is not a repository. Aborting."
@@ -96,30 +96,30 @@ Go look at it, then add it to your repository!
96
96
  specifying --migrate or --migrate 'rake db:migrate'.
97
97
  Migrations can also be skipped by using --no-migrate.
98
98
  DESC
99
- method_option :ignore_bad_master, :type => :boolean, :aliases => %w(--ignore-bad-bridge),
100
- :desc => "Force a deploy even if the master is in a bad state"
101
- method_option :migrate, :type => :string, :aliases => %w(-m),
102
- :lazy_default => true,
103
- :desc => "Run migrations via [MIGRATE]; use --no-migrate to avoid running migrations"
104
- method_option :ref, :type => :string, :aliases => %w(-r --branch --tag),
105
- :required => true, :default => '',
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."
107
- method_option :force_ref, :type => :string, :aliases => %w(--ignore-default-branch -R),
108
- :lazy_default => true,
109
- :desc => "Force a deploy of the specified git ref even if a default is set in ey.yml."
110
- method_option :environment, :type => :string, :aliases => %w(-e),
111
- :required => true, :default => false,
112
- :desc => "Environment in which to deploy this application"
113
- method_option :app, :type => :string, :aliases => %w(-a),
114
- :required => true, :default => '',
115
- :desc => "Name of the application to deploy"
116
- method_option :account, :type => :string, :aliases => %w(-c),
117
- :required => true, :default => '',
118
- :desc => "Name of the account in which the environment can be found"
119
- method_option :verbose, :type => :boolean, :aliases => %w(-v),
120
- :desc => "Be verbose"
121
- method_option :config, :type => :hash, :default => {}, :aliases => %w(--extra-deploy-hook-options),
122
- :desc => "Hash made available in deploy hooks (in the 'config' hash), can also override some ey.yml settings."
99
+ method_option :ignore_bad_master, type: :boolean, aliases: %w(--ignore-bad-bridge),
100
+ desc: "Force a deploy even if the master is in a bad state"
101
+ method_option :migrate, type: :string, aliases: %w(-m),
102
+ lazy_default: true,
103
+ desc: "Run migrations via [MIGRATE]; use --no-migrate to avoid running migrations"
104
+ method_option :ref, type: :string, aliases: %w(-r --branch --tag),
105
+ required: true, default: '',
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."
107
+ method_option :force_ref, type: :string, aliases: %w(--ignore-default-branch -R),
108
+ lazy_default: true,
109
+ desc: "Force a deploy of the specified git ref even if a default is set in ey.yml."
110
+ method_option :environment, type: :string, aliases: %w(-e),
111
+ required: true, default: false,
112
+ desc: "Environment in which to deploy this application"
113
+ method_option :app, type: :string, aliases: %w(-a),
114
+ required: true, default: '',
115
+ desc: "Name of the application to deploy"
116
+ method_option :account, type: :string, aliases: %w(-c),
117
+ required: true, default: '',
118
+ desc: "Name of the account in which the environment can be found"
119
+ method_option :verbose, type: :boolean, aliases: %w(-v),
120
+ desc: "Be verbose"
121
+ method_option :config, type: :hash, default: {}, aliases: %w(--extra-deploy-hook-options),
122
+ desc: "Hash made available in deploy hooks (in the 'config' hash), can also override some ey.yml settings."
123
123
  def deploy
124
124
  app_env = fetch_app_environment(options[:app], options[:environment], options[:account])
125
125
 
@@ -127,11 +127,11 @@ Go look at it, then add it to your repository!
127
127
  deploy_config = EY::DeployConfig.new(options, env_config, repo, ui)
128
128
 
129
129
  deployment = app_env.new_deployment({
130
- :ref => deploy_config.ref,
131
- :migrate => deploy_config.migrate,
132
- :migrate_command => deploy_config.migrate_command,
133
- :extra_config => deploy_config.extra_config,
134
- :serverside_version => serverside_version,
130
+ ref: deploy_config.ref,
131
+ migrate: deploy_config.migrate,
132
+ migrate_command: deploy_config.migrate_command,
133
+ extra_config: deploy_config.extra_config,
134
+ serverside_version: serverside_version,
135
135
  })
136
136
 
137
137
  runner = serverside_runner(app_env, deploy_config.verbose, deployment.serverside_version, options[:ignore_bad_master])
@@ -204,15 +204,15 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
204
204
  deployment as failed. Only run this when a deployment is known to be
205
205
  wrongly unfinished/stuck and when further deployments are blocked.
206
206
  DESC
207
- method_option :environment, :type => :string, :aliases => %w(-e),
208
- :required => true, :default => false,
209
- :desc => "Environment in which to deploy this application"
210
- method_option :app, :type => :string, :aliases => %w(-a),
211
- :required => true, :default => '',
212
- :desc => "Name of the application to deploy"
213
- method_option :account, :type => :string, :aliases => %w(-c),
214
- :required => true, :default => '',
215
- :desc => "Name of the account in which the environment can be found"
207
+ method_option :environment, type: :string, aliases: %w(-e),
208
+ required: true, default: false,
209
+ desc: "Environment in which to deploy this application"
210
+ method_option :app, type: :string, aliases: %w(-a),
211
+ required: true, default: '',
212
+ desc: "Name of the application to deploy"
213
+ method_option :account, type: :string, aliases: %w(-c),
214
+ required: true, default: '',
215
+ desc: "Name of the account in which the environment can be found"
216
216
  def timeout_deploy
217
217
  app_env = fetch_app_environment(options[:app], options[:environment], options[:account])
218
218
  deployment = app_env.last_deployment
@@ -235,15 +235,15 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
235
235
  Show the current status of most recent deployment of the specified
236
236
  application and environment.
237
237
  DESC
238
- method_option :environment, :type => :string, :aliases => %w(-e),
239
- :required => true, :default => '',
240
- :desc => "Environment where the application is deployed"
241
- method_option :app, :type => :string, :aliases => %w(-a),
242
- :required => true, :default => '',
243
- :desc => "Name of the application"
244
- method_option :account, :type => :string, :aliases => %w(-c),
245
- :required => true, :default => '',
246
- :desc => "Name of the account in which the application can be found"
238
+ method_option :environment, type: :string, aliases: %w(-e),
239
+ required: true, default: '',
240
+ desc: "Environment where the application is deployed"
241
+ method_option :app, type: :string, aliases: %w(-a),
242
+ required: true, default: '',
243
+ desc: "Name of the application"
244
+ method_option :account, type: :string, aliases: %w(-c),
245
+ required: true, default: '',
246
+ desc: "Name of the account in which the application can be found"
247
247
  def status
248
248
  app_env = fetch_app_environment(options[:app], options[:environment], options[:account])
249
249
  deployment = app_env.last_deployment
@@ -260,19 +260,19 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
260
260
  display all environments, including those for this app.
261
261
  DESC
262
262
 
263
- method_option :all, :type => :boolean, :aliases => %(-A),
264
- :desc => "Show all environments (ignores --app, --account, and --environment arguments)"
265
- method_option :simple, :type => :boolean, :aliases => %(-s),
266
- :desc => "Display one environment per line with no extra output"
267
- method_option :app, :type => :string, :aliases => %w(-a),
268
- :required => true, :default => '',
269
- :desc => "Show environments for this application"
270
- method_option :account, :type => :string, :aliases => %w(-c),
271
- :required => true, :default => '',
272
- :desc => "Show environments in this account"
273
- method_option :environment, :type => :string, :aliases => %w(-e),
274
- :required => true, :default => '',
275
- :desc => "Show environments matching environment name"
263
+ method_option :all, type: :boolean, aliases: %(-A),
264
+ desc: "Show all environments (ignores --app, --account, and --environment arguments)"
265
+ method_option :simple, type: :boolean, aliases: %(-s),
266
+ desc: "Display one environment per line with no extra output"
267
+ method_option :app, type: :string, aliases: %w(-a),
268
+ required: true, default: '',
269
+ desc: "Show environments for this application"
270
+ method_option :account, type: :string, aliases: %w(-c),
271
+ required: true, default: '',
272
+ desc: "Show environments in this account"
273
+ method_option :environment, type: :string, aliases: %w(-e),
274
+ required: true, default: '',
275
+ desc: "Show environments matching environment name"
276
276
  def environments
277
277
  if options[:all] && options[:simple]
278
278
  ui.print_simple_envs api.environments
@@ -286,10 +286,10 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
286
286
  end
287
287
 
288
288
  resolver = api.resolve_app_environments({
289
- :account_name => options[:account],
290
- :app_name => options[:app],
291
- :environment_name => options[:environment],
292
- :remotes => remotes,
289
+ account_name: options[:account],
290
+ app_name: options[:app],
291
+ environment_name: options[:environment],
292
+ remotes: remotes,
293
293
  })
294
294
 
295
295
  resolver.no_matches do |errors|
@@ -322,18 +322,32 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
322
322
  or -uS (--user --host) to output bash loop friendly "user@hostname"
323
323
  DESC
324
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"
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
+ method_option :all, type: :boolean, aliases: %(-A),
338
+ desc: "Show all servers (for compatibility only, this is the default for this command)"
339
+ method_option :app_master, type: :boolean,
340
+ desc: "Show only app master server"
341
+ method_option :app_servers, type: :boolean, aliases: %w(--app),
342
+ desc: "Show only application servers"
343
+ method_option :db_servers, type: :boolean, aliases: %w(--db),
344
+ desc: "Show only database servers"
345
+ method_option :db_master, type: :boolean,
346
+ desc: "Show only the master database server"
347
+ method_option :db_slaves, type: :boolean,
348
+ desc: "Show only the slave database servers"
349
+ method_option :utilities, type: :array, lazy_default: true, aliases: %w(--util),
350
+ desc: "Show only utility servers or only utility servers with the given names"
337
351
  def servers
338
352
  if options[:environment] == '' && options[:account] == ''
339
353
  repo.fail_on_no_remotes!
@@ -345,7 +359,8 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
345
359
  end
346
360
 
347
361
  username = options[:user] && environment.username
348
- servers = environment.instances
362
+
363
+ servers = filter_servers(environment, options, default: {all: true})
349
364
 
350
365
  if options[:host]
351
366
  ui.print_hostnames(servers, username)
@@ -367,12 +382,12 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
367
382
  successfully completed.
368
383
  DESC
369
384
 
370
- method_option :environment, :type => :string, :aliases => %w(-e),
371
- :required => true, :default => '',
372
- :desc => "Environment to rebuild"
373
- method_option :account, :type => :string, :aliases => %w(-c),
374
- :required => true, :default => '',
375
- :desc => "Name of the account in which the environment can be found"
385
+ method_option :environment, type: :string, aliases: %w(-e),
386
+ required: true, default: '',
387
+ desc: "Environment to rebuild"
388
+ method_option :account, type: :string, aliases: %w(-c),
389
+ required: true, default: '',
390
+ desc: "Name of the account in which the environment can be found"
376
391
  def rebuild
377
392
  environment = fetch_environment(options[:environment], options[:account])
378
393
  ui.info "Updating instances on #{environment.hierarchy_name}"
@@ -386,19 +401,19 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
386
401
  remote server(s) to restart application servers.
387
402
  DESC
388
403
 
389
- method_option :environment, :type => :string, :aliases => %w(-e),
390
- :required => true, :default => '',
391
- :desc => "Environment in which to roll back the application"
392
- method_option :app, :type => :string, :aliases => %w(-a),
393
- :required => true, :default => '',
394
- :desc => "Name of the application to roll back"
395
- method_option :account, :type => :string, :aliases => %w(-c),
396
- :required => true, :default => '',
397
- :desc => "Name of the account in which the environment can be found"
398
- method_option :verbose, :type => :boolean, :aliases => %w(-v),
399
- :desc => "Be verbose"
400
- method_option :config, :type => :hash, :default => {}, :aliases => %w(--extra-deploy-hook-options),
401
- :desc => "Hash made available in deploy hooks (in the 'config' hash), can also override some ey.yml settings."
404
+ method_option :environment, type: :string, aliases: %w(-e),
405
+ required: true, default: '',
406
+ desc: "Environment in which to roll back the application"
407
+ method_option :app, type: :string, aliases: %w(-a),
408
+ required: true, default: '',
409
+ desc: "Name of the application to roll back"
410
+ method_option :account, type: :string, aliases: %w(-c),
411
+ required: true, default: '',
412
+ desc: "Name of the account in which the environment can be found"
413
+ method_option :verbose, type: :boolean, aliases: %w(-v),
414
+ desc: "Be verbose"
415
+ method_option :config, type: :hash, default: {}, aliases: %w(--extra-deploy-hook-options),
416
+ desc: "Hash made available in deploy hooks (in the 'config' hash), can also override some ey.yml settings."
402
417
  def rollback
403
418
  app_env = fetch_app_environment(options[:app], options[:environment], options[:account])
404
419
  env_config = config.environment_config(app_env.environment_name)
@@ -421,7 +436,7 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
421
436
  desc "ssh [COMMAND] [--all] [--environment ENVIRONMENT]", "Open an ssh session to the master app server, or run a command."
422
437
  long_desc <<-DESC
423
438
  If a command is supplied, it will be run, otherwise a session will be
424
- opened. The application master is used for environments with clusters.
439
+ opened. The bridge server (app master) is used for environments with multiple instances.
425
440
 
426
441
  Option --all requires a command to be supplied and runs it on all servers or
427
442
  pass --each to connect to each server one after another.
@@ -431,36 +446,37 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
431
446
 
432
447
  $ #{banner_base} ssh "rm -f /some/file" -e my-environment --all
433
448
  DESC
434
- method_option :environment, :type => :string, :aliases => %w(-e),
435
- :required => true, :default => '',
436
- :desc => "Environment to ssh into"
437
- method_option :account, :type => :string, :aliases => %w(-c),
438
- :required => true, :default => '',
439
- :desc => "Name of the account in which the environment can be found"
440
- method_option :all, :type => :boolean, :aliases => %(-A),
441
- :desc => "Run command on all servers"
442
- method_option :app_servers, :type => :boolean,
443
- :desc => "Run command on all application servers"
444
- method_option :db_servers, :type => :boolean,
445
- :desc => "Run command on the database servers"
446
- method_option :db_master, :type => :boolean,
447
- :desc => "Run command on the master database server"
448
- method_option :db_slaves, :type => :boolean,
449
- :desc => "Run command on the slave database servers"
450
- method_option :utilities, :type => :array, :lazy_default => true,
451
- :desc => "Run command on the utility servers with the given names. If no names are given, run on all utility servers."
452
- method_option :shell, :type => :string, :default => 'bash', :aliases => %w(-s),
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."
449
+ method_option :environment, type: :string, aliases: %w(-e),
450
+ required: true, default: '',
451
+ desc: "Environment to ssh into"
452
+ method_option :account, type: :string, aliases: %w(-c),
453
+ required: true, default: '',
454
+ desc: "Name of the account in which the environment can be found"
455
+ method_option :all, type: :boolean, aliases: %(-A),
456
+ desc: "Run command on all servers"
457
+ method_option :app_servers, type: :boolean,
458
+ desc: "Run command on all application servers"
459
+ method_option :db_servers, type: :boolean,
460
+ desc: "Run command on the database servers"
461
+ method_option :db_master, type: :boolean,
462
+ desc: "Run command on the master database server"
463
+ method_option :db_slaves, type: :boolean,
464
+ desc: "Run command on the slave database servers"
465
+ method_option :utilities, type: :array, lazy_default: true,
466
+ desc: "Run command on the utility servers with the given names. If no names are given, run on all utility servers."
467
+ method_option :shell, type: :string, default: 'bash', aliases: %w(-s),
468
+ desc: "Run command in a shell other than bash. Use --no-shell to run the command without a shell."
469
+ method_option :pty, type: :boolean, default: false, aliases: %w(-t),
470
+ desc: "If a command is given, run in a pty. Required for interactive commands like sudo."
471
+ method_option :bind_address, type: :string, aliases: %w(-L),
472
+ desc: "When a command is not given, pass -L to the ssh command."
473
+ method_option :each, type: :boolean, default: false,
474
+ desc: "If no command is given, connect to multiple servers each one after another, instead of exiting with an error."
460
475
 
461
476
  def ssh(cmd=nil)
462
477
  environment = fetch_environment(options[:environment], options[:account])
463
- instances = ssh_hosts(options, environment)
478
+ instances = filter_servers(environment, options, default: {app_master: true})
479
+ user = environment.username
464
480
  ssh_opts = []
465
481
 
466
482
  if cmd
@@ -488,7 +504,8 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
488
504
 
489
505
  trap(:INT) { abort "Aborting..." }
490
506
 
491
- exits = instances.map do |instance|
507
+ exits = []
508
+ instances.each do |instance|
492
509
  host = instance.public_hostname
493
510
  name = instance.name ? "#{instance.role} (#{instance.name})" : instance.role
494
511
  ui.info "\nConnecting to #{name} #{host}..."
@@ -496,37 +513,122 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
496
513
  ui.info "Ctrl + C to abort"
497
514
  sleep 1.3
498
515
  end
499
- system Escape.shell_command((ssh_cmd + ["#{environment.username}@#{host}"] + [cmd]).compact)
500
- $?.exitstatus
516
+ sshcmd = Escape.shell_command((ssh_cmd + ["#{user}@#{host}"] + [cmd]).compact)
517
+ ui.debug "$ #{sshcmd}"
518
+ system sshcmd
519
+ exits << $?.exitstatus
501
520
  end
502
521
 
503
522
  exit exits.detect {|status| status != 0 } || 0
504
523
  end
505
524
 
506
- no_tasks do
507
- def ssh_host_filter(opts)
508
- return lambda {|instance| true } if opts[:all]
509
- return lambda {|instance| %w(solo app app_master ).include?(instance.role) } if opts[:app_servers]
510
- return lambda {|instance| %w(solo db_master db_slave).include?(instance.role) } if opts[:db_servers ]
511
- return lambda {|instance| %w(solo db_master ).include?(instance.role) } if opts[:db_master ]
512
- return lambda {|instance| %w(db_slave ).include?(instance.role) } if opts[:db_slaves ]
513
- return lambda {|instance| %w(util).include?(instance.role) && opts[:utilities].include?(instance.name) } if opts[:utilities]
514
- return lambda {|instance| %w(solo app_master ).include?(instance.role) }
525
+ desc "scp [FROM_PATH] [TO_PATH] [--all] [--environment ENVIRONMENT]", "scp a file to/from multiple servers in an environment"
526
+ long_desc <<-DESC
527
+ Use the system `scp` command to copy files to some or all of the servers.
528
+
529
+ If `HOST:` is found in the FROM_PATH or TO_PATH, the server name will be
530
+ substituted in place of `HOST:` when scp is run. This allows you to scp in
531
+ either direction by putting `HOST:` in the FROM_PATH or TO_PATH, as follows:
532
+
533
+ $ #{banner_base} scp example.json HOST:/data/app_name/current/config/ -e env --app-servers
534
+
535
+ $ #{banner_base} scp HOST:/data/app_name/current/config/example.json ./ -e env --app-servers
536
+
537
+ If `HOST:` is not specified, TO_PATH will be used as the remote path.
538
+ Be sure to escape shell words so they don't expand locally (e.g. '~').
539
+
540
+ Note: this command is a bit picky about its ordering. FROM_PATH TO_PATH
541
+ must follow immediately after `ey scp` with no flags in between.
542
+ DESC
543
+ method_option :environment, :type => :string, :aliases => %w(-e),
544
+ :required => true, :default => '',
545
+ :desc => "Name of the destination environment"
546
+ method_option :account, :type => :string, :aliases => %w(-c),
547
+ :required => true, :default => '',
548
+ :desc => "Name of the account in which the environment can be found"
549
+ method_option :all, :type => :boolean, :aliases => %(-A),
550
+ :desc => "scp to all servers"
551
+ method_option :app_servers, :type => :boolean,
552
+ :desc => "scp to all application servers"
553
+ method_option :db_servers, :type => :boolean,
554
+ :desc => "scp to database servers"
555
+ method_option :db_master, :type => :boolean,
556
+ :desc => "scp to the master database server"
557
+ method_option :db_slaves, :type => :boolean,
558
+ :desc => "scp to the slave database servers"
559
+ method_option :utilities, :type => :array, :lazy_default => true,
560
+ :desc => "scp to all utility servers or only those with the given names"
561
+
562
+ def scp(from_path, to_path)
563
+ environment = fetch_environment(options[:environment], options[:account])
564
+ instances = filter_servers(environment, options, default: {app_master: true})
565
+ user = environment.username
566
+
567
+ ui.info "Copying '#{from_path}' to '#{to_path}' on #{instances.count} server#{instances.count == 1 ? '' : 's'} serially..."
568
+
569
+ # default to `scp FROM_PATH HOST:TO_PATH`
570
+ unless [from_path, to_path].detect { |path| path =~ /HOST:/ }
571
+ to_path = "HOST:#{to_path}"
515
572
  end
516
573
 
517
- def ssh_hosts(opts, environment)
518
- if opts[:utilities] and not opts[:utilities].respond_to?(:include?)
519
- includes_everything = []
520
- class << includes_everything
521
- def include?(*) true end
522
- end
523
- filter = ssh_host_filter(opts.merge(:utilities => includes_everything))
574
+ exits = []
575
+ instances.each do |instance|
576
+ host = instance.public_hostname
577
+ authority = "#{user}@#{host}:"
578
+
579
+ name = instance.name ? "#{instance.role} (#{instance.name})" : instance.role
580
+ ui.info "# #{name} #{host}"
581
+
582
+ from = from_path.sub(/^HOST:/, authority)
583
+ to = to_path.sub(/^HOST:/, authority)
584
+
585
+ cmd = Escape.shell_command(["scp", from, to])
586
+ ui.debug "$ #{cmd}"
587
+ system cmd
588
+ exits << $?.exitstatus
589
+ end
590
+
591
+ exit exits.detect {|status| status != 0 } || 0
592
+ end
593
+
594
+ no_tasks do
595
+ OPT_TO_ROLES = {
596
+ all: %w[all],
597
+ app_master: %w[solo app_master],
598
+ app_servers: %w[solo app app_master],
599
+ db_servers: %w[solo db_master db_slave],
600
+ db_master: %w[solo db_master],
601
+ db_slaves: %w[db_slave],
602
+ utilities: %w[util],
603
+ }
604
+
605
+ def filter_servers(environment, cli_opts, filter_opts)
606
+ if (cli_opts.keys.map(&:to_sym) & OPT_TO_ROLES.keys).any?
607
+ options = cli_opts.dup
608
+ else
609
+ options = filter_opts[:default].dup
610
+ end
611
+
612
+ options.keep_if {|k,v| OPT_TO_ROLES.has_key?(k.to_sym) }
613
+
614
+ if options[:all]
615
+ instances = environment.instances
524
616
  else
525
- filter = ssh_host_filter(opts)
617
+ roles = {}
618
+ options.each do |cli_opt,cli_val|
619
+ if cli_val && OPT_TO_ROLES.has_key?(cli_opt.to_sym)
620
+ OPT_TO_ROLES[cli_opt.to_sym].each do |role|
621
+ roles[role] = cli_val # val is true or an array of strings
622
+ end
623
+ end
624
+ end
625
+ instances = environment.select_instances(roles)
626
+ end
627
+
628
+ if instances.empty?
629
+ raise NoInstancesError.new(environment.name)
526
630
  end
527
631
 
528
- instances = environment.instances.select {|instance| filter[instance] }
529
- raise NoInstancesError.new(environment.name) if instances.empty?
530
632
  return instances
531
633
  end
532
634
  end
@@ -537,12 +639,12 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
537
639
  recipes were uploaded to the environment & run, their logs will also be
538
640
  displayed beneath the main configuration logs.
539
641
  DESC
540
- method_option :environment, :type => :string, :aliases => %w(-e),
541
- :required => true, :default => '',
542
- :desc => "Environment with the interesting logs"
543
- method_option :account, :type => :string, :aliases => %w(-c),
544
- :required => true, :default => '',
545
- :desc => "Name of the account in which the environment can be found"
642
+ method_option :environment, type: :string, aliases: %w(-e),
643
+ required: true, default: '',
644
+ desc: "Environment with the interesting logs"
645
+ method_option :account, type: :string, aliases: %w(-c),
646
+ required: true, default: '',
647
+ desc: "Name of the account in which the environment can be found"
546
648
  def logs
547
649
  environment = fetch_environment(options[:environment], options[:account])
548
650
  environment.logs.each do |log|
@@ -618,15 +720,15 @@ WARNING: Interrupting again may prevent Engine Yard Cloud from recording this
618
720
  end
619
721
 
620
722
  desc "launch [--app APP] [--environment ENVIRONMENT] [--account ACCOUNT]", "Open application in browser."
621
- method_option :environment, :type => :string, :aliases => %w(-e),
622
- :required => true, :default => '',
623
- :desc => "Environment where the application is deployed"
624
- method_option :app, :type => :string, :aliases => %w(-a),
625
- :required => true, :default => '',
626
- :desc => "Name of the application"
627
- method_option :account, :type => :string, :aliases => %w(-c),
628
- :required => true, :default => '',
629
- :desc => "Name of the account in which the application can be found"
723
+ method_option :environment, type: :string, aliases: %w(-e),
724
+ required: true, default: '',
725
+ desc: "Environment where the application is deployed"
726
+ method_option :app, type: :string, aliases: %w(-a),
727
+ required: true, default: '',
728
+ desc: "Name of the application"
729
+ method_option :account, type: :string, aliases: %w(-c),
730
+ required: true, default: '',
731
+ desc: "Name of the account in which the application can be found"
630
732
  def launch
631
733
  app_env = fetch_app_environment(options[:app], options[:environment], options[:account])
632
734
  Launchy.open(app_env.uri)