engineyard-serverside 2.7.8pre2 → 2.8.0.pre

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.
Files changed (96) hide show
  1. data/bin/engineyard-serverside +1 -1
  2. data/bin/engineyard-serverside-execute-hook +1 -1
  3. data/bin/engineyard-serverside-execute-service-hook +35 -0
  4. data/lib/engineyard-serverside.rb +0 -1
  5. data/lib/engineyard-serverside/about.rb +11 -8
  6. data/lib/engineyard-serverside/callbacks.rb +11 -0
  7. data/lib/engineyard-serverside/callbacks/collection.rb +17 -0
  8. data/lib/engineyard-serverside/callbacks/collection/base.rb +79 -0
  9. data/lib/engineyard-serverside/callbacks/collection/combined.rb +45 -0
  10. data/lib/engineyard-serverside/callbacks/collection/deploy_hooks.rb +21 -0
  11. data/lib/engineyard-serverside/callbacks/collection/service_hooks.rb +17 -0
  12. data/lib/engineyard-serverside/callbacks/collection/service_hooks/collection.rb +24 -0
  13. data/lib/engineyard-serverside/callbacks/collection/service_hooks/combined.rb +40 -0
  14. data/lib/engineyard-serverside/callbacks/distributor.rb +21 -0
  15. data/lib/engineyard-serverside/callbacks/distributor/remote.rb +76 -0
  16. data/lib/engineyard-serverside/callbacks/distributor/viability_filter.rb +66 -0
  17. data/lib/engineyard-serverside/callbacks/executor.rb +23 -0
  18. data/lib/engineyard-serverside/callbacks/executor/base.rb +44 -0
  19. data/lib/engineyard-serverside/callbacks/executor/executable.rb +123 -0
  20. data/lib/engineyard-serverside/callbacks/executor/ruby.rb +20 -0
  21. data/lib/engineyard-serverside/callbacks/executor/ruby/context.rb +81 -0
  22. data/lib/engineyard-serverside/callbacks/executor/ruby/executor.rb +118 -0
  23. data/{spec/fixtures/gitrepo/bar → lib/engineyard-serverside/callbacks/hooks.rb} +0 -0
  24. data/lib/engineyard-serverside/callbacks/hooks/app.rb +21 -0
  25. data/lib/engineyard-serverside/callbacks/hooks/base.rb +43 -0
  26. data/lib/engineyard-serverside/callbacks/hooks/service.rb +28 -0
  27. data/lib/engineyard-serverside/callbacks/service_hook.rb +20 -0
  28. data/lib/engineyard-serverside/cli.rb +4 -225
  29. data/lib/engineyard-serverside/cli/app.rb +136 -0
  30. data/lib/engineyard-serverside/cli/helpers.rb +58 -0
  31. data/lib/engineyard-serverside/cli/server_hash_extractor.rb +49 -0
  32. data/lib/engineyard-serverside/cli/workflows.rb +45 -0
  33. data/lib/engineyard-serverside/cli/workflows/base.rb +78 -0
  34. data/lib/engineyard-serverside/cli/workflows/calling_deploy_hooks.rb +31 -0
  35. data/lib/engineyard-serverside/cli/workflows/deploying_applications.rb +28 -0
  36. data/lib/engineyard-serverside/cli/workflows/disabling_maintenance.rb +29 -0
  37. data/lib/engineyard-serverside/cli/workflows/enabling_maintenance.rb +29 -0
  38. data/lib/engineyard-serverside/cli/workflows/errors.rb +13 -0
  39. data/lib/engineyard-serverside/cli/workflows/helpers.rb +21 -0
  40. data/lib/engineyard-serverside/cli/workflows/integrating_servers.rb +71 -0
  41. data/lib/engineyard-serverside/cli/workflows/restarting_applications.rb +36 -0
  42. data/lib/engineyard-serverside/cli/workflows/rolling_back_applications.rb +28 -0
  43. data/lib/engineyard-serverside/cli/workflows/showing_maintenance_status.rb +28 -0
  44. data/lib/engineyard-serverside/configuration.rb +1 -0
  45. data/lib/engineyard-serverside/dependency_manager/bundler.rb +46 -18
  46. data/lib/engineyard-serverside/dependency_manager/npm.rb +12 -1
  47. data/lib/engineyard-serverside/deploy.rb +7 -45
  48. data/lib/engineyard-serverside/maintenance.rb +1 -9
  49. data/lib/engineyard-serverside/paths.rb +11 -0
  50. data/lib/engineyard-serverside/propagator.rb +59 -0
  51. data/lib/engineyard-serverside/rails_assets.rb +2 -1
  52. data/lib/engineyard-serverside/slug.rb +7 -0
  53. data/lib/engineyard-serverside/slug/distributor.rb +58 -0
  54. data/lib/engineyard-serverside/slug/enabler.rb +100 -0
  55. data/lib/engineyard-serverside/slug/failure_handler.rb +24 -0
  56. data/lib/engineyard-serverside/slug/finalizer.rb +86 -0
  57. data/lib/engineyard-serverside/slug/generator.rb +29 -0
  58. data/lib/engineyard-serverside/slug/migrator.rb +41 -0
  59. data/lib/engineyard-serverside/slug/restarter.rb +103 -0
  60. data/lib/engineyard-serverside/slug/source.rb +16 -0
  61. data/lib/engineyard-serverside/slug/source/updater.rb +194 -0
  62. data/lib/engineyard-serverside/version.rb +1 -1
  63. data/lib/railway.rb +43 -0
  64. data/lib/result.rb +7 -0
  65. data/lib/result/base.rb +41 -0
  66. data/lib/result/dsl.rb +16 -0
  67. data/lib/result/failure.rb +29 -0
  68. data/lib/result/success.rb +24 -0
  69. data/lib/runner.rb +34 -0
  70. data/spec/archive_deploy_spec.rb +1 -1
  71. data/spec/bundler_deploy_spec.rb +22 -1
  72. data/spec/configuration_spec.rb +1 -0
  73. data/spec/deploy_hook_spec.rb +148 -132
  74. data/spec/fixtures/lockfiles/1.15.1-no-bundler +51 -0
  75. data/spec/fixtures/repos/assets_error/Gemfile +5 -0
  76. data/spec/fixtures/repos/assets_error/Gemfile.lock +88 -0
  77. data/spec/fixtures/repos/assets_error/README +1 -0
  78. data/spec/fixtures/repos/assets_error/Rakefile +4 -0
  79. data/spec/fixtures/{gitrepo/foo → repos/assets_error/app/assets/empty} +0 -0
  80. data/spec/fixtures/repos/assets_error/config/application.rb +5 -0
  81. data/spec/fixtures/repos/assets_error/config/ey.yml +4 -0
  82. data/spec/fixtures/repos/bundler_old/Gemfile +5 -0
  83. data/spec/fixtures/repos/bundler_old/Gemfile.lock +15 -0
  84. data/spec/fixtures/repos/bundler_old/README +1 -0
  85. data/spec/fixtures/repos/no_ey_config_no_warning/Gemfile +3 -0
  86. data/spec/fixtures/repos/no_ey_config_no_warning/Gemfile.lock +10 -0
  87. data/spec/fixtures/repos/no_ey_config_no_warning/README +1 -0
  88. data/spec/fixtures/repos/no_ey_config_no_warning/ey.yml +5 -0
  89. data/spec/lockfile_parser_spec.rb +5 -1
  90. data/spec/rails31_deploy_spec.rb +8 -0
  91. data/spec/rollback_spec.rb +1 -1
  92. data/spec/services_deploy_spec.rb +12 -0
  93. data/spec/spec_helper.rb +14 -8
  94. metadata +488 -429
  95. data/lib/engineyard-serverside/cli_helpers.rb +0 -53
  96. data/lib/engineyard-serverside/deploy_hook.rb +0 -142
@@ -0,0 +1,58 @@
1
+ module EY
2
+ module Serverside
3
+ module CLI
4
+
5
+ # Helpers is a set of methods that define options and such for an App
6
+ # task
7
+ module Helpers
8
+ def account_app_env_options
9
+ method_option :app, :type => :string,
10
+ :required => true,
11
+ :desc => "Application to deploy",
12
+ :aliases => %w[-a --app-name]
13
+ method_option :environment_name, :type => :string,
14
+ :required => true,
15
+ :desc => "Environment name"
16
+ method_option :account_name, :type => :string,
17
+ :required => true,
18
+ :desc => "Account name"
19
+ end
20
+
21
+ def framework_env_option
22
+ method_option :framework_env, :type => :string,
23
+ :required => true,
24
+ :desc => "Ruby web framework environment",
25
+ :aliases => ["-e"]
26
+ end
27
+
28
+ def stack_option
29
+ method_option :stack, :type => :string,
30
+ :desc => "Web stack (so we can restart it correctly)"
31
+ end
32
+
33
+
34
+ def config_option
35
+ method_option :config, :type => :string,
36
+ :desc => "Additional configuration"
37
+ end
38
+
39
+ def instances_options
40
+ method_option :instances, :type => :array,
41
+ :desc => "Hostnames of instances to deploy to, e.g. --instances localhost app1 app2"
42
+ method_option :instance_roles, :type => :hash,
43
+ :default => {},
44
+ :desc => "Roles of instances, keyed on hostname, comma-separated. e.g. instance1:app_master,etc instance2:db,memcached ..."
45
+ method_option :instance_names, :type => :hash,
46
+ :default => {},
47
+ :desc => "Instance names, keyed on hostname. e.g. instance1:name1 instance2:name2"
48
+ end
49
+
50
+ def verbose_option
51
+ method_option :verbose, :type => :boolean,
52
+ :desc => "Verbose output",
53
+ :aliases => ["-v"]
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,49 @@
1
+ module EY
2
+ module Serverside
3
+ module CLI
4
+
5
+ # ServerHashExtractor, given an options hash and a deploy configuration,
6
+ # generates an array of hashes that can be used to instantiate Server
7
+ # objects
8
+ class ServerHashExtractor
9
+ def self.hashes(options, config)
10
+ new(options, config).hashes
11
+ end
12
+
13
+ attr_reader :options, :config
14
+
15
+ def initialize(options, config)
16
+ @options = options
17
+ @config = config
18
+ end
19
+
20
+ def hashes
21
+ return [] unless instances
22
+
23
+ instances.collect {|hostname|
24
+ {
25
+ :hostname => hostname,
26
+ :roles => instance_roles[hostname].to_s.split(','),
27
+ :name => instance_names[hostname],
28
+ :user => config.user
29
+ }
30
+ }
31
+ end
32
+
33
+ private
34
+ def instances
35
+ options[:instances]
36
+ end
37
+
38
+ def instance_roles
39
+ options[:instance_roles]
40
+ end
41
+
42
+ def instance_names
43
+ options[:instance_names]
44
+ end
45
+
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,45 @@
1
+ require 'engineyard-serverside/cli/workflows/calling_deploy_hooks'
2
+ require 'engineyard-serverside/cli/workflows/deploying_applications'
3
+ require 'engineyard-serverside/cli/workflows/disabling_maintenance'
4
+ require 'engineyard-serverside/cli/workflows/enabling_maintenance'
5
+ require 'engineyard-serverside/cli/workflows/integrating_servers'
6
+ require 'engineyard-serverside/cli/workflows/restarting_applications'
7
+ require 'engineyard-serverside/cli/workflows/rolling_back_applications'
8
+ require 'engineyard-serverside/cli/workflows/showing_maintenance_status'
9
+
10
+ module EY
11
+ module Serverside
12
+ module CLI
13
+
14
+ # Workflows is a collection of reified procedures that handle the
15
+ # various requirements of our CLI app
16
+ module Workflows
17
+ DEFINED = {
18
+ :deploy => DeployingApplications,
19
+ :disable_maintenance => DisablingMaintenance,
20
+ :enable_maintenance => EnablingMaintenance,
21
+ :hook => CallingDeployHooks,
22
+ :integrate => IntegratingServers,
23
+ :maintenance_status => ShowingMaintenanceStatus,
24
+ :restart => RestartingApplications,
25
+ :rollback => RollingBackApplications
26
+ }
27
+
28
+ def self.perform(workflow, options = {})
29
+ resolve(workflow).
30
+ perform(options)
31
+ end
32
+
33
+ def self.resolve(workflow)
34
+ (DEFINED[normalized(workflow)] || Base)
35
+ end
36
+
37
+ def self.normalized(workflow)
38
+ return nil if workflow.nil?
39
+
40
+ workflow.to_sym
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,78 @@
1
+ require 'engineyard-serverside/about'
2
+ require 'engineyard-serverside/cli/server_hash_extractor'
3
+ require 'engineyard-serverside/cli/workflows/errors'
4
+ require 'engineyard-serverside/configuration'
5
+
6
+ module EY
7
+ module Serverside
8
+ module CLI
9
+ module Workflows
10
+
11
+ # Base is the template from which all Workflows are derived
12
+ class Base
13
+ attr_reader :options
14
+
15
+ def initialize(options = {})
16
+ @options = options
17
+ end
18
+
19
+ def perform
20
+ shell.debug "Initializing #{About.name_with_version}."
21
+
22
+ begin
23
+ procedure
24
+ rescue EY::Serverside::RemoteFailure => remote_error
25
+ shell.fatal(remote_error.message)
26
+ raise
27
+ rescue Exception => error
28
+ shell.fatal("#{error.backtrace[0]}: #{error.message} (#{error.class})")
29
+ raise
30
+ end
31
+ end
32
+
33
+ def self.perform(options = {})
34
+ new(options).perform
35
+ end
36
+
37
+ private
38
+ def config
39
+ @config ||= EY::Serverside::Deploy::Configuration.new(options)
40
+ end
41
+
42
+ def shell
43
+ @shell ||= EY::Serverside::Shell.new(
44
+ :verbose => config.verbose,
45
+ :log_path => File.join(
46
+ ENV['HOME'],
47
+ "#{config.app}-#{task_name}.log"
48
+ )
49
+ )
50
+ end
51
+
52
+ def servers
53
+ @servers ||= EY::Serverside::Servers.from_hashes(
54
+ EY::Serverside::CLI::ServerHashExtractor.hashes(options, config),
55
+ shell
56
+ )
57
+ end
58
+
59
+ def task_name
60
+ raise Undefined.new(
61
+ "You must define the private task_name method for your workflow."
62
+ )
63
+ end
64
+
65
+ def procedure
66
+ raise Undefined.new(
67
+ "You must define the private procedure method for your workflow."
68
+ )
69
+ end
70
+
71
+ def propagate_serverside
72
+ EY::Serverside::Propagator.propagate(servers, shell)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,31 @@
1
+ require 'engineyard-serverside/cli/workflows/base'
2
+ require 'engineyard-serverside/callbacks'
3
+
4
+ module EY
5
+ module Serverside
6
+ module CLI
7
+ module Workflows
8
+
9
+ # CallingDeployHooks is a Workflow that, given a hook_name option,
10
+ # executes the requested deploy hook
11
+ class CallingDeployHooks < Base
12
+ private
13
+ def procedure
14
+ Callbacks.
15
+ load(config.paths).
16
+ execute(config, shell, hook_name)
17
+ end
18
+
19
+ def task_name
20
+ "hook-#{hook_name}"
21
+ end
22
+
23
+ def hook_name
24
+ options[:hook_name]
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ require 'engineyard-serverside/cli/workflows/base'
2
+ require 'engineyard-serverside/cli/workflows/helpers'
3
+
4
+ module EY
5
+ module Serverside
6
+ module CLI
7
+ module Workflows
8
+
9
+ # DeployingApplications is a Workflow that deploys the application
10
+ # specified by the incoming options
11
+ class DeployingApplications < Base
12
+ include Helpers
13
+
14
+ private
15
+ def procedure
16
+ propagate_serverside
17
+
18
+ deployer.deploy
19
+ end
20
+
21
+ def task_name
22
+ 'deploy'
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ require 'engineyard-serverside/cli/workflows/base'
2
+ require 'engineyard-serverside/cli/workflows/helpers'
3
+ require 'engineyard-serverside/maintenance'
4
+
5
+ module EY
6
+ module Serverside
7
+ module CLI
8
+ module Workflows
9
+
10
+ # DisablingMaintenance is a Workflow that removes the maintenance page
11
+ # for the application specified in the options
12
+ class DisablingMaintenance < Base
13
+ include Helpers
14
+
15
+ private
16
+ def procedure
17
+ propagate_serverside
18
+
19
+ maintenance.manually_disable
20
+ end
21
+
22
+ def task_name
23
+ 'disable_maintenance'
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ require 'engineyard-serverside/cli/workflows/base'
2
+ require 'engineyard-serverside/cli/workflows/helpers'
3
+ require 'engineyard-serverside/maintenance'
4
+
5
+ module EY
6
+ module Serverside
7
+ module CLI
8
+ module Workflows
9
+
10
+ # EnablingMaintenance is a Workflow that puts a maintenance page in
11
+ # place for the application specified in the options
12
+ class EnablingMaintenance < Base
13
+ include Helpers
14
+
15
+ private
16
+ def procedure
17
+ propagate_serverside
18
+
19
+ maintenance.manually_enable
20
+ end
21
+
22
+ def task_name
23
+ 'enable_maintenance'
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ module EY
2
+ module Serverside
3
+ module CLI
4
+ module Workflows
5
+ # Undefined is an error that is raised when one attemps to perform
6
+ # a Workflow that is not fully defined
7
+ class Undefined < StandardError
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ module EY
2
+ module Serverside
3
+ module CLI
4
+ module Workflows
5
+
6
+ # Helpers is a collection of methods that can be mixed into a Workflow
7
+ # to provide easy access to some of the underlying concepts for
8
+ # procedures like deploying, managing maintenance state, etc
9
+ module Helpers
10
+ def deployer
11
+ EY::Serverside::Deploy.new(servers, config, shell)
12
+ end
13
+
14
+ def maintenance
15
+ EY::Serverside::Maintenance.new(servers, config, shell)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,71 @@
1
+ require 'engineyard-serverside/cli/workflows/base'
2
+
3
+ module EY
4
+ module Serverside
5
+ module CLI
6
+ module Workflows
7
+
8
+ # IntegratingServers is a Workflow that attempts to integrate new
9
+ # servers into an existing environment
10
+ class IntegratingServers < Base
11
+ def initialize(options = {})
12
+ super
13
+
14
+ # We need to set some extra options, but options is frozen by
15
+ # the time we get here, so dupe it!
16
+ @options = options.dup
17
+
18
+ # so that we deploy to the same place there that we have here
19
+ @options[:release_path] = current_app_dir.realpath.to_s
20
+
21
+ # we have to deploy the same SHA there as here
22
+ @options[:branch] = current_app_dir.join('REVISION').read.strip
23
+
24
+ # always rebundle gems on integrate to make sure the instance comes up correctly.
25
+ @options[:clean] = true
26
+ end
27
+
28
+ private
29
+ def procedure
30
+ propagate_serverside
31
+
32
+ # We have to rsync the entire app dir, so we need all the permissions to be correct!
33
+ owner_user = config.user
34
+ owner_group = config.group
35
+
36
+ chown_command = %|find #{app_dir} \\( -not -user #{owner_user} -or -not -group #{owner_group} \\) -exec chown -h #{owner_user}:#{owner_group} "{}" +|
37
+
38
+ shell.logged_system("sudo sh -l -c '#{chown_command}'", servers.detect {|server| server.local?})
39
+
40
+ servers.run_for_each! do |server|
41
+ chown = server.command_on_server('sudo sh -l -c', chown_command)
42
+ sync = server.sync_directory_command(app_dir, options[:ignore_existing])
43
+ clean = server.command_on_server('sh -l -c', "rm -rf #{current_app_dir}")
44
+ "(#{chown}) && (#{sync}) && (#{clean})"
45
+ end
46
+
47
+ # deploy local-ref to other instances into /data/$app/local-current
48
+ EY::Serverside::Deploy.new(servers, config, shell).cached_deploy
49
+ end
50
+
51
+ def task_name
52
+ "integrate-#{options[:instances].join('-')}".gsub(/[^-.\w]/,'')
53
+ end
54
+
55
+ def integrate_options
56
+ @integrate_options ||= options.dup
57
+ end
58
+
59
+ def app_dir
60
+ @app_dir ||= Pathname.new "/data/#{options[:app]}"
61
+ end
62
+
63
+ def current_app_dir
64
+ @current_app_dir ||= app_dir.join("current")
65
+ end
66
+
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end