engineyard-eycap 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt ADDED
@@ -0,0 +1,84 @@
1
+ == HEAD / 0000-00-00
2
+ * rake install_gem_no_doc for faster install
3
+
4
+ == 0.3.3 / 2008-05-07
5
+ * add ey_logger to log deploys to server
6
+
7
+ == 0.3.2 / 2008-04-29
8
+ * adding db:clone_to_local task to take a dump on the slice, fetch it, and load it into your dev db on your workstation
9
+ * only clone from replica database
10
+ * remove call to variable in task desc
11
+ * fix ferret symlinking
12
+ * gemspec for github
13
+
14
+ == 0.3.1 / 2008-03-17
15
+ * Make the custom maintenance pages actually work!
16
+
17
+ == 0.3.0 / 2008-03-05
18
+ * Adding custom maintenance pages is now as easy as copying a custom html file to #{shared_path}/system/maintenance.html.custom
19
+
20
+ == 0.2.10 / 2008-03-02
21
+ * Symlink memcached.yml only on :memcached => true, except :no_release => true
22
+
23
+ == 0.2.9 / 2008-02-27
24
+ * Fix a bug with ultrasphinx:configure running on multiple hosts
25
+
26
+ == 0.2.8 / 2008-02-20
27
+ * Add tasks for solr starting,stopping, and log tailing.
28
+ * Add monit namespace and make appservers php/merb compatible
29
+ * Make ultrasphinx symlinking a little smarter
30
+ * Add tomcat tasks for spongecell
31
+
32
+ == 0.2.6 / 2008-02-14
33
+ * Make mongrel restarts only apply to mongrel slices
34
+
35
+ == 0.2.5 / 2008-02-11
36
+ * Added db cloning task
37
+
38
+ == 0.2.4 / 2008-02-06
39
+ * Symlink memcached.yml in on deploy if you enable the callback
40
+
41
+ == 0.2.3 / 2008-02-01
42
+ * Make log tailing environmentally aware. Also add tasks to tail mongrel logs
43
+
44
+ == 0.2.2 / 2008-01-25
45
+ * sphinx:configure ultrasphinx configuration task
46
+
47
+ == 0.2.1 / 2008-01-25
48
+ * override default deploy recipe start/stop tasks
49
+
50
+ == 0.2.0 / 2008-01-23
51
+ * sphinx:symlink ultrasphinx configuration directory
52
+
53
+ == 0.1.9 / 2008-01-21
54
+ * Correct memcached tasks.
55
+
56
+ == 0.1.8 / 2008-01-20
57
+ * Add memcached tasks
58
+
59
+ == 0.1.7 / 2008-01-19
60
+ * fix symlink_configs task
61
+
62
+ == 0.1.6 / 2008-01-19
63
+ * add restart tasks for backgroundrb
64
+
65
+ == 0.1.5 / 2008-01-18
66
+ * fixed bug in filtered_remote_cache that prevented a changed checkout URL from taking over the cache
67
+
68
+ == 0.1.4 / 2008-01-17
69
+ * added sphinx:[reindex|start|stop|restart] matches only app servers with :sphinx => true
70
+
71
+ == 0.1.3 / 2008-01-17
72
+ * filtered_remote_cache to removes the cached copy of the source URL changed
73
+
74
+ == 0.1.2 / 2008-01-15
75
+ * added filtered_remote_cache capistrano deployment strategy
76
+
77
+ == 0.1.1 / 2008-01-15
78
+ * removed database tasks until problem with 'defer' is solved
79
+
80
+ == 0.1.0 / 2008-01-14
81
+ * Bugfix for empty :application variable
82
+
83
+ == 0.0.1 / 2008-01-14
84
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,25 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/capistrano/recipes/deploy/strategy/filtered_remote_cache.rb
6
+ lib/eycap.rb
7
+ lib/eycap/lib/ey_logger.rb
8
+ lib/eycap/lib/ey_logger_hooks.rb
9
+ lib/eycap/recipes.rb
10
+ lib/eycap/recipes/backgroundrb.rb
11
+ lib/eycap/recipes/database.rb
12
+ lib/eycap/recipes/deploy.rb
13
+ lib/eycap/recipes/ferret.rb
14
+ lib/eycap/recipes/juggernaut.rb
15
+ lib/eycap/recipes/memcached.rb
16
+ lib/eycap/recipes/mongrel.rb
17
+ lib/eycap/recipes/monit.rb
18
+ lib/eycap/recipes/nginx.rb
19
+ lib/eycap/recipes/slice.rb
20
+ lib/eycap/recipes/solr.rb
21
+ lib/eycap/recipes/sphinx.rb
22
+ lib/eycap/recipes/templates/maintenance.rhtml
23
+ lib/eycap/recipes/tomcat.rb
24
+ test/test_eycap.rb
25
+ test/test_helper.rb
data/README.txt ADDED
@@ -0,0 +1,63 @@
1
+ = eycap
2
+
3
+ == DESCRIPTION:
4
+
5
+ Engine Yard capistrano tasks for use specifically with Engine Yard slices. They include convenience methods for managed a database, mongrel, nginx or other services.
6
+
7
+ Also included is a deployment strategy, :filtered_remote_cache, which speeds up deployment like :remote_cache, but filters out .svn directory which are a security risk and write slowly to shared disks.
8
+
9
+ == REQUIREMENTS:
10
+
11
+ * capistrano (http://capify.org) > 2.0.0, but recommended with > 2.2.0
12
+
13
+ == INSTALL:
14
+
15
+ $ gem sources -a http://gems.github.com/ (you only need to do this once)
16
+ $ gem install engineyard-eycap
17
+
18
+ == SOURCE:
19
+
20
+ eycaps git repo is available on GitHub, which can be browsed at:
21
+
22
+ http://github.com/engineyard/eycap
23
+
24
+ and cloned from:
25
+
26
+ git://github.com/engineyard/eycap.git
27
+
28
+ == USAGE:
29
+
30
+ = Include in capistrano
31
+
32
+ In your deploy.rb, simply include this line at the top:
33
+
34
+ require 'eycap/recipes'
35
+
36
+ = Filtered remote cache
37
+
38
+ To use filtered_remote_cache, simply:
39
+
40
+ set :deploy_via, :filtered_remote_cache
41
+
42
+ == LICENSE:
43
+
44
+ Copyright (c) 2008 Engine Yard
45
+
46
+ Permission is hereby granted, free of charge, to any person obtaining
47
+ a copy of this software and associated documentation files (the
48
+ "Software"), to deal in the Software without restriction, including
49
+ without limitation the rights to use, copy, modify, merge, publish,
50
+ distribute, sublicense, and/or sell copies of the Software, and to
51
+ permit persons to whom the Software is furnished to do so, subject to
52
+ the following conditions:
53
+
54
+ The above copyright notice and this permission notice shall be
55
+ included in all copies or substantial portions of the Software.
56
+
57
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
58
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
59
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
60
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
61
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
62
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
63
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+ require './lib/eycap'
4
+
5
+ Hoe.new('eycap', Eycap::VERSION) do |p|
6
+ p.author = 'Engine Yard'
7
+ p.email = 'tech@engineyard.com'
8
+ p.summary = 'Capistrano tasks for Engine Yard slices'
9
+ p.description = 'A bunch of useful recipes to help deployment to Engine Yard slices'
10
+ p.url = 'http://eycap.rubyforge.org'
11
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
12
+ p.extra_deps << ['capistrano', '>= 2.2.0']
13
+ end
14
+
15
+ desc "Open an irb session preloaded with this library"
16
+ task :console do
17
+ sh "irb -rubygems -r ./lib/eycap.rb"
18
+ end
19
+
20
+ task :coverage do
21
+ system("rm -fr coverage")
22
+ system("rcov test/test_*.rb")
23
+ system("open coverage/index.html")
24
+ end
25
+
26
+ desc "Upload site to Rubyforge"
27
+ task :site do
28
+ end
29
+
30
+ desc 'Install the package as a gem.'
31
+ task :install_gem_no_doc => [:clean, :package] do
32
+ sh "#{'sudo ' unless Hoe::WINDOZE}gem install --local --no-rdoc --no-ri pkg/*.gem"
33
+ end
@@ -0,0 +1,48 @@
1
+ require 'capistrano/recipes/deploy/strategy/remote'
2
+
3
+ module Capistrano
4
+ module Deploy
5
+ module Strategy
6
+
7
+ # Implements the deployment strategy that keeps a cached checkout of
8
+ # the source code on each remote server. Each deploy simply updates the
9
+ # cached checkout, and then filters a copy through tar to remove unwanted .svn directories,
10
+ # finally leaving a pristeen, export-like copy at the destination.
11
+ class FilteredRemoteCache < Remote
12
+ # Executes the SCM command for this strategy and writes the REVISION
13
+ # mark file to each host.
14
+ def deploy!
15
+ update_repository_cache
16
+ tar_copy_repository_cache
17
+ end
18
+
19
+ def check!
20
+ super.check do |d|
21
+ d.remote.writable(shared_path)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def repository_cache
28
+ configuration[:repository_cache] || "/var/cache/engineyard/#{configuration[:application]}"
29
+ end
30
+
31
+ def update_repository_cache
32
+ logger.trace "checking if the cached copy URL matches this deploy, then updating it"
33
+ command = "if [ -d #{repository_cache} ] && ! [ `svn info #{repository_cache} | grep URL | awk '{print $2}'` = '#{configuration[:repository]}' ]; then " +
34
+ "rm -rf #{repository_cache} && #{source.checkout(revision, repository_cache)}; " +
35
+ "elif [ -d #{repository_cache} ]; then #{source.sync(revision, repository_cache)}; " +
36
+ "else #{source.checkout(revision, repository_cache)}; fi"
37
+ scm_run(command)
38
+ end
39
+
40
+ def tar_copy_repository_cache
41
+ logger.trace "copying and filtering .svn via tar from cached version to #{configuration[:release_path]}"
42
+ run "mkdir #{configuration[:release_path]} && tar c --exclude=#{configuration[:filter_spec] || ".svn"} -C #{repository_cache} . | tar xC #{configuration[:release_path]} && #{mark}"
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,124 @@
1
+ require 'tmpdir'
2
+ module Capistrano
3
+
4
+ class Logger
5
+
6
+ def ey_log(level, message, line_prefix = nil)
7
+ EYLogger.log(level, message, line_prefix) if EYLogger.setup?
8
+ log_without_ey_logging(level, message, line_prefix)
9
+ end
10
+
11
+ unless method_defined?(:log_without_ey_logging)
12
+ alias_method :log_without_ey_logging, :log
13
+ alias_method :log, :ey_log
14
+ end
15
+
16
+ def close
17
+ device.close if @needs_close
18
+ EYLogger.close if EYLogger.setup?
19
+ end
20
+ end
21
+
22
+ class EYLogger
23
+
24
+ # Sets up the EYLogger to beging capturing capistrano's logging. You should pass the capistrno configuration
25
+ # and the deploy type as a string. The deploy type is for reporting purposes only but must be included.
26
+ def self.setup(configuration, deploy_type, options = {})
27
+ @_configuration = configuration
28
+ @_deploy_type = deploy_type.gsub(/:/, "_")
29
+ @_log_path = options[:deploy_log_path] || Dir.tmpdir
30
+ @_log_path << "/" unless @_log_path =~ /\/$/
31
+ FileUtils.mkdir_p(@_log_path)
32
+ @_setup = true
33
+ @_success = true
34
+ end
35
+
36
+ def self.log(level, message, line_prefix=nil)
37
+ return nil unless setup?
38
+ @release_name = @_configuration[:release_name] if @release_name.nil?
39
+ @_log_file_path = @_log_path + @release_name + ".log" unless @_log_file_path
40
+ @_deploy_log_file = File.open(@_log_file_path, "w") if @_deploy_log_file.nil?
41
+
42
+ indent = "%*s" % [Logger::MAX_LEVEL, "*" * (Logger::MAX_LEVEL - level)]
43
+ message.each do |line|
44
+ if line_prefix
45
+ @_deploy_log_file << "#{indent} [#{line_prefix}] #{line.strip}\n"
46
+ else
47
+ @_deploy_log_file << "#{indent} #{line.strip}\n"
48
+ end
49
+ end
50
+ end
51
+
52
+ def self.post_process
53
+ unless ::Interrupt === $!
54
+ puts "\n\nPlease wait while the log file is processed\n"
55
+ # Should dump the stack trace of an exception if there is one
56
+ error = $!
57
+ unless error.nil?
58
+ @_deploy_log_file << error.message << "\n"
59
+ @_deploy_log_file << error.backtrace.join("\n")
60
+ @_success = false
61
+ end
62
+ self.close
63
+
64
+ hooks = [:any]
65
+ hooks << self.successful? ? :success : :failure
66
+ puts "Executing Post Processing Hooks"
67
+ hooks.each do |h|
68
+ @_post_process_hooks[h].each do |key|
69
+ @_configuration.parent.find_and_execute_task(key)
70
+ end
71
+ end
72
+ puts "Finished Post Processing Hooks"
73
+ end
74
+ end
75
+
76
+ # Adds a post processing hook.
77
+ #
78
+ # Provide a task name to execute. These tasks are executed after capistrano has actually run its course.
79
+ #
80
+ # Takes a key to control when the hook is executed.'
81
+ # :any - always executed
82
+ # :success - only execute on success
83
+ # :failure - only execute on failure
84
+ #
85
+ # ==== Example
86
+ # Capistrano::EYLogger.post_process_hook( "ey_logger:upload_log_to_slice", :any)
87
+ #
88
+ def self.post_process_hook(task, key = :any)
89
+ @_post_process_hooks ||= Hash.new{|h,k| h[k] = []}
90
+ @_post_process_hooks[key] << task
91
+ end
92
+
93
+ def self.setup?
94
+ !!@_setup
95
+ end
96
+
97
+ def self.deploy_type
98
+ @_deploy_type
99
+ end
100
+
101
+ def self.successful?
102
+ !!@_success
103
+ end
104
+
105
+ def self.failure?
106
+ !@_success
107
+ end
108
+
109
+ def self.log_file_path
110
+ @_log_file_path
111
+ end
112
+
113
+ def self.remote_log_file_name
114
+ @_log_file_name ||= "#{@_configuration[:release_name]}-#{@_deploy_type}-#{self.successful? ? "SUCCESS" : "FAILURE"}.log"
115
+ end
116
+
117
+ def self.close
118
+ @_deploy_log_file.flush unless @_deploy_log_file.nil?
119
+ @_deploy_log_file.close unless @_deploy_log_file.nil?
120
+ @_setup = false
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,14 @@
1
+ require File.join(File.dirname(__FILE__), "ey_logger")
2
+
3
+ # These tasks are setup to use with the logger as post commit hooks.
4
+ Capistrano::Configuration.instance(:must_exist).load do
5
+ namespace :ey_logger do
6
+ task :upload_log_to_slice, :except => { :no_release => true} do
7
+ logger = Capistrano::EYLogger
8
+ run "mkdir -p #{shared_path}/deploy_logs"
9
+ put File.open(logger.log_file_path).read, "#{shared_path}/deploy_logs/#{logger.remote_log_file_name}"
10
+ end
11
+ end
12
+ end
13
+
14
+ Capistrano::EYLogger.post_process_hook("ey_logger:upload_log_to_slice")
@@ -0,0 +1,23 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :bdrb do
4
+ desc "After update_code you want to reindex"
5
+ task :reindex, :roles => :app, :only => {:backgroundrb => true} do
6
+ run "/engineyard/bin/searchd #{application} reindex"
7
+ end
8
+
9
+ desc "Start Backgroundrb"
10
+ task :start, :roles => :app, :only => {:backgroundrb => true} do
11
+ sudo "/usr/bin/monit start all -g backgroundrb_#{application}"
12
+ end
13
+ desc "Stop Backgroundrb"
14
+ task :stop, :roles => :app, :only => {:backgroundrb => true} do
15
+ sudo "/usr/bin/monit stop all -g backgroundrb_#{application}"
16
+ end
17
+ desc "Restart Backgroundrb"
18
+ task :restart, :roles => :app, :only => {:backgroundrb => true} do
19
+ sudo "/usr/bin/monit restart all -g backgroundrb_#{application}"
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,37 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :db do
4
+ task :backup_name, :only => { :primary => true } do
5
+ now = Time.now
6
+ run "mkdir -p #{shared_path}/db_backups"
7
+ backup_time = [now.year,now.month,now.day,now.hour,now.min,now.sec].join('-')
8
+ set :backup_file, "#{shared_path}/db_backups/#{environment_database}-snapshot-#{backup_time}.sql"
9
+ end
10
+
11
+ desc "Clone Production Database to Staging Database."
12
+ task :clone_prod_to_staging, :roles => :db, :only => { :primary => true } do
13
+ backup_name
14
+ on_rollback { run "rm -f #{backup_file}" }
15
+ run "mysqldump --add-drop-table -u #{dbuser} -h #{production_dbhost}-replica -p#{dbpass} #{production_database} > #{backup_file}"
16
+ run "mysql -u #{dbuser} -p#{dbpass} -h #{staging_dbhost} #{staging_database} < #{backup_file}"
17
+ run "rm -f #{backup_file}"
18
+ end
19
+
20
+ desc "Backup your database to shared_path+/db_backups"
21
+ task :dump, :roles => :db, :only => {:primary => true} do
22
+ backup_name
23
+ run "mysqldump --add-drop-table -u #{dbuser} -h #{environment_dbhost}-replica -p#{dbpass} #{environment_database} | bzip2 -c > #{backup_file}.bz2"
24
+ end
25
+
26
+ desc "Sync your production database to your local workstation"
27
+ task :clone_to_local, :roles => :db, :only => {:primary => true} do
28
+ backup_name
29
+ dump
30
+ get "#{backup_file}.bz2", "/tmp/#{application}.sql.gz"
31
+ development_info = YAML.load_file("config/database.yml")['development']
32
+ run_str = "bzcat /tmp/#{application}.sql.gz | mysql -u #{development_info['username']} -p#{development_info['password']} -h #{development_info['host']} #{development_info['database']}"
33
+ %x!#{run_str}!
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,90 @@
1
+ require File.join(File.dirname(__FILE__), "..", "lib", "ey_logger.rb")
2
+ Capistrano::Configuration.instance(:must_exist).load do
3
+
4
+ namespace :deploy do
5
+ # This is here to hook into the logger for deploy and deploy:long tasks
6
+ ["deploy", "deploy:long"].each do |tsk|
7
+ before(tsk) do
8
+ Capistrano::EYLogger.setup( self, tsk )
9
+ at_exit{ Capistrano::EYLogger.post_process if Capistrano::EYLogger.setup? }
10
+ end
11
+ end
12
+
13
+ desc "Link the database.yml and mongrel_cluster.yml files into the current release path."
14
+ task :symlink_configs, :roles => :app, :except => {:no_release => true} do
15
+ run <<-CMD
16
+ cd #{release_path} &&
17
+ ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml &&
18
+ ln -nfs #{shared_path}/config/mongrel_cluster.yml #{release_path}/config/mongrel_cluster.yml
19
+ CMD
20
+ end
21
+
22
+ desc "Display the maintenance.html page while deploying with migrations. Then it restarts and enables the site again."
23
+ task :long do
24
+ transaction do
25
+ update_code
26
+ web.disable
27
+ symlink
28
+ migrate
29
+ end
30
+
31
+ restart
32
+ web.enable
33
+ end
34
+
35
+ desc "Restart the Mongrel processes on the app slices."
36
+ task :restart, :roles => :app do
37
+ mongrel.restart
38
+ end
39
+
40
+ desc "Start the Mongrel processes on the app slices."
41
+ task :spinner, :roles => :app do
42
+ mongrel.start
43
+ end
44
+
45
+ desc "Start the Mongrel processes on the app slices."
46
+ task :start, :roles => :app do
47
+ mongrel.start
48
+ end
49
+
50
+ desc "Stop the Mongrel processes on the app slices."
51
+ task :stop, :roles => :app do
52
+ mongrel.stop
53
+ end
54
+
55
+ namespace :web do
56
+ desc <<-DESC
57
+ Present a maintenance page to visitors. Disables your application's web \
58
+ interface by writing a "maintenance.html" file to each web server. The \
59
+ servers must be configured to detect the presence of this file, and if \
60
+ it is present, always display it instead of performing the request.
61
+
62
+ By default, the maintenance page will just say the site is down for \
63
+ "maintenance", and will be back "shortly", but you can customize the \
64
+ page by specifying the REASON and UNTIL environment variables:
65
+
66
+ $ cap deploy:web:disable \\
67
+ REASON="hardware upgrade" \\
68
+ UNTIL="12pm Central Time"
69
+
70
+ Further customization copy your html file to shared_path+'/system/maintenance.html.custom'.
71
+ If this file exists it will be used instead of the default capistrano ugly page
72
+ DESC
73
+ task :disable, :roles => :web, :except => { :no_release => true } do
74
+ maint_file = "#{shared_path}/system/maintenance.html"
75
+ require 'erb'
76
+ on_rollback { run "rm #{shared_path}/system/maintenance.html" }
77
+
78
+ reason = ENV['REASON']
79
+ deadline = ENV['UNTIL']
80
+
81
+ template = File.read(File.join(File.dirname(__FILE__), "templates", "maintenance.rhtml"))
82
+ result = ERB.new(template).result(binding)
83
+
84
+ put result, "#{shared_path}/system/maintenance.html.tmp", :mode => 0644
85
+ run "if [ -f #{shared_path}/system/maintenance.html.custom ]; then cp #{shared_path}/system/maintenance.html.custom #{maint_file}; else cp #{shared_path}/system/maintenance.html.tmp #{maint_file}; fi"
86
+ end
87
+ end
88
+ end
89
+
90
+ end
@@ -0,0 +1,20 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :ferret do
4
+ desc "After update_code you want to symlink the index and ferret_server.yml file into place"
5
+ task :symlink_configs, :roles => :app, :except => {:no_release => true} do
6
+ run <<-CMD
7
+ cd #{release_path} &&
8
+ ln -nfs #{shared_path}/config/ferret_server.yml #{release_path}/config/ferret_server.yml &&
9
+ if [ -d #{release_path}/index ]; then mv #{release_path}/index #{release_path}/index.bak; fi &&
10
+ ln -nfs #{shared_path}/index #{release_path}/index
11
+ CMD
12
+ end
13
+ [:start,:stop,:restart].each do |op|
14
+ desc "#{op} ferret server"
15
+ task op, :roles => :app, :except => {:no_release => true} do
16
+ sudo "/usr/bin/monit #{op} all -g ferret_#{application}"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :juggernaut do
4
+ desc "After update_code you want to symlink the juggernaut.yml file into place"
5
+ task :symlink_configs, :roles => :app, :except => {:no_release => true} do
6
+ run <<-CMD
7
+ cd #{release_path} &&
8
+ ln -nfs #{shared_path}/config/juggernaut.yml #{release_path}/config/juggernaut.yml
9
+ CMD
10
+ end
11
+ [:start,:stop,:restart].each do |op|
12
+ desc "#{op} juggernaut server"
13
+ task op, :roles => :app, :except => {:no_release => true} do
14
+ sudo "/usr/bin/monit #{op} all -g juggernaut_#{application}"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ namespace :memcached do
3
+ desc "Start memcached"
4
+ task :start, :roles => :app, :only => {:memcached => true} do
5
+ sudo "/etc/init.d/memcached start"
6
+ end
7
+ desc "Stop memcached"
8
+ task :stop, :roles => :app, :only => {:memcached => true} do
9
+ sudo "/etc/init.d/memcached stop"
10
+ end
11
+ desc "Restart memcached"
12
+ task :restart, :roles => :app, :only => {:memcached => true} do
13
+ sudo "/etc/init.d/memcached restart"
14
+ end
15
+ desc "Symlink the memcached.yml file into place if it exists"
16
+ task :symlink_configs, :roles => :app, :only => {:memcached => true }, :except => { :no_release => true } do
17
+ run "if [ -f #{shared_path}/config/memcached.yml ]; then ln -nfs #{shared_path}/config/memcached.yml #{release_path}/config/memcached.yml; fi"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,28 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ namespace :mongrel do
3
+ desc <<-DESC
4
+ Start Mongrel processes on the app server. This uses the :use_sudo variable to determine whether to use sudo or not. By default, :use_sudo is
5
+ set to true.
6
+ DESC
7
+ task :start, :roles => :app do
8
+ sudo "/usr/bin/monit start all -g #{monit_group}"
9
+ end
10
+
11
+ desc <<-DESC
12
+ Restart the Mongrel processes on the app server by starting and stopping the cluster. This uses the :use_sudo
13
+ variable to determine whether to use sudo or not. By default, :use_sudo is set to true.
14
+ DESC
15
+ task :restart, :roles => :app do
16
+ sudo "/usr/bin/monit restart all -g #{monit_group}"
17
+ end
18
+
19
+ desc <<-DESC
20
+ Stop the Mongrel processes on the app server. This uses the :use_sudo
21
+ variable to determine whether to use sudo or not. By default, :use_sudo is
22
+ set to true.
23
+ DESC
24
+ task :stop, :roles => :app do
25
+ sudo "/usr/bin/monit stop all -g #{monit_group}"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :monit do
4
+ desc "Get the status of your mongrels"
5
+ task :status, :roles => :app do
6
+ @monit_output ||= { }
7
+ sudo "/usr/bin/monit status" do |channel, stream, data|
8
+ @monit_output[channel[:server].to_s] ||= [ ]
9
+ @monit_output[channel[:server].to_s].push(data.chomp)
10
+ end
11
+ @monit_output.each do |k,v|
12
+ puts "#{k} -> #{'*'*55}"
13
+ puts v.join("\n")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :nginx do
4
+ desc "Start Nginx on the app slices."
5
+ task :start, :roles => :app do
6
+ sudo "/etc/init.d/nginx start"
7
+ end
8
+
9
+ desc "Restart the Nginx processes on the app slices."
10
+ task :restart , :roles => :app do
11
+ sudo "/etc/init.d/nginx restart"
12
+ end
13
+
14
+ desc "Stop the Nginx processes on the app slices."
15
+ task :stop , :roles => :app do
16
+ sudo "/etc/init.d/nginx stop"
17
+ end
18
+
19
+ desc "Tail the nginx access logs for this application"
20
+ task :tail, :roles => :app do
21
+ run "tail -f /var/log/engineyard/nginx/#{application}.access.log" do |channel, stream, data|
22
+ puts "#{channel[:server]}: #{data}" unless data =~ /^10\.[01]\.0/ # skips lb pull pages
23
+ break if stream == :err
24
+ end
25
+ end
26
+
27
+ desc "Tail the nginx error logs on the app slices"
28
+ task :tail_error, :roles => :app do
29
+ run "tail -f /var/log/engineyard/nginx/error.log" do |channel, stream, data|
30
+ puts "#{channel[:server]}: #{data}" unless data =~ /^10\.[01]\.0/ # skips lb pull pages
31
+ break if stream == :err
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,21 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :slice do
4
+ desc "Tail the Rails production log for this environment"
5
+ task :tail_production_logs, :roles => :app do
6
+ run "tail -f #{shared_path}/log/#{rails_env}.log" do |channel, stream, data|
7
+ puts # for an extra line break before the host name
8
+ puts "#{channel[:server]} -> #{data}"
9
+ break if stream == :err
10
+ end
11
+ end
12
+ desc "Tail the Mongrel logs this environment"
13
+ task :tail_mongrel_logs, :roles => :app do
14
+ run "tail -f #{shared_path}/log/mongrel*.log" do |channel, stream, data|
15
+ puts # for an extra line break before the host name
16
+ puts "#{channel[:server]} -> #{data}"
17
+ break if stream == :err
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :solr do
4
+ desc "After update_code you want to symlink the index and ferret_server.yml file into place"
5
+ task :symlink_configs, :roles => :app, :except => {:no_release => true} do
6
+ run <<-CMD
7
+ cd #{release_path} && ln -nfs #{shared_path}/config/solr.yml #{release_path}/config/solr.yml
8
+ CMD
9
+ end
10
+
11
+ [:start,:stop,:restart].each do |op|
12
+ desc "#{op} ferret server"
13
+ task op, :roles => :app, :only => {:solr => true} do
14
+ sudo "/usr/bin/monit #{op} all -g solr_#{application}"
15
+ end
16
+ end
17
+
18
+ namespace :tail do
19
+ desc "Tail the Solr logs this environment"
20
+ task :logs, :roles => :app, :only => {:solr => true} do
21
+ run "tail -f /var/log/engineyard/solr/#{application}.log" do |channel, stream, data|
22
+ puts # for an extra line break before the host name
23
+ puts "#{channel[:server]} -> #{data}"
24
+ break if stream == :err
25
+ end
26
+ end
27
+ desc "Tail the Solr error logs this environment"
28
+ task :errors, :roles => :app, :only => {:solr => true} do
29
+ run "tail -f /var/log/engineyard/solr/#{application}.err.log" do |channel, stream, data|
30
+ puts # for an extra line break before the host name
31
+ puts "#{channel[:server]} -> #{data}"
32
+ break if stream == :err
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,34 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :sphinx do
4
+ desc "After update_code you want to configure, then reindex"
5
+ task :configure, :roles => :app, :only => {:sphinx => true}, :except => {:no_release => true} do
6
+ run "/engineyard/bin/searchd #{application} configure"
7
+ end
8
+
9
+ desc "After configure you want to reindex"
10
+ task :reindex, :roles => :app, :only => {:sphinx => true} do
11
+ run "/engineyard/bin/searchd #{application} reindex"
12
+ end
13
+
14
+ desc "Start Sphinx Searchd"
15
+ task :start, :roles => :app, :only => {:sphinx => true} do
16
+ sudo "/usr/bin/monit start all -g sphinx_#{application}"
17
+ end
18
+ desc "Stop Sphinx Searchd"
19
+ task :stop, :roles => :app, :only => {:sphinx => true} do
20
+ sudo "/usr/bin/monit stop all -g sphinx_#{application}"
21
+ end
22
+ desc "Restart Sphinx Searchd"
23
+ task :restart, :roles => :app, :only => {:sphinx => true} do
24
+ sudo "/usr/bin/monit restart all -g sphinx_#{application}"
25
+ end
26
+
27
+ desc "Symlink the sphinx config file"
28
+ task :symlink, :roles => :app, :only => {:sphinx => true}, :except => {:no_release => true} do
29
+ run "if [ -d #{release_path}/config/ultrasphinx ]; then mv #{release_path}/config/ultrasphinx #{release_path}/config/ultrasphinx.bak; fi"
30
+ run "ln -nfs #{shared_path}/config/ultrasphinx #{release_path}/config/ultrasphinx"
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,53 @@
1
+
2
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
3
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
+
5
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
6
+
7
+ <head>
8
+ <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
9
+ <title>System down for maintenance</title>
10
+
11
+ <style type="text/css">
12
+ div.outer {
13
+ position: absolute;
14
+ left: 50%;
15
+ top: 50%;
16
+ width: 500px;
17
+ height: 300px;
18
+ margin-left: -260px;
19
+ margin-top: -150px;
20
+ }
21
+
22
+ .DialogBody {
23
+ margin: 0;
24
+ padding: 10px;
25
+ text-align: left;
26
+ border: 1px solid #ccc;
27
+ border-right: 1px solid #999;
28
+ border-bottom: 1px solid #999;
29
+ background-color: #fff;
30
+ }
31
+
32
+ body { background-color: #fff; }
33
+ </style>
34
+ </head>
35
+
36
+ <body>
37
+
38
+ <div class="outer">
39
+ <div class="DialogBody" style="text-align: center;">
40
+ <div style="text-align: center; width: 200px; margin: 0 auto;">
41
+ <p style="color: red; font-size: 16px; line-height: 20px;">
42
+ The system is down for <%= reason ? reason : "maintenance" %>
43
+ as of <%= Time.now.strftime("%H:%M %Z") %>.
44
+ </p>
45
+ <p style="color: #666;">
46
+ It'll be back <%= deadline ? deadline : "shortly" %>.
47
+ </p>
48
+ </div>
49
+ </div>
50
+ </div>
51
+
52
+ </body>
53
+ </html>
@@ -0,0 +1,16 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ namespace :tomcat do
3
+ desc "Start tomcat"
4
+ task :start, :roles => :app, :only => {:tomcat => true} do
5
+ sudo "/etc/init.d/tomcat start"
6
+ end
7
+ desc "Stop tomcat"
8
+ task :stop, :roles => :app, :only => {:tomcat => true} do
9
+ sudo "/etc/init.d/tomcat stop"
10
+ end
11
+ desc "Restart tomcat"
12
+ task :restart, :roles => :app, :only => {:tomcat => true} do
13
+ sudo "/etc/init.d/tomcat restart"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ require 'eycap/lib/ey_logger'
2
+ require 'eycap/lib/ey_logger_hooks'
3
+ require 'eycap/recipes/database'
4
+ require 'eycap/recipes/ferret'
5
+ require 'eycap/recipes/mongrel'
6
+ require 'eycap/recipes/nginx'
7
+ require 'eycap/recipes/slice'
8
+ require 'eycap/recipes/deploy'
9
+ require 'eycap/recipes/sphinx'
10
+ require 'eycap/recipes/backgroundrb'
11
+ require 'eycap/recipes/memcached'
12
+ require 'eycap/recipes/solr'
13
+ require 'eycap/recipes/monit'
14
+ require 'eycap/recipes/tomcat'
15
+ require 'eycap/recipes/juggernaut'
16
+
17
+ Capistrano::Configuration.instance(:must_exist).load do
18
+
19
+ default_run_options[:pty] = true if respond_to?(:default_run_options)
20
+ set :keep_releases, 3
21
+ set :runner, defer { user }
22
+
23
+ end
data/lib/eycap.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Eycap
2
+ VERSION = '0.3.3'
3
+ end
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestEycap < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_truth
9
+ assert true
10
+ end
11
+ end
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/eycap'
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: engineyard-eycap
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.3
5
+ platform: ruby
6
+ authors:
7
+ - Engine Yard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-05-12 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: capistrano
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.2.0
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: hoe
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 1.5.1
32
+ version:
33
+ description: A bunch of useful recipes to help deployment to Engine Yard slices
34
+ email: tech@engineyard.com
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files:
40
+ - History.txt
41
+ - Manifest.txt
42
+ - README.txt
43
+ files:
44
+ - History.txt
45
+ - Manifest.txt
46
+ - README.txt
47
+ - Rakefile
48
+ - lib/capistrano/recipes/deploy/strategy/filtered_remote_cache.rb
49
+ - lib/eycap.rb
50
+ - lib/eycap/lib/ey_logger.rb
51
+ - lib/eycap/lib/ey_logger_hooks.rb
52
+ - lib/eycap/recipes.rb
53
+ - lib/eycap/recipes/backgroundrb.rb
54
+ - lib/eycap/recipes/database.rb
55
+ - lib/eycap/recipes/deploy.rb
56
+ - lib/eycap/recipes/ferret.rb
57
+ - lib/eycap/recipes/juggernaut.rb
58
+ - lib/eycap/recipes/memcached.rb
59
+ - lib/eycap/recipes/mongrel.rb
60
+ - lib/eycap/recipes/monit.rb
61
+ - lib/eycap/recipes/nginx.rb
62
+ - lib/eycap/recipes/slice.rb
63
+ - lib/eycap/recipes/solr.rb
64
+ - lib/eycap/recipes/sphinx.rb
65
+ - lib/eycap/recipes/templates/maintenance.rhtml
66
+ - lib/eycap/recipes/tomcat.rb
67
+ - test/test_eycap.rb
68
+ - test/test_helper.rb
69
+ has_rdoc: true
70
+ homepage: http://eycap.rubyforge.org
71
+ post_install_message:
72
+ rdoc_options:
73
+ - --main
74
+ - README.txt
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: "0"
82
+ version:
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: "0"
88
+ version:
89
+ requirements: []
90
+
91
+ rubyforge_project: eycap
92
+ rubygems_version: 1.0.1
93
+ signing_key:
94
+ specification_version: 2
95
+ summary: Capistrano tasks for Engine Yard slices
96
+ test_files:
97
+ - test/test_eycap.rb
98
+ - test/test_helper.rb