nirvdrum-rubber 1.1.7

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 (186) hide show
  1. data/CHANGELOG +146 -0
  2. data/COPYING +339 -0
  3. data/README +6 -0
  4. data/TODO +11 -0
  5. data/VERSION +1 -0
  6. data/bin/vulcanize +41 -0
  7. data/generators/vulcanize/USAGE +6 -0
  8. data/generators/vulcanize/templates/apache/config/rubber/deploy-apache.rb +51 -0
  9. data/generators/vulcanize/templates/apache/config/rubber/role/apache/deflate.conf +10 -0
  10. data/generators/vulcanize/templates/apache/config/rubber/role/apache/expires.conf +9 -0
  11. data/generators/vulcanize/templates/apache/config/rubber/role/apache/headers.conf +6 -0
  12. data/generators/vulcanize/templates/apache/config/rubber/role/apache/monit-apache.conf +8 -0
  13. data/generators/vulcanize/templates/apache/config/rubber/role/apache/ports.conf +5 -0
  14. data/generators/vulcanize/templates/apache/config/rubber/role/apache/setenvif.conf +52 -0
  15. data/generators/vulcanize/templates/apache/config/rubber/role/web_tools/tools-apache-vhost.conf +66 -0
  16. data/generators/vulcanize/templates/apache/config/rubber/role/web_tools/tools-apache.auth +7 -0
  17. data/generators/vulcanize/templates/apache/config/rubber/role/web_tools/tools-index.html +34 -0
  18. data/generators/vulcanize/templates/apache/config/rubber/rubber-apache.yml +6 -0
  19. data/generators/vulcanize/templates/apache/templates.yml +1 -0
  20. data/generators/vulcanize/templates/base/Capfile +14 -0
  21. data/generators/vulcanize/templates/base/config/deploy.rb +55 -0
  22. data/generators/vulcanize/templates/base/config/rubber/common/crontab +17 -0
  23. data/generators/vulcanize/templates/base/config/rubber/common/monit-postfix.conf +8 -0
  24. data/generators/vulcanize/templates/base/config/rubber/common/rubber.profile +14 -0
  25. data/generators/vulcanize/templates/base/config/rubber/deploy-setup.rb +84 -0
  26. data/generators/vulcanize/templates/base/config/rubber/rubber-dns.yml +79 -0
  27. data/generators/vulcanize/templates/base/config/rubber/rubber.yml +227 -0
  28. data/generators/vulcanize/templates/base/lib/tasks/rubber.rake +15 -0
  29. data/generators/vulcanize/templates/base/script/cron-rake +18 -0
  30. data/generators/vulcanize/templates/base/script/cron-runner +18 -0
  31. data/generators/vulcanize/templates/base/script/cron-sh +67 -0
  32. data/generators/vulcanize/templates/base/templates.yml +1 -0
  33. data/generators/vulcanize/templates/complete_mongrel_mysql/config/rubber/role/haproxy/haproxy-mongrel.conf +23 -0
  34. data/generators/vulcanize/templates/complete_mongrel_mysql/config/rubber/role/nginx/nginx-mongrel.conf +113 -0
  35. data/generators/vulcanize/templates/complete_mongrel_mysql/config/rubber/rubber-complete.yml +41 -0
  36. data/generators/vulcanize/templates/complete_mongrel_mysql/templates.yml +6 -0
  37. data/generators/vulcanize/templates/complete_passenger_mysql/config/rubber/role/haproxy/haproxy-passenger.conf +21 -0
  38. data/generators/vulcanize/templates/complete_passenger_mysql/config/rubber/rubber-complete.yml +40 -0
  39. data/generators/vulcanize/templates/complete_passenger_mysql/templates.yml +10 -0
  40. data/generators/vulcanize/templates/cruise/config/rubber/deploy-cruise.rb +72 -0
  41. data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/cruise +40 -0
  42. data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/my.cnf +165 -0
  43. data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/production.rb +8 -0
  44. data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/site_config.rb +76 -0
  45. data/generators/vulcanize/templates/cruise/config/rubber/role/web_tools/cruise-nginx.conf +11 -0
  46. data/generators/vulcanize/templates/cruise/config/rubber/rubber-cruise.yml +18 -0
  47. data/generators/vulcanize/templates/cruise/templates.yml +1 -0
  48. data/generators/vulcanize/templates/haproxy/config/rubber/deploy-haproxy.rb +45 -0
  49. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/haproxy-base.conf +26 -0
  50. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/haproxy-default.conf +8 -0
  51. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/monit-haproxy.conf +9 -0
  52. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/syslog-haproxy.conf +6 -0
  53. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/syslogd-default.conf +17 -0
  54. data/generators/vulcanize/templates/haproxy/config/rubber/role/web_tools/haproxy-nginx.conf +10 -0
  55. data/generators/vulcanize/templates/haproxy/config/rubber/rubber-haproxy.yml +7 -0
  56. data/generators/vulcanize/templates/haproxy/templates.yml +1 -0
  57. data/generators/vulcanize/templates/jetty/config/rubber/deploy-jetty.rb +59 -0
  58. data/generators/vulcanize/templates/jetty/config/rubber/role/jetty/jetty.sh +589 -0
  59. data/generators/vulcanize/templates/jetty/config/rubber/role/jetty/jetty.xml +199 -0
  60. data/generators/vulcanize/templates/jetty/config/rubber/role/jetty/monit-jetty.conf +9 -0
  61. data/generators/vulcanize/templates/jetty/config/rubber/rubber-jetty.yml +10 -0
  62. data/generators/vulcanize/templates/jetty/templates.yml +1 -0
  63. data/generators/vulcanize/templates/memcached/config/memcached.yml +28 -0
  64. data/generators/vulcanize/templates/memcached/config/rubber/common/memcached.yml +14 -0
  65. data/generators/vulcanize/templates/memcached/config/rubber/role/memcached/memcached.conf +52 -0
  66. data/generators/vulcanize/templates/memcached/config/rubber/role/memcached/memcached_munin_plugin +249 -0
  67. data/generators/vulcanize/templates/memcached/config/rubber/rubber-memcached.yml +7 -0
  68. data/generators/vulcanize/templates/memcached/templates.yml +1 -0
  69. data/generators/vulcanize/templates/minimal_mysql/templates.yml +7 -0
  70. data/generators/vulcanize/templates/minimal_nodb/templates.yml +6 -0
  71. data/generators/vulcanize/templates/mongrel/config/rubber/deploy-mongrel.rb +75 -0
  72. data/generators/vulcanize/templates/mongrel/config/rubber/role/mongrel/mongrel_cluster.yml +12 -0
  73. data/generators/vulcanize/templates/mongrel/config/rubber/role/mongrel/monit-mongrel.conf +20 -0
  74. data/generators/vulcanize/templates/mongrel/config/rubber/rubber-mongrel.yml +9 -0
  75. data/generators/vulcanize/templates/mongrel/templates.yml +1 -0
  76. data/generators/vulcanize/templates/monit/config/rubber/common/monit-default.conf +15 -0
  77. data/generators/vulcanize/templates/monit/config/rubber/common/monit.conf +251 -0
  78. data/generators/vulcanize/templates/monit/config/rubber/deploy-monit.rb +32 -0
  79. data/generators/vulcanize/templates/monit/config/rubber/role/web_tools/monit-admin-nginx.conf +10 -0
  80. data/generators/vulcanize/templates/monit/config/rubber/rubber-monit.yml +6 -0
  81. data/generators/vulcanize/templates/monit/templates.yml +1 -0
  82. data/generators/vulcanize/templates/munin/config/rubber/common/monit-munin.conf +8 -0
  83. data/generators/vulcanize/templates/munin/config/rubber/common/munin-node.conf +48 -0
  84. data/generators/vulcanize/templates/munin/config/rubber/common/munin-plugins.conf +9 -0
  85. data/generators/vulcanize/templates/munin/config/rubber/deploy-munin.rb +46 -0
  86. data/generators/vulcanize/templates/munin/config/rubber/role/web_tools/munin-nginx.conf +8 -0
  87. data/generators/vulcanize/templates/munin/config/rubber/role/web_tools/munin-plugins.conf +31 -0
  88. data/generators/vulcanize/templates/munin/config/rubber/role/web_tools/munin.conf +80 -0
  89. data/generators/vulcanize/templates/munin/config/rubber/rubber-munin.yml +8 -0
  90. data/generators/vulcanize/templates/munin/script/munin/example_mysql_query.rb +57 -0
  91. data/generators/vulcanize/templates/munin/script/munin/example_simple.rb +24 -0
  92. data/generators/vulcanize/templates/munin/templates.yml +1 -0
  93. data/generators/vulcanize/templates/mysql/config/rubber/common/database.yml +11 -0
  94. data/generators/vulcanize/templates/mysql/config/rubber/deploy-mysql.rb +156 -0
  95. data/generators/vulcanize/templates/mysql/config/rubber/role/db/crontab +14 -0
  96. data/generators/vulcanize/templates/mysql/config/rubber/role/db/monit-mysql.cnf +10 -0
  97. data/generators/vulcanize/templates/mysql/config/rubber/role/db/my.cnf +167 -0
  98. data/generators/vulcanize/templates/mysql/config/rubber/role/mysql_slave/mysql_slave_munin_plugin +51 -0
  99. data/generators/vulcanize/templates/mysql/config/rubber/rubber-mysql.yml +46 -0
  100. data/generators/vulcanize/templates/mysql/templates.yml +1 -0
  101. data/generators/vulcanize/templates/mysql_cluster/config/rubber/common/mysql_cluster_migrations.rb +13 -0
  102. data/generators/vulcanize/templates/mysql_cluster/config/rubber/deploy-mysql_cluster.rb +173 -0
  103. data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_data/my.cnf +15 -0
  104. data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_mgm/ndb_mgmd.cnf +39 -0
  105. data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_sql/monit-mysql_cluster_sql.cnf +10 -0
  106. data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_sql/my.cnf +23 -0
  107. data/generators/vulcanize/templates/mysql_cluster/config/rubber/rubber-mysql_cluster.yml +32 -0
  108. data/generators/vulcanize/templates/mysql_cluster/templates.yml +1 -0
  109. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/database.yml +16 -0
  110. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/monit-mysql_proxy.cnf +10 -0
  111. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/mysql-proxy +153 -0
  112. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/mysql-proxy.conf +10 -0
  113. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/mysql-proxy.lua +5 -0
  114. data/generators/vulcanize/templates/mysql_proxy/config/rubber/deploy-mysql_proxy.rb +52 -0
  115. data/generators/vulcanize/templates/mysql_proxy/config/rubber/rubber-mysql_proxy.yml +11 -0
  116. data/generators/vulcanize/templates/mysql_proxy/templates.yml +1 -0
  117. data/generators/vulcanize/templates/nginx/config/rubber/deploy-nginx.rb +45 -0
  118. data/generators/vulcanize/templates/nginx/config/rubber/role/nginx/crontab +9 -0
  119. data/generators/vulcanize/templates/nginx/config/rubber/role/nginx/monit-nginx.conf +8 -0
  120. data/generators/vulcanize/templates/nginx/config/rubber/role/nginx/nginx.conf +42 -0
  121. data/generators/vulcanize/templates/nginx/config/rubber/role/web_tools/nginx-tools.conf +55 -0
  122. data/generators/vulcanize/templates/nginx/config/rubber/role/web_tools/tools-index.html +30 -0
  123. data/generators/vulcanize/templates/nginx/config/rubber/role/web_tools/tools-nginx.auth +7 -0
  124. data/generators/vulcanize/templates/nginx/config/rubber/rubber-nginx.yml +10 -0
  125. data/generators/vulcanize/templates/nginx/templates.yml +1 -0
  126. data/generators/vulcanize/templates/passenger/config/rubber/deploy-passenger.rb +37 -0
  127. data/generators/vulcanize/templates/passenger/config/rubber/role/passenger/munin-passenger-memory.conf +34 -0
  128. data/generators/vulcanize/templates/passenger/config/rubber/role/passenger/munin-passenger-sudoers.conf +7 -0
  129. data/generators/vulcanize/templates/passenger/config/rubber/role/passenger/munin-passenger.conf +47 -0
  130. data/generators/vulcanize/templates/passenger/config/rubber/role/passenger/passenger-apache-vhost.conf +46 -0
  131. data/generators/vulcanize/templates/passenger/config/rubber/role/passenger/passenger.conf +10 -0
  132. data/generators/vulcanize/templates/passenger/config/rubber/rubber-passenger.yml +15 -0
  133. data/generators/vulcanize/templates/passenger/templates.yml +3 -0
  134. data/generators/vulcanize/templates/redis/config/rubber/deploy-redis.rb +36 -0
  135. data/generators/vulcanize/templates/redis/config/rubber/role/redis/crontab +8 -0
  136. data/generators/vulcanize/templates/redis/config/rubber/role/redis/monit-redis.conf +9 -0
  137. data/generators/vulcanize/templates/redis/config/rubber/role/redis/redis.conf +141 -0
  138. data/generators/vulcanize/templates/redis/config/rubber/rubber-redis.yml +4 -0
  139. data/generators/vulcanize/templates/redis/templates.yml +1 -0
  140. data/generators/vulcanize/templates/resque/config/rubber/deploy-resque-worker-default.rb +38 -0
  141. data/generators/vulcanize/templates/resque/config/rubber/deploy-resque.rb +39 -0
  142. data/generators/vulcanize/templates/resque/config/rubber/role/resque_worker_default/monit-resque_worker_default.conf +19 -0
  143. data/generators/vulcanize/templates/resque/config/rubber/rubber-resque.yml +10 -0
  144. data/generators/vulcanize/templates/resque/templates.yml +3 -0
  145. data/generators/vulcanize/templates/sphinx/config/rubber/common/sphinx.yml +46 -0
  146. data/generators/vulcanize/templates/sphinx/config/rubber/deploy-sphinx.rb +112 -0
  147. data/generators/vulcanize/templates/sphinx/config/rubber/role/sphinx/crontab +11 -0
  148. data/generators/vulcanize/templates/sphinx/config/rubber/role/sphinx/monit-sphinx.conf +10 -0
  149. data/generators/vulcanize/templates/sphinx/config/rubber/rubber-sphinx.yml +6 -0
  150. data/generators/vulcanize/templates/sphinx/templates.yml +1 -0
  151. data/generators/vulcanize/vulcanize_generator.rb +67 -0
  152. data/lib/capistrano/hostcmd.rb +12 -0
  153. data/lib/rubber.rb +38 -0
  154. data/lib/rubber/capistrano.rb +1 -0
  155. data/lib/rubber/cloud.rb +13 -0
  156. data/lib/rubber/cloud/aws.rb +334 -0
  157. data/lib/rubber/cloud/base.rb +16 -0
  158. data/lib/rubber/configuration.rb +47 -0
  159. data/lib/rubber/dns.rb +13 -0
  160. data/lib/rubber/dns/base.rb +84 -0
  161. data/lib/rubber/dns/dyndns.rb +78 -0
  162. data/lib/rubber/dns/nettica.rb +117 -0
  163. data/lib/rubber/dns/zerigo.rb +174 -0
  164. data/lib/rubber/environment.rb +169 -0
  165. data/lib/rubber/generator.rb +197 -0
  166. data/lib/rubber/instance.rb +166 -0
  167. data/lib/rubber/recipes/rubber.rb +89 -0
  168. data/lib/rubber/recipes/rubber/bundles.rb +28 -0
  169. data/lib/rubber/recipes/rubber/deploy.rb +90 -0
  170. data/lib/rubber/recipes/rubber/instances.rb +393 -0
  171. data/lib/rubber/recipes/rubber/load_balancers.rb +44 -0
  172. data/lib/rubber/recipes/rubber/security_groups.rb +189 -0
  173. data/lib/rubber/recipes/rubber/setup.rb +457 -0
  174. data/lib/rubber/recipes/rubber/spot_requests.rb +17 -0
  175. data/lib/rubber/recipes/rubber/static_ips.rb +107 -0
  176. data/lib/rubber/recipes/rubber/utils.rb +203 -0
  177. data/lib/rubber/recipes/rubber/volumes.rb +264 -0
  178. data/lib/rubber/tasks/rubber.rb +279 -0
  179. data/lib/rubber/util.rb +37 -0
  180. data/rails/init.rb +9 -0
  181. data/test/environment_test.rb +133 -0
  182. data/test/generator_test.rb +323 -0
  183. data/test/instance_test.rb +93 -0
  184. data/test/test_helper.rb +8 -0
  185. data/test/util_test.rb +16 -0
  186. metadata +298 -0
@@ -0,0 +1,89 @@
1
+ # add this plugins lib dir to load path for capistrano
2
+ $:.unshift "#{File.dirname(__FILE__)}/../lib"
3
+ require 'rubygems'
4
+ require "socket"
5
+ require 'resolv'
6
+ require 'enumerator'
7
+ require 'capistrano/hostcmd'
8
+ require 'pp'
9
+ require 'rubber'
10
+
11
+ namespace :rubber do
12
+
13
+ # advise capistrano's task method so that tasks for non-existant roles don't
14
+ # fail when roles isn't defined due to using a FILTER for load_roles
15
+ # If you have a task you need to execute even when there are no
16
+ # roles, you have to use required_task instead of task - see rubber:create
17
+ # as an example of this role bootstrapping problem.
18
+ def allow_optional_tasks(ns)
19
+ class << ns
20
+ alias :required_task :task
21
+ def task(name, options={}, &block)
22
+ required_task(name, options) do
23
+ # define empty roles for the case when a task has a role that we don't define anywhere
24
+ [*options[:roles]].each do |r|
25
+ roles[r] ||= []
26
+ end
27
+
28
+ if find_servers_for_task(current_task).empty?
29
+ logger.info "No servers for task #{name}, skipping"
30
+ next
31
+ end
32
+ block.call
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ allow_optional_tasks(self)
39
+ on :load, "rubber:init"
40
+
41
+ required_task :init do
42
+ # Require cap 2.4 since we depend on bugs that have been fixed
43
+ require 'capistrano/version'
44
+ if Capistrano::Version::MAJOR < 2 || Capistrano::Version::MINOR < 4
45
+ fatal "rubber requires capistrano 2.4.0 or greater"
46
+ end
47
+
48
+ set :rubber_cfg, Rubber::Configuration.get_configuration(RUBBER_ENV)
49
+ set :rubber_env, rubber_cfg.environment.bind()
50
+ set :rubber_instances, rubber_cfg.instance
51
+
52
+ set :cloud, Rubber::Cloud::get_provider(rubber_env.cloud_provider || "aws", rubber_env, self)
53
+
54
+ load_roles() unless rubber_env.disable_auto_roles
55
+ # NOTE: for some reason Capistrano requires you to have both the public and
56
+ # the private key in the same folder, the public key should have the
57
+ # extension ".pub".
58
+ ssh_options[:keys] = rubber_env.cloud_providers[rubber_env.cloud_provider].key_file
59
+ end
60
+
61
+
62
+ # Automatically load and define capistrano roles from instance config
63
+ def load_roles
64
+ top.roles.clear
65
+
66
+ # define empty roles for all known ones so tasks don't fail if a role
67
+ # doesn't exist due to a filter
68
+ all_roles = rubber_instances.all_roles
69
+ all_roles += rubber_cfg.environment.known_roles
70
+ all_roles.uniq!
71
+ all_roles.each {|name| top.roles[name.to_sym] = []}
72
+
73
+ # define capistrano host => role mapping for all instances
74
+ rubber_instances.filtered.each do |ic|
75
+ ic.roles.each do |role|
76
+ opts = Rubber::Util::symbolize_keys(role.options)
77
+ msg = "Auto role: #{role.name.to_sym} => #{ic.full_name}"
78
+ msg << ", #{opts.inspect}" if opts.inspect.size > 0
79
+ logger.info msg
80
+ top.role role.name.to_sym, ic.full_name, opts
81
+ end
82
+ end
83
+ end
84
+
85
+ end
86
+
87
+ Dir[File.join(File.dirname(__FILE__), 'rubber/*.rb')].each do |rubber_part|
88
+ load(rubber_part)
89
+ end
@@ -0,0 +1,28 @@
1
+ namespace :rubber do
2
+
3
+ desc "Back up and register an image of the running instance"
4
+ task :bundle do
5
+ if find_servers_for_task(current_task).size > 1
6
+ fatal "Can only bundle a single instance at a time, use FILTER to limit the scope"
7
+ end
8
+ image_name = get_env('IMAGE', "The image name for the bundle", true, Time.now.strftime("%Y%m%d_%H%M"))
9
+ image_id = cloud.create_image(image_name)
10
+ logger.info "Newly registered image is: #{image_id}"
11
+ end
12
+
13
+ desc "De-register and Destroy the image for the given name"
14
+ required_task :destroy_bundle do
15
+ image_id = get_env('IMAGE_ID', 'The id of the image to be destroyed', true)
16
+ cloud.destroy_image(image_id)
17
+ end
18
+
19
+ desc "Describes all your own image bundles"
20
+ required_task :describe_bundles do
21
+ images = cloud.describe_images()
22
+ images.each do |image|
23
+ logger.info "ID: #{image[:id]}"
24
+ logger.info "Location: #{image[:location]}"
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,90 @@
1
+ namespace :rubber do
2
+
3
+ # Add in some hooks so that we can insert our own hooks at head/tail of
4
+ # hook chain - this is needed for making monit stop before everyone else.
5
+ before "deploy:start", "rubber:pre_start"
6
+ before "deploy:restart", "rubber:pre_restart"
7
+ before "deploy:stop", "rubber:pre_stop"
8
+ on :load do
9
+ after "deploy:start", "rubber:post_start"
10
+ after "deploy:restart", "rubber:post_restart"
11
+ after "deploy:stop", "rubber:post_stop"
12
+ end
13
+
14
+ task :pre_start do
15
+ end
16
+ task :pre_restart do
17
+ end
18
+ task :pre_stop do
19
+ end
20
+ task :post_start do
21
+ end
22
+ task :post_restart do
23
+ end
24
+ task :post_stop do
25
+ end
26
+
27
+ # Don't want to do rubber:config for update_code as that tree isn't official
28
+ # until it is 'committed' by the symlink task (and doing so causes it to run
29
+ # for bootstrap_db which should only config the db config file). However,
30
+ # deploy:migrations doesn't call update, so we need an additional trigger for
31
+ # it
32
+ after "deploy:update", "rubber:config"
33
+ after "deploy:rollback_code", "rubber:config"
34
+ before "deploy:migrate", "rubber:config"
35
+
36
+ desc <<-DESC
37
+ Configures the deployed rails application by running the rubber configuration process
38
+ DESC
39
+ task :config do
40
+ opts = {}
41
+ opts['NO_POST'] = true if ENV['NO_POST']
42
+ opts['FILE'] = ENV['FILE'] if ENV['FILE']
43
+ opts['RUBBER_ENV'] = RUBBER_ENV
44
+ # we need to set rails env as well because when running rake
45
+ # in a rails project, rails gets loaded before the rubber hook gets run
46
+ opts['RAILS_ENV'] = RUBBER_ENV
47
+
48
+ # when running deploy:migrations, we need to run config against release_path
49
+ opts[:deploy_path] = current_release if fetch(:migrate_target, :current).to_sym == :latest
50
+
51
+ run_config(opts)
52
+ end
53
+
54
+ # because we start server as appserver user, but migrate as root, server needs to be able to write logs, etc.
55
+ before "rubber:pre_start", "rubber:setup_app_permissions"
56
+ before "rubber:pre_restart", "rubber:setup_app_permissions"
57
+
58
+ desc <<-DESC
59
+ Sets permissions of files in application directory to be owned by app_user.
60
+ DESC
61
+ task :setup_app_permissions do
62
+ run "find #{shared_path} -name cached-copy -prune -o -print | xargs chown #{rubber_env.app_user}:#{rubber_env.app_user}"
63
+ run "chown -R #{rubber_env.app_user}:#{rubber_env.app_user} #{current_path}/tmp"
64
+ end
65
+
66
+ def run_config(options={})
67
+ path = options.delete(:deploy_path) || current_path
68
+ extra_env = options.keys.inject("") {|all, k| "#{all} #{k}=\"#{options[k]}\""}
69
+
70
+ # Need to do this so we can work with staging instances without having to
71
+ # checkin instance file between create and bootstrap, as well as during a deploy
72
+ if fetch(:push_instance_config, false)
73
+ push_files = [rubber_instances.file] + rubber_cfg.environment.config_files
74
+ push_files.each do |file|
75
+ dest_file = file.sub(/^#{RUBBER_ROOT}\/?/, '')
76
+ put(File.read(file), File.join(path, dest_file), :mode => "+r")
77
+ end
78
+ end
79
+
80
+ # if the user has defined a secret config file, then push it into RUBBER_ROOT/config/rubber
81
+ secret = rubber_cfg.environment.config_secret
82
+ if secret && File.exist?(secret)
83
+ base = rubber_cfg.environment.config_root.sub(/^#{RUBBER_ROOT}\/?/, '')
84
+ put(File.read(secret), File.join(path, base, File.basename(secret)), :mode => "+r")
85
+ end
86
+
87
+ sudo "sh -c 'cd #{path} && #{extra_env} rake rubber:config'"
88
+ end
89
+
90
+ end
@@ -0,0 +1,393 @@
1
+ namespace :rubber do
2
+
3
+ desc <<-DESC
4
+ Create a new EC2 instance with the given ALIAS and ROLES
5
+ DESC
6
+ required_task :create do
7
+ instance_alias = get_env('ALIAS', "Instance alias (e.g. web01)", true)
8
+
9
+ env = rubber_cfg.environment.bind(nil, instance_alias)
10
+ default_roles = env.instance_roles
11
+ r = get_env("ROLES", "Instance roles (e.g. web,app,db:primary=true)", true, default_roles)
12
+
13
+ create_spot_instance = ENV.delete("SPOT_INSTANCE") || env.cloud_providers[env.cloud_provider].spot_instance
14
+
15
+ if r == '*'
16
+ instance_roles = rubber_cfg.environment.known_roles
17
+ instance_roles = instance_roles.collect {|role| role == "db" ? "db:primary=true" : role }
18
+ else
19
+ instance_roles = r.split(",")
20
+ end
21
+
22
+ ir = []
23
+ instance_roles.each do |r|
24
+ role = Rubber::Configuration::RoleItem.parse(r)
25
+
26
+ # If user doesn't setup a primary db, then be nice and do it
27
+ if role.name == "db" && role.options["primary"] == nil && rubber_instances.for_role("db").size == 0
28
+ value = Capistrano::CLI.ui.ask("You do not have a primary db role, should #{instance_alias} be it [y/n]?: ")
29
+ role.options["primary"] = true if value =~ /^y/
30
+ end
31
+
32
+ ir << role
33
+ end
34
+
35
+ # Add in roles that the given set of roles depends on
36
+ ir = Rubber::Configuration::RoleItem.expand_role_dependencies(ir, get_role_dependencies)
37
+
38
+ create_instance(instance_alias, ir, create_spot_instance)
39
+ end
40
+
41
+ desc <<-DESC
42
+ Refresh the host data for a EC2 instance with the given ALIAS.
43
+ This is useful to run when rubber:create fails after instance creation
44
+ DESC
45
+ task :refresh do
46
+ instance_alias = get_env('ALIAS', "Instance alias (e.g. web01)", true)
47
+ ENV.delete('ROLES') # so we don't get an error if people leave ROLES in env from :create CLI
48
+ refresh_instance(instance_alias)
49
+ end
50
+
51
+ desc <<-DESC
52
+ Destroy the EC2 instance for the given ALIAS
53
+ DESC
54
+ task :destroy do
55
+ instance_alias = get_env('ALIAS', "Instance alias (e.g. web01)", true)
56
+ ENV.delete('ROLES') # so we don't get an error if people leave ROLES in env from :create CLI
57
+ destroy_instance(instance_alias)
58
+ end
59
+
60
+ desc <<-DESC
61
+ Destroy ALL the EC2 instances for the current env
62
+ DESC
63
+ task :destroy_all do
64
+ rubber_instances.each do |ic|
65
+ destroy_instance(ic.name)
66
+ end
67
+ end
68
+
69
+ desc <<-DESC
70
+ Adds the given ROLES to the instance named ALIAS
71
+ DESC
72
+ required_task :add_role do
73
+ instance_alias = get_env('ALIAS', "Instance alias (e.g. web01)", true)
74
+ r = get_env('ROLES', "Instance roles (e.g. web,app,db:primary=true)", true)
75
+
76
+ instance_roles = r.split(",")
77
+
78
+ ir = []
79
+ instance_roles.each do |r|
80
+ role = Rubber::Configuration::RoleItem.parse(r)
81
+ ir << role
82
+ end
83
+
84
+ # Add in roles that the given set of roles depends on
85
+ ir = Rubber::Configuration::RoleItem.expand_role_dependencies(ir, get_role_dependencies)
86
+
87
+ instance = rubber_instances[instance_alias]
88
+ fatal "Instance does not exist: #{instance_alias}" unless instance
89
+
90
+ instance.roles = (instance.roles + ir).uniq
91
+ rubber_instances.save()
92
+ logger.info "Roles for #{instance_alias} are now:"
93
+ logger.info instance.role_names.sort.join("\n")
94
+ logger.info ''
95
+ logger.info "Run 'cap rubber:bootstrap' if done adding roles"
96
+ end
97
+
98
+ desc <<-DESC
99
+ Removes the given ROLES from the instance named ALIAS
100
+ DESC
101
+ required_task :remove_role do
102
+ instance_alias = get_env('ALIAS', "Instance alias (e.g. web01)", true)
103
+ r = get_env('ROLES', "Instance roles (e.g. web,app,db:primary=true)", true)
104
+
105
+ instance_roles = r.split(",")
106
+
107
+ ir = []
108
+ instance_roles.each do |r|
109
+ role = Rubber::Configuration::RoleItem.parse(r)
110
+ ir << role
111
+ end
112
+
113
+ instance = rubber_instances[instance_alias]
114
+ fatal "Instance does not exist: #{instance_alias}" unless instance
115
+
116
+ instance.roles = (instance.roles - ir).uniq
117
+ rubber_instances.save()
118
+ logger.info "Roles for #{instance_alias} are now:"
119
+ logger.info instance.role_names.sort.join("\n")
120
+ end
121
+
122
+ desc <<-DESC
123
+ List all your EC2 instances
124
+ DESC
125
+ required_task :describe do
126
+ results = []
127
+ format = "%-10s %-10s %-10s %-15s %-30s"
128
+ results << format % %w[InstanceID State Zone IP Alias\ (*=unknown)]
129
+
130
+ instances = cloud.describe_instances()
131
+ instances.each do |instance|
132
+ local_alias = find_alias(instance[:external_ip], instance[:id], instance[:state] == 'running')
133
+ results << format % [instance[:id], instance[:state], instance[:zone], instance[:external_ip] || "NoIP", local_alias || "Unknown"]
134
+ end
135
+ results.each {|r| logger.info r}
136
+ end
137
+
138
+ desc <<-DESC
139
+ Describes the availability zones
140
+ DESC
141
+ required_task :describe_zones do
142
+ results = []
143
+ format = "%-20s %-15s"
144
+ results << format % %w[Name State]
145
+
146
+ zones = cloud.describe_availability_zones()
147
+ zones.each do |zone|
148
+ results << format % [zone[:name], zone[:state]]
149
+ end
150
+
151
+ results.each {|r| logger.info r}
152
+ end
153
+
154
+
155
+ set :print_ip_command, "ifconfig eth0 | awk 'NR==2 {print $2}' | awk -F: '{print $2}'"
156
+
157
+ # Creates a new ec2 instance with the given alias and roles
158
+ # Configures aliases (/etc/hosts) on local and remote machines
159
+ def create_instance(instance_alias, instance_roles, create_spot_instance=false)
160
+ fatal "Instance already exists: #{instance_alias}" if rubber_instances[instance_alias]
161
+
162
+ role_names = instance_roles.collect{|x| x.name}
163
+ env = rubber_cfg.environment.bind(role_names, instance_alias)
164
+
165
+ # We need to use security_groups during create, so create them up front
166
+ setup_security_groups(instance_alias, role_names)
167
+ security_groups = get_assigned_security_groups(instance_alias, role_names)
168
+
169
+ ami = env.cloud_providers[env.cloud_provider].image_id
170
+ ami_type = env.cloud_providers[env.cloud_provider].image_type
171
+ availability_zone = env.availability_zone
172
+
173
+ if create_spot_instance
174
+ spot_price = env.cloud_providers[env.cloud_provider].spot_price.to_s
175
+
176
+ logger.info "Creating spot instance request for instance #{ami}/#{ami_type}/#{security_groups.join(',') rescue 'Default'}/#{availability_zone || 'Default'}"
177
+ request_id = cloud.create_spot_instance_request(spot_price, ami, ami_type, security_groups, availability_zone)
178
+
179
+ print "Waiting for spot instance request to be fulfilled"
180
+ max_wait_time = env.cloud_providers[env.cloud_provider].spot_instance_request_timeout || (1.0 / 0) # Use the specified timeout value or default to infinite.
181
+ instance_id = nil
182
+ while instance_id.nil? do
183
+ print "."
184
+ sleep 2
185
+ max_wait_time -= 2
186
+
187
+ request = cloud.describe_spot_instance_requests(request_id).first
188
+ instance_id = request[:instance_id]
189
+
190
+ if max_wait_time < 0 && instance_id.nil?
191
+ cloud.destroy_spot_instance_request(request[:id])
192
+
193
+ print "\n"
194
+ print "Failed to fulfill spot instance in the time specified. Falling back to on-demand instance creation."
195
+ break
196
+ end
197
+ end
198
+
199
+ print "\n"
200
+ end
201
+
202
+ if !create_spot_instance || (create_spot_instance && max_wait_time < 0)
203
+ logger.info "Creating instance #{ami}/#{ami_type}/#{security_groups.join(',') rescue 'Default'}/#{availability_zone || 'Default'}"
204
+ instance_id = cloud.create_instance(ami, ami_type, security_groups, availability_zone)
205
+ end
206
+
207
+ logger.info "Instance #{instance_id} created"
208
+
209
+ instance_item = Rubber::Configuration::InstanceItem.new(instance_alias, env.domain, instance_roles, instance_id, security_groups)
210
+ instance_item.spot_instance_request_id = request_id if create_spot_instance
211
+ rubber_instances.add(instance_item)
212
+ rubber_instances.save()
213
+
214
+
215
+ print "Waiting for instance to start"
216
+ while true do
217
+ print "."
218
+ sleep 2
219
+ instance = cloud.describe_instances(instance_id).first
220
+
221
+ if instance[:state] == "running"
222
+ print "\n"
223
+ logger.info "Instance running, fetching hostname/ip data"
224
+ instance_item.external_host = instance[:external_host]
225
+ instance_item.external_ip = instance[:external_ip]
226
+ instance_item.internal_host = instance[:internal_host]
227
+ instance_item.zone = instance[:zone]
228
+ rubber_instances.save()
229
+
230
+ # setup amazon elastic ips if configured to do so
231
+ setup_static_ips
232
+
233
+ # Need to setup aliases so ssh doesn't give us errors when we
234
+ # later try? to connect to same ip but using alias
235
+ setup_local_aliases
236
+
237
+ # re-load the roles since we may have just defined new ones
238
+ load_roles() unless env.disable_auto_roles
239
+
240
+ # Connect to newly created instance and grab its internal ip
241
+ # so that we can update all aliases
242
+
243
+ task :_get_ip, :hosts => instance_item.external_ip do
244
+ instance_item.internal_ip = capture(print_ip_command).strip
245
+ rubber_instances.save()
246
+ end
247
+
248
+ # even though instance is running, sometimes ssh hasn't started yet,
249
+ # so retry on connect failure
250
+ begin
251
+ _get_ip
252
+ rescue ConnectionError
253
+ sleep 2
254
+ logger.info "Failed to connect to #{instance_alias} (#{instance_item.external_ip}), retrying"
255
+ retry
256
+ end
257
+
258
+ # Add the aliases for this instance to all other hosts
259
+ setup_remote_aliases
260
+ setup_dns_aliases
261
+
262
+ break
263
+ end
264
+ end
265
+ end
266
+
267
+ # Refreshes a ec2 instance with the given alias
268
+ # Configures aliases (/etc/hosts) on local and remote machines
269
+ def refresh_instance(instance_alias)
270
+ instance_item = rubber_instances[instance_alias]
271
+
272
+ fatal "Instance does not exist: #{instance_alias}" if ! instance_item
273
+
274
+ env = rubber_cfg.environment.bind(instance_item.role_names, instance_alias)
275
+
276
+ instance = cloud.describe_instances(instance_item.instance_id).first
277
+
278
+ if instance[:state] == "running"
279
+ logger.info "\nInstance running, fetching hostname/ip data"
280
+ instance_item.external_host = instance[:external_host]
281
+ instance_item.external_ip = instance[:external_ip]
282
+ instance_item.internal_host = instance[:internal_host]
283
+ instance_item.zone = instance[:zone]
284
+
285
+ # setup amazon elastic ips if configured to do so
286
+ setup_static_ips
287
+
288
+ # Need to setup aliases so ssh doesn't give us errors when we
289
+ # later try to connect to same ip but using alias
290
+ setup_local_aliases
291
+
292
+ # re-load the roles since we may have just defined new ones
293
+ load_roles() unless env.disable_auto_roles
294
+
295
+ # Connect to newly created instance and grab its internal ip
296
+ # so that we can update all aliases
297
+ task :_get_ip, :hosts => instance_item.external_ip do
298
+ instance_item.internal_ip = capture(print_ip_command).strip
299
+ rubber_instances.save()
300
+ end
301
+
302
+ # even though instance is running, sometimes ssh hasn't started yet,
303
+ # so retry on connect failure
304
+ begin
305
+ _get_ip
306
+ rescue ConnectionError
307
+ sleep 2
308
+ logger.info "Failed to connect to #{instance_alias} (#{instance_item.external_ip}), retrying"
309
+ retry
310
+ end
311
+
312
+
313
+ # Add the aliases for this instance to all other hosts
314
+ setup_remote_aliases
315
+ setup_dns_aliases
316
+ end
317
+ end
318
+
319
+
320
+ # Destroys the given ec2 instance
321
+ def destroy_instance(instance_alias)
322
+ instance_item = rubber_instances[instance_alias]
323
+ fatal "Instance does not exist: #{instance_alias}" if ! instance_item
324
+
325
+ env = rubber_cfg.environment.bind(instance_item.role_names, instance_item.name)
326
+
327
+ value = Capistrano::CLI.ui.ask("About to DESTROY #{instance_alias} (#{instance_item.instance_id}) in mode #{RUBBER_ENV}. Are you SURE [yes/NO]?: ")
328
+ fatal("Exiting", 0) if value != "yes"
329
+
330
+ if instance_item.static_ip
331
+ value = Capistrano::CLI.ui.ask("Instance has a static ip, do you want to release it? [y/N]?: ")
332
+ destroy_static_ip(instance_item.static_ip) if value =~ /^y/
333
+ end
334
+
335
+ if instance_item.volumes
336
+ value = Capistrano::CLI.ui.ask("Instance has persistent volumes, do you want to destroy them? [y/N]?: ")
337
+ if value =~ /^y/
338
+ instance_item.volumes.clone.each do |volume_id|
339
+ destroy_volume(volume_id)
340
+ end
341
+ end
342
+ end
343
+
344
+ logger.info "Destroying instance alias=#{instance_alias}, instance_id=#{instance_item.instance_id}"
345
+
346
+ cloud.destroy_instance(instance_item.instance_id)
347
+
348
+ rubber_instances.remove(instance_alias)
349
+ rubber_instances.save()
350
+
351
+ # re-load the roles since we just removed some and setup_remote_aliases
352
+ # shouldn't hit removed ones
353
+ load_roles() unless env.disable_auto_roles
354
+
355
+ setup_aliases
356
+ destroy_dyndns(instance_item)
357
+ cleanup_known_hosts(instance_item) unless env.disable_known_hosts_cleanup
358
+ end
359
+
360
+
361
+ # delete from ~/.ssh/known_hosts all lines that begin with ec2- or instance_alias
362
+ def cleanup_known_hosts(instance_item)
363
+ logger.info "Cleaning ~/.ssh/known_hosts"
364
+ File.open(File.expand_path('~/.ssh/known_hosts'), 'r+') do |f|
365
+ out = ""
366
+ f.each do |line|
367
+ line = case line
368
+ when /^ec2-/; ''
369
+ when /#{instance_item.full_name}/; ''
370
+ when /#{instance_item.external_host}/; ''
371
+ when /#{instance_item.external_ip}/; ''
372
+ else line;
373
+ end
374
+ out << line
375
+ end
376
+ f.pos = 0
377
+ f.print out
378
+ f.truncate(f.pos)
379
+ end
380
+ end
381
+
382
+ def get_role_dependencies
383
+ # convert string format of role_dependencies from rubber.yml into
384
+ # objects for use by expand_role_dependencies
385
+ deps = {}
386
+ rubber_env.role_dependencies.each do |k, v|
387
+ rhs = Array(v).collect {|r| Rubber::Configuration::RoleItem.parse(r)}
388
+ deps[Rubber::Configuration::RoleItem.parse(k)] = rhs
389
+ end if rubber_env.role_dependencies
390
+ return deps
391
+ end
392
+
393
+ end