factorylabs-fdlcap 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +55 -2
- data/VERSION +1 -1
- data/fdlcap.gemspec +2 -4
- data/lib/fdlcap/recipes/database.rb +103 -1
- data/lib/fdlcap/recipes/geminstaller.rb +32 -10
- data/lib/fdlcap/recipes/performance.rb +45 -5
- data/lib/fdlcap/recipes/slice.rb +14 -0
- metadata +2 -4
- data/README +0 -0
data/README.rdoc
CHANGED
@@ -1,7 +1,60 @@
|
|
1
1
|
= fdlcap
|
2
2
|
|
3
|
-
|
3
|
+
Inspired by Engine Yard's eycap (http://github.com/engineyard/eycap), fdlcap is a set of extracted cap tasks, configurations, and callbacks from various Factory Design Labs projects.
|
4
|
+
|
5
|
+
It's designed to ease some common scenarios for deploying reasonably complex apps to Engine Yard environments. It's also designed to make it easier to package up deployment logic and make it reusable.
|
6
|
+
|
7
|
+
Some of the recipes include:
|
8
|
+
|
9
|
+
- auto_tagger - provide a default set of stages and set up deploy callbacks for progressive deployment with auto_tagger (http://github.com/zilkey/auto_tagger))
|
10
|
+
- craken - set up deploy callbacks for deploying raketab files to cron with craken
|
11
|
+
- delayed_job - start/stop/restart delayed_job workers with monit and set up deploy callbacks for restarting workers
|
12
|
+
- geminstaller - set up deploy callbacks for running chad woolley's geminstaller
|
13
|
+
- newrelic - set up deploy callbacks for notifying newrelic of deployments
|
14
|
+
- rake - run arbitrary rake tasks, commands, and ruby snippets on remote servers from a single command
|
15
|
+
- rsync - pull assets from production servers to development
|
16
|
+
- sass - set up deploy callbacks for updating sass stylesheets on deploy to avoid caching issues
|
17
|
+
- slice - tail arbitrary server logs and show custom maintenance pages
|
18
|
+
- ssh - shortcut to execute ssh sessions and tunnels to remote servers
|
19
|
+
- thinking_sphinx - set up deploy callbacks for thinking sphinx
|
20
|
+
|
21
|
+
One kind of cool addition is a simple mechanism for bundling callbacks, configuration variables, and tasks into reusable recipe chunks that can easily be dropped into your deploy configuration.
|
22
|
+
|
23
|
+
For example, to automatically set up tasks and callbacks for delayed_job and sass, you would add the following to deploy.rb:
|
24
|
+
|
25
|
+
use_recipe :delayed_job
|
26
|
+
use_recipe :sass
|
27
|
+
|
28
|
+
You can also create your own recipe chunks with the define_recipe method:
|
29
|
+
|
30
|
+
define_recipe :my_recipe do
|
31
|
+
# tasks, config, whatever go here
|
32
|
+
end
|
33
|
+
|
34
|
+
Then include them in your deploy.rb:
|
35
|
+
|
36
|
+
use_recipe :my_recipe
|
37
|
+
|
38
|
+
==Prereqs
|
39
|
+
|
40
|
+
Aside from capistrano, fdlcap depends on the following gems:
|
41
|
+
|
42
|
+
- capistrano-ext (for multistage deployments)
|
43
|
+
- engineyard-eycap (for deployment configurations and support recipes - http://github.com/engineyard/eycap)
|
44
|
+
- zilkey-auto_tagger (for rolling deploy tags via git - http://github.com/zilkey/auto_tagger)
|
45
|
+
|
46
|
+
These should all be installed automatically by rubygems when you install fdlcap.
|
47
|
+
|
48
|
+
==Installation
|
49
|
+
|
50
|
+
sudo gem install factorylabs-fdlcap --source=http://gems.github.com
|
51
|
+
|
52
|
+
You may want to add the gem to your config.gems or geminstaller config as well.
|
53
|
+
|
54
|
+
You'll also need to add the following line to your deploy.rb:
|
55
|
+
|
56
|
+
require 'fdlcap/recipes'
|
4
57
|
|
5
58
|
== Copyright
|
6
59
|
|
7
|
-
Copyright (c) 2009 Gabe Varela. See LICENSE for details.
|
60
|
+
Copyright (c) 2009 Gabe Varela and Jay Zeschin. See LICENSE for details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.5
|
data/fdlcap.gemspec
CHANGED
@@ -2,22 +2,20 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{fdlcap}
|
5
|
-
s.version = "0.2.
|
5
|
+
s.version = "0.2.5"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Factory Design Labs"]
|
9
|
-
s.date = %q{2009-06-
|
9
|
+
s.date = %q{2009-06-26}
|
10
10
|
s.default_executable = %q{fdlcap}
|
11
11
|
s.email = %q{interactive@factorylabs.com}
|
12
12
|
s.executables = ["fdlcap"]
|
13
13
|
s.extra_rdoc_files = [
|
14
14
|
"LICENSE",
|
15
|
-
"README",
|
16
15
|
"README.rdoc"
|
17
16
|
]
|
18
17
|
s.files = [
|
19
18
|
"LICENSE",
|
20
|
-
"README",
|
21
19
|
"README.rdoc",
|
22
20
|
"Rakefile",
|
23
21
|
"VERSION",
|
@@ -1,5 +1,62 @@
|
|
1
1
|
Capistrano::Configuration.instance(:must_exist).load do
|
2
|
+
set(:create_database_on_cold, true)
|
3
|
+
|
4
|
+
set(:copy_compression, :gzip)
|
5
|
+
|
6
|
+
set(:exclude_tables, [])
|
7
|
+
|
8
|
+
# Returns the file extension used for the compression method in
|
9
|
+
# question.
|
10
|
+
def compression_extension
|
11
|
+
case copy_compression
|
12
|
+
when :gzip, :gz then "tar.gz"
|
13
|
+
when :bzip2, :bz2 then "tar.bz2"
|
14
|
+
when :zip then "zip"
|
15
|
+
else raise ArgumentError, "invalid compression type #{compression.inspect}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns the command necessary to compress the given directory
|
20
|
+
# into the given file. The command is returned as an array, where
|
21
|
+
# the first element is the utility to be used to perform the compression.
|
22
|
+
def compress(directory, file)
|
23
|
+
case copy_compression
|
24
|
+
when :gzip, :gz then ["tar", "czf", file, directory]
|
25
|
+
when :bzip2, :bz2 then ["tar", "cjf", file, directory]
|
26
|
+
when :zip then ["zip", "-qr", file, directory]
|
27
|
+
else raise ArgumentError, "invalid compression type #{copy_compression.inspect}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the command necessary to decompress the given file,
|
32
|
+
# relative to the current working directory. It must also
|
33
|
+
# preserve the directory structure in the file. The command is returned
|
34
|
+
# as an array, where the first element is the utility to be used to
|
35
|
+
# perform the decompression.
|
36
|
+
def decompress(file)
|
37
|
+
case copy_compression
|
38
|
+
when :gzip, :gz then ["tar", "xzf", file]
|
39
|
+
when :bzip2, :bz2 then ["tar", "xjf", file]
|
40
|
+
when :zip then ["unzip", "-q", file]
|
41
|
+
else raise ArgumentError, "invalid compression type #{copy_compression.inspect}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Capistrano::Configuration
|
46
|
+
def execute(command, failure_message = "Command failed")
|
47
|
+
puts "Executing: #{command}"
|
48
|
+
system(command) || raise(failure_message)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
2
52
|
namespace :database do
|
53
|
+
desc <<-DESC
|
54
|
+
create the production database
|
55
|
+
DESC
|
56
|
+
task :create, :roles => :db do
|
57
|
+
run "cd #{current_path} && rake db:create RAILS_ENV=#{rails_env} --trace"
|
58
|
+
end
|
59
|
+
|
3
60
|
desc "Push db remotely"
|
4
61
|
task :push_db_remotely, :roles => :db do
|
5
62
|
|
@@ -45,7 +102,7 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
45
102
|
--database #{local_db_info["database"]} | gzip > #{local_dump_file_gz_path}"
|
46
103
|
|
47
104
|
upload "#{local_dump_file_gz_path}", "#{dump_file_name}.gz", :via => :scp
|
48
|
-
|
105
|
+
|
49
106
|
execute "echo ^G^G^G^G^G"
|
50
107
|
|
51
108
|
run "gzip -df ~/#{dump_file_name}.gz"
|
@@ -63,5 +120,50 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
63
120
|
run "rm ~/#{dump_file_name}"
|
64
121
|
|
65
122
|
end
|
123
|
+
|
124
|
+
# ganked from pivotal
|
125
|
+
desc "Pull db locally"
|
126
|
+
task :pull_db_locally, :roles => :db do
|
127
|
+
all_db_info = YAML.load(File.read("config/database.yml"))
|
128
|
+
db_info = all_db_info[rails_env.to_s]
|
129
|
+
raise "Missing database.yml entry for #{rails_env.to_s}" unless db_info
|
130
|
+
|
131
|
+
database = db_info["database"]
|
132
|
+
dump_file = "/tmp/#{database}.sql"
|
133
|
+
|
134
|
+
db_host = db_info["host"]
|
135
|
+
host = ""
|
136
|
+
host_arg = " -h #{db_host}" if db_host
|
137
|
+
run "mysqldump -e -q --single-transaction \
|
138
|
+
-u #{db_info["username"]} --password=#{db_info["password"]} \
|
139
|
+
--database #{db_info["database"]} #{host_arg} | gzip > #{dump_file}.gz"
|
140
|
+
|
141
|
+
|
142
|
+
get "#{dump_file}.gz", "#{dump_file}.gz"
|
143
|
+
run "rm #{dump_file}.gz"
|
144
|
+
|
145
|
+
target_env = ENV['LOCAL_ENV'] || "development"
|
146
|
+
target_db_info = all_db_info[target_env]
|
147
|
+
target_db_login = "-u #{target_db_info["username"]} --password=#{target_db_info["password"]}"
|
148
|
+
target_db_login += " -h #{target_db_info["host"]}" if target_db_info["host"]
|
149
|
+
|
150
|
+
gunzip_cmd = "gunzip -c #{dump_file}.gz"
|
151
|
+
sed_cmd = "sed 's/#{db_info["database"]}/#{target_db_info["database"]}/g' > #{dump_file}"
|
152
|
+
execute("#{gunzip_cmd} | #{sed_cmd}", "gunzip/sed of #{dump_file}.gz failed")
|
153
|
+
execute("mysqladmin #{target_db_login} drop #{target_db_info["database"]} -f", "mysqladmin drop failed")
|
154
|
+
execute("mysqladmin #{target_db_login} create #{target_db_info["database"]}", "mysqladmin create failed")
|
155
|
+
execute("mysql #{target_db_login} --database #{target_db_info["database"]} < #{dump_file}", "mysql import failed")
|
156
|
+
execute("rake db:migrate RAILS_ENV=#{target_env}", "migrate failed")
|
157
|
+
execute("rm #{dump_file}", "rm of local unzipped #{dump_file} failed")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
namespace :deploy do
|
162
|
+
task :cold do
|
163
|
+
update
|
164
|
+
database.create if create_database_on_cold
|
165
|
+
migrate
|
166
|
+
start
|
167
|
+
end
|
66
168
|
end
|
67
169
|
end
|
@@ -4,25 +4,47 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
4
4
|
# Tasks
|
5
5
|
#
|
6
6
|
namespace :geminstaller do
|
7
|
-
desc
|
7
|
+
desc <<-DESC
|
8
|
+
install geminstaller
|
9
|
+
DESC
|
10
|
+
task :install, :only => { :geminstaller => true } do
|
11
|
+
as = fetch(:runner, "app")
|
12
|
+
via = fetch(:run_method, :sudo)
|
13
|
+
invoke_command "gem install geminstaller", :via => via, :as => as
|
14
|
+
invoke_command "gem source -a http://gems.github.com", :via => via, :as => as
|
15
|
+
end
|
16
|
+
|
17
|
+
desc <<-DESC
|
18
|
+
run geminstaller rake task to install gems on the server
|
19
|
+
DESC
|
8
20
|
task :run, :only => { :geminstaller => true } do
|
9
|
-
|
21
|
+
as = fetch(:runner, "app")
|
22
|
+
via = fetch(:run_method, :sudo)
|
23
|
+
invoke_command "/usr/bin/geminstaller -c #{current_path}/config/geminstaller.yml --geminstaller-output=all --rubygems-output=all", :via => via, :as => as
|
10
24
|
end
|
11
25
|
|
12
|
-
desc
|
13
|
-
|
14
|
-
|
15
|
-
|
26
|
+
desc <<-DESC
|
27
|
+
add geminstaller config to list of remote dependencies.
|
28
|
+
DESC
|
29
|
+
task :add_remote_gem_dependencies, :only => { :geminstaller => true } do
|
30
|
+
CONFIG_PATH = File.join('config', 'geminstaller.yml')
|
31
|
+
if File.exists?(CONFIG_PATH)
|
32
|
+
gems = YAML.load(ERB.new(File.read(CONFIG_PATH)).result)['gems']
|
33
|
+
gems.each do |gem|
|
34
|
+
depend :remote, :gem, gem['name'], gem['version']
|
35
|
+
end
|
36
|
+
end
|
16
37
|
end
|
17
38
|
end
|
18
39
|
|
19
40
|
#
|
20
41
|
# Callbacks
|
21
42
|
#
|
22
|
-
|
23
|
-
after
|
24
|
-
after
|
25
|
-
after
|
43
|
+
before "deploy:check", "geminstaller:add_remote_gem_dependencies"
|
44
|
+
after "deploy:setup", "geminstaller:install"
|
45
|
+
after "geminstaller:install", "geminstaller:run"
|
46
|
+
after "deploy:symlink", "geminstaller:run"
|
47
|
+
after "geminstaller:run", "deploy:migrate"
|
26
48
|
end
|
27
49
|
|
28
50
|
end
|
@@ -26,13 +26,53 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
26
26
|
|
27
27
|
namespace :autobench do
|
28
28
|
|
29
|
-
task :
|
30
|
-
|
31
|
-
run "/usr/local/bin/autobench --single_host --host1
|
32
|
-
download "/tmp/
|
33
|
-
run "rm /tmp/
|
29
|
+
task :run_test, :roles => :app do
|
30
|
+
options = ENV['OPTIONS'] || "--low_rate=1 --high_rate=20 --rate_step=2 --num_call=2 --num_conn=200"
|
31
|
+
run "/usr/local/bin/autobench --single_host --host1=#{ENV['HOST']} --uri1=#{ENV['URL']} --file=/tmp/test.bench.txt #{options}"
|
32
|
+
download "/tmp/test.bench.txt", "autobench/test.bench.txt", :via => :scp
|
33
|
+
run "rm /tmp/test.bench.txt"
|
34
34
|
end
|
35
35
|
|
36
36
|
end
|
37
|
+
|
38
|
+
namespace :install do
|
39
|
+
|
40
|
+
task :setup do
|
41
|
+
sudo "rm -rf src"
|
42
|
+
run "mkdir -p src"
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Install httperf"
|
46
|
+
task :httperf do
|
47
|
+
setup
|
48
|
+
|
49
|
+
cmd = [
|
50
|
+
"cd src",
|
51
|
+
"wget ftp://ftp.hpl.hp.com/pub/httperf/httperf-0.9.0.tar.gz",
|
52
|
+
"tar xfz httperf-0.9.0.tar.gz",
|
53
|
+
"cd httperf-0.9.0",
|
54
|
+
"./configure --prefix=/usr/local",
|
55
|
+
"make",
|
56
|
+
"sudo make install"
|
57
|
+
].join(' && ')
|
58
|
+
run cmd
|
59
|
+
run 'rm httperf-0.9.0.tar.gz'
|
60
|
+
end
|
61
|
+
|
62
|
+
task :autobench do
|
63
|
+
setup
|
64
|
+
|
65
|
+
cmd = [
|
66
|
+
"cd src",
|
67
|
+
"wget http://www.xenoclast.org/autobench/downloads/autobench-2.1.2.tar.gz",
|
68
|
+
"tar xfz autobench-2.1.2.tar.gz",
|
69
|
+
"cd autobench-2.1.2",
|
70
|
+
"make",
|
71
|
+
"sudo make install"
|
72
|
+
].join(' && ')
|
73
|
+
run cmd
|
74
|
+
run 'rm autobench-2.1.2.tar.gz'
|
75
|
+
end
|
76
|
+
end
|
37
77
|
|
38
78
|
end
|
data/lib/fdlcap/recipes/slice.rb
CHANGED
@@ -20,6 +20,20 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
desc <<-DESC
|
24
|
+
grep the production.log to find long running queries
|
25
|
+
DESC
|
26
|
+
task :grep_requests, :roles => :app do
|
27
|
+
run "grep 'Completed in [0-9]*' #{shared_path}/log/#{rails_env}.log"
|
28
|
+
end
|
29
|
+
|
30
|
+
desc <<-DESC
|
31
|
+
grep the production.log to find long running queries
|
32
|
+
DESC
|
33
|
+
task :grep_long_requests, :roles => :app do
|
34
|
+
run "grep 'Completed in [0-9][0-9]' #{shared_path}/log/#{rails_env}.log"
|
35
|
+
end
|
36
|
+
|
23
37
|
end
|
24
38
|
|
25
39
|
# Deploy the custom maintenance page
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: factorylabs-fdlcap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Factory Design Labs
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-06-
|
12
|
+
date: 2009-06-26 00:00:00 -07:00
|
13
13
|
default_executable: fdlcap
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -60,11 +60,9 @@ extensions: []
|
|
60
60
|
|
61
61
|
extra_rdoc_files:
|
62
62
|
- LICENSE
|
63
|
-
- README
|
64
63
|
- README.rdoc
|
65
64
|
files:
|
66
65
|
- LICENSE
|
67
|
-
- README
|
68
66
|
- README.rdoc
|
69
67
|
- Rakefile
|
70
68
|
- VERSION
|
data/README
DELETED
File without changes
|