rubber 1.0.2

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 (163) hide show
  1. data/CHANGELOG +39 -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 +62 -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 +30 -0
  18. data/generators/vulcanize/templates/apache/config/rubber/rubber-apache.yml +7 -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 +16 -0
  23. data/generators/vulcanize/templates/base/config/rubber/common/profile.rc +9 -0
  24. data/generators/vulcanize/templates/base/config/rubber/deploy-setup.rb +104 -0
  25. data/generators/vulcanize/templates/base/config/rubber/rubber.yml +241 -0
  26. data/generators/vulcanize/templates/base/lib/tasks/rubber.rake +15 -0
  27. data/generators/vulcanize/templates/base/script/cron-rake +18 -0
  28. data/generators/vulcanize/templates/base/script/cron-runner +18 -0
  29. data/generators/vulcanize/templates/base/script/cron-sh +67 -0
  30. data/generators/vulcanize/templates/base/templates.yml +1 -0
  31. data/generators/vulcanize/templates/complete_mongrel_mysql/config/rubber/role/haproxy/haproxy-mongrel.conf +23 -0
  32. data/generators/vulcanize/templates/complete_mongrel_mysql/config/rubber/role/nginx/nginx-mongrel.conf +113 -0
  33. data/generators/vulcanize/templates/complete_mongrel_mysql/config/rubber/rubber-complete.yml +41 -0
  34. data/generators/vulcanize/templates/complete_mongrel_mysql/templates.yml +6 -0
  35. data/generators/vulcanize/templates/complete_passenger_mysql/config/rubber/role/haproxy/haproxy-passenger.conf +19 -0
  36. data/generators/vulcanize/templates/complete_passenger_mysql/config/rubber/rubber-complete.yml +40 -0
  37. data/generators/vulcanize/templates/complete_passenger_mysql/templates.yml +10 -0
  38. data/generators/vulcanize/templates/cruise/config/rubber/deploy-cruise.rb +72 -0
  39. data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/cruise +40 -0
  40. data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/my.cnf +165 -0
  41. data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/production.rb +8 -0
  42. data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/site_config.rb +76 -0
  43. data/generators/vulcanize/templates/cruise/config/rubber/role/web_tools/cruise-nginx.conf +11 -0
  44. data/generators/vulcanize/templates/cruise/config/rubber/rubber-cruise.yml +18 -0
  45. data/generators/vulcanize/templates/cruise/templates.yml +1 -0
  46. data/generators/vulcanize/templates/haproxy/config/rubber/deploy-haproxy.rb +45 -0
  47. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/haproxy-base.conf +26 -0
  48. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/haproxy-default.conf +8 -0
  49. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/monit-haproxy.conf +9 -0
  50. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/syslog-haproxy.conf +6 -0
  51. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/syslogd-default.conf +17 -0
  52. data/generators/vulcanize/templates/haproxy/config/rubber/role/web_tools/haproxy-nginx.conf +10 -0
  53. data/generators/vulcanize/templates/haproxy/config/rubber/rubber-haproxy.yml +7 -0
  54. data/generators/vulcanize/templates/haproxy/templates.yml +1 -0
  55. data/generators/vulcanize/templates/memcached/config/memcached.yml +28 -0
  56. data/generators/vulcanize/templates/memcached/config/rubber/common/memcached.yml +14 -0
  57. data/generators/vulcanize/templates/memcached/config/rubber/role/memcached/memcached.conf +52 -0
  58. data/generators/vulcanize/templates/memcached/config/rubber/role/memcached/memcached_munin_plugin +249 -0
  59. data/generators/vulcanize/templates/memcached/config/rubber/rubber-memcached.yml +7 -0
  60. data/generators/vulcanize/templates/memcached/templates.yml +1 -0
  61. data/generators/vulcanize/templates/minimal_mysql/templates.yml +7 -0
  62. data/generators/vulcanize/templates/minimal_nodb/templates.yml +6 -0
  63. data/generators/vulcanize/templates/mongrel/config/rubber/deploy-mongrel.rb +75 -0
  64. data/generators/vulcanize/templates/mongrel/config/rubber/role/mongrel/mongrel_cluster.yml +12 -0
  65. data/generators/vulcanize/templates/mongrel/config/rubber/role/mongrel/monit-mongrel.conf +20 -0
  66. data/generators/vulcanize/templates/mongrel/config/rubber/rubber-mongrel.yml +9 -0
  67. data/generators/vulcanize/templates/mongrel/templates.yml +1 -0
  68. data/generators/vulcanize/templates/monit/config/rubber/common/monit-default.conf +15 -0
  69. data/generators/vulcanize/templates/monit/config/rubber/common/monit.conf +251 -0
  70. data/generators/vulcanize/templates/monit/config/rubber/deploy-monit.rb +32 -0
  71. data/generators/vulcanize/templates/monit/config/rubber/role/web_tools/monit-admin-nginx.conf +10 -0
  72. data/generators/vulcanize/templates/monit/config/rubber/rubber-monit.yml +6 -0
  73. data/generators/vulcanize/templates/monit/templates.yml +1 -0
  74. data/generators/vulcanize/templates/munin/config/rubber/common/monit-munin.conf +8 -0
  75. data/generators/vulcanize/templates/munin/config/rubber/common/munin-node.conf +48 -0
  76. data/generators/vulcanize/templates/munin/config/rubber/deploy-munin.rb +46 -0
  77. data/generators/vulcanize/templates/munin/config/rubber/role/web_tools/munin-nginx.conf +8 -0
  78. data/generators/vulcanize/templates/munin/config/rubber/role/web_tools/munin-plugins.conf +31 -0
  79. data/generators/vulcanize/templates/munin/config/rubber/role/web_tools/munin.conf +80 -0
  80. data/generators/vulcanize/templates/munin/config/rubber/rubber-munin.yml +8 -0
  81. data/generators/vulcanize/templates/munin/script/munin/example_mysql_query.rb +57 -0
  82. data/generators/vulcanize/templates/munin/script/munin/example_simple.rb +24 -0
  83. data/generators/vulcanize/templates/munin/templates.yml +1 -0
  84. data/generators/vulcanize/templates/mysql/config/rubber/common/database.yml +11 -0
  85. data/generators/vulcanize/templates/mysql/config/rubber/deploy-mysql.rb +156 -0
  86. data/generators/vulcanize/templates/mysql/config/rubber/role/db/crontab +14 -0
  87. data/generators/vulcanize/templates/mysql/config/rubber/role/db/monit-mysql.cnf +10 -0
  88. data/generators/vulcanize/templates/mysql/config/rubber/role/db/my.cnf +167 -0
  89. data/generators/vulcanize/templates/mysql/config/rubber/role/mysql_slave/mysql_slave_munin_plugin +51 -0
  90. data/generators/vulcanize/templates/mysql/config/rubber/rubber-mysql.yml +46 -0
  91. data/generators/vulcanize/templates/mysql/templates.yml +1 -0
  92. data/generators/vulcanize/templates/mysql_cluster/config/rubber/common/mysql_cluster_migrations.rb +13 -0
  93. data/generators/vulcanize/templates/mysql_cluster/config/rubber/deploy-mysql_cluster.rb +173 -0
  94. data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_data/my.cnf +15 -0
  95. data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_mgm/ndb_mgmd.cnf +39 -0
  96. data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_sql/monit-mysql_cluster_sql.cnf +10 -0
  97. data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_sql/my.cnf +23 -0
  98. data/generators/vulcanize/templates/mysql_cluster/config/rubber/rubber-mysql_cluster.yml +32 -0
  99. data/generators/vulcanize/templates/mysql_cluster/templates.yml +1 -0
  100. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/database.yml +16 -0
  101. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/monit-mysql_proxy.cnf +10 -0
  102. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/mysql-proxy +153 -0
  103. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/mysql-proxy.conf +10 -0
  104. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/mysql-proxy.lua +5 -0
  105. data/generators/vulcanize/templates/mysql_proxy/config/rubber/deploy-mysql_proxy.rb +52 -0
  106. data/generators/vulcanize/templates/mysql_proxy/config/rubber/rubber-mysql_proxy.yml +11 -0
  107. data/generators/vulcanize/templates/mysql_proxy/templates.yml +1 -0
  108. data/generators/vulcanize/templates/nginx/config/rubber/deploy-nginx.rb +45 -0
  109. data/generators/vulcanize/templates/nginx/config/rubber/role/nginx/crontab +9 -0
  110. data/generators/vulcanize/templates/nginx/config/rubber/role/nginx/monit-nginx.conf +8 -0
  111. data/generators/vulcanize/templates/nginx/config/rubber/role/nginx/nginx.conf +42 -0
  112. data/generators/vulcanize/templates/nginx/config/rubber/role/web_tools/nginx-tools.conf +55 -0
  113. data/generators/vulcanize/templates/nginx/config/rubber/role/web_tools/tools-index.html +30 -0
  114. data/generators/vulcanize/templates/nginx/config/rubber/role/web_tools/tools-nginx.auth +7 -0
  115. data/generators/vulcanize/templates/nginx/config/rubber/rubber-nginx.yml +10 -0
  116. data/generators/vulcanize/templates/nginx/templates.yml +1 -0
  117. data/generators/vulcanize/templates/passenger/config/rubber/deploy-passenger.rb +37 -0
  118. data/generators/vulcanize/templates/passenger/config/rubber/role/passenger/munin-passenger-sudoers.conf +6 -0
  119. data/generators/vulcanize/templates/passenger/config/rubber/role/passenger/munin-passenger.conf +47 -0
  120. data/generators/vulcanize/templates/passenger/config/rubber/role/passenger/passenger-apache-vhost.conf +46 -0
  121. data/generators/vulcanize/templates/passenger/config/rubber/role/passenger/passenger.conf +10 -0
  122. data/generators/vulcanize/templates/passenger/config/rubber/rubber-passenger.yml +12 -0
  123. data/generators/vulcanize/templates/passenger/templates.yml +1 -0
  124. data/generators/vulcanize/templates/sphinx/config/rubber/common/sphinx.yml +46 -0
  125. data/generators/vulcanize/templates/sphinx/config/rubber/deploy-sphinx.rb +112 -0
  126. data/generators/vulcanize/templates/sphinx/config/rubber/role/sphinx/crontab +11 -0
  127. data/generators/vulcanize/templates/sphinx/config/rubber/role/sphinx/monit-sphinx.conf +10 -0
  128. data/generators/vulcanize/templates/sphinx/config/rubber/rubber-sphinx.yml +6 -0
  129. data/generators/vulcanize/templates/sphinx/templates.yml +1 -0
  130. data/generators/vulcanize/vulcanize_generator.rb +67 -0
  131. data/lib/capistrano/hostcmd.rb +12 -0
  132. data/lib/rubber.rb +38 -0
  133. data/lib/rubber/capistrano.rb +1 -0
  134. data/lib/rubber/cloud.rb +13 -0
  135. data/lib/rubber/cloud/aws.rb +305 -0
  136. data/lib/rubber/cloud/base.rb +16 -0
  137. data/lib/rubber/configuration.rb +47 -0
  138. data/lib/rubber/dns.rb +13 -0
  139. data/lib/rubber/dns/base.rb +69 -0
  140. data/lib/rubber/dns/dyndns.rb +63 -0
  141. data/lib/rubber/dns/nettica.rb +73 -0
  142. data/lib/rubber/dns/zerigo.rb +131 -0
  143. data/lib/rubber/environment.rb +161 -0
  144. data/lib/rubber/generator.rb +197 -0
  145. data/lib/rubber/instance.rb +165 -0
  146. data/lib/rubber/recipes/rubber.rb +89 -0
  147. data/lib/rubber/recipes/rubber/bundles.rb +28 -0
  148. data/lib/rubber/recipes/rubber/deploy.rb +90 -0
  149. data/lib/rubber/recipes/rubber/instances.rb +348 -0
  150. data/lib/rubber/recipes/rubber/load_balancers.rb +44 -0
  151. data/lib/rubber/recipes/rubber/security_groups.rb +189 -0
  152. data/lib/rubber/recipes/rubber/setup.rb +357 -0
  153. data/lib/rubber/recipes/rubber/static_ips.rb +107 -0
  154. data/lib/rubber/recipes/rubber/utils.rb +203 -0
  155. data/lib/rubber/recipes/rubber/volumes.rb +264 -0
  156. data/lib/rubber/tasks/rubber.rb +221 -0
  157. data/lib/rubber/util.rb +37 -0
  158. data/test/environment_test.rb +118 -0
  159. data/test/generator_test.rb +323 -0
  160. data/test/instance_test.rb +93 -0
  161. data/test/test_helper.rb +4 -0
  162. data/test/util_test.rb +16 -0
  163. metadata +274 -0
@@ -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,348 @@
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
+ r = get_env('ROLES', "Instance roles (e.g. web,app,db:primary=true)", true)
9
+ if r == '*'
10
+ instance_roles = rubber_cfg.environment.known_roles
11
+ instance_roles = instance_roles.collect {|role| role == "db" ? "db:primary=true" : role }
12
+ else
13
+ instance_roles = r.split(",")
14
+ end
15
+
16
+ ir = []
17
+ instance_roles.each do |r|
18
+ role = Rubber::Configuration::RoleItem.parse(r)
19
+
20
+ # If user doesn't setup a primary db, then be nice and do it
21
+ if role.name == "db" && role.options["primary"] == nil && rubber_instances.for_role("db").size == 0
22
+ value = Capistrano::CLI.ui.ask("You do not have a primary db role, should #{instance_alias} be it [y/n]?: ")
23
+ role.options["primary"] = true if value =~ /^y/
24
+ end
25
+
26
+ ir << role
27
+ end
28
+
29
+ # Add in roles that the given set of roles depends on
30
+ ir = Rubber::Configuration::RoleItem.expand_role_dependencies(ir, get_role_dependencies)
31
+
32
+ create_instance(instance_alias, ir)
33
+ end
34
+
35
+ desc <<-DESC
36
+ Refresh the host data for a EC2 instance with the given ALIAS.
37
+ This is useful to run when rubber:create fails after instance creation
38
+ DESC
39
+ task :refresh do
40
+ instance_alias = get_env('ALIAS', "Instance alias (e.g. web01)", true)
41
+ ENV.delete('ROLES') # so we don't get an error if people leave ROLES in env from :create CLI
42
+ refresh_instance(instance_alias)
43
+ end
44
+
45
+ desc <<-DESC
46
+ Destroy the EC2 instance for the given ALIAS
47
+ DESC
48
+ task :destroy do
49
+ instance_alias = get_env('ALIAS', "Instance alias (e.g. web01)", true)
50
+ ENV.delete('ROLES') # so we don't get an error if people leave ROLES in env from :create CLI
51
+ destroy_instance(instance_alias)
52
+ end
53
+
54
+ desc <<-DESC
55
+ Destroy ALL the EC2 instances for the current env
56
+ DESC
57
+ task :destroy_all do
58
+ rubber_instances.each do |ic|
59
+ destroy_instance(ic.name)
60
+ end
61
+ end
62
+
63
+ desc <<-DESC
64
+ Adds the given ROLES to the instance named ALIAS
65
+ DESC
66
+ required_task :add_role do
67
+ instance_alias = get_env('ALIAS', "Instance alias (e.g. web01)", true)
68
+ r = get_env('ROLES', "Instance roles (e.g. web,app,db:primary=true)", true)
69
+
70
+ instance_roles = r.split(",")
71
+
72
+ ir = []
73
+ instance_roles.each do |r|
74
+ role = Rubber::Configuration::RoleItem.parse(r)
75
+ ir << role
76
+ end
77
+
78
+ # Add in roles that the given set of roles depends on
79
+ ir = Rubber::Configuration::RoleItem.expand_role_dependencies(ir, get_role_dependencies)
80
+
81
+ instance = rubber_instances[instance_alias]
82
+ fatal "Instance does not exist: #{instance_alias}" unless instance
83
+
84
+ instance.roles = (instance.roles + ir).uniq
85
+ rubber_instances.save()
86
+ end
87
+
88
+ desc <<-DESC
89
+ Removes the given ROLES from the instance named ALIAS
90
+ DESC
91
+ required_task :remove_role do
92
+ instance_alias = get_env('ALIAS', "Instance alias (e.g. web01)", true)
93
+ r = get_env('ROLES', "Instance roles (e.g. web,app,db:primary=true)", true)
94
+
95
+ instance_roles = r.split(",")
96
+
97
+ ir = []
98
+ instance_roles.each do |r|
99
+ role = Rubber::Configuration::RoleItem.parse(r)
100
+ ir << role
101
+ end
102
+
103
+ instance = rubber_instances[instance_alias]
104
+ fatal "Instance does not exist: #{instance_alias}" unless instance
105
+
106
+ instance.roles = (instance.roles - ir).uniq
107
+ rubber_instances.save()
108
+ end
109
+
110
+ desc <<-DESC
111
+ List all your EC2 instances
112
+ DESC
113
+ required_task :describe do
114
+ results = []
115
+ format = "%-10s %-10s %-10s %-15s %-30s"
116
+ results << format % %w[InstanceID State Zone IP Alias\ (*=unknown)]
117
+
118
+ instances = cloud.describe_instances()
119
+ instances.each do |instance|
120
+ local_alias = find_alias(instance[:external_ip], instance[:id], instance[:state] == 'running')
121
+ results << format % [instance[:id], instance[:state], instance[:zone], instance[:external_ip] || "NoIP", local_alias || "Unknown"]
122
+ end
123
+ results.each {|r| logger.info r}
124
+ end
125
+
126
+ desc <<-DESC
127
+ Describes the availability zones
128
+ DESC
129
+ required_task :describe_zones do
130
+ results = []
131
+ format = "%-20s %-15s"
132
+ results << format % %w[Name State]
133
+
134
+ zones = cloud.describe_availability_zones()
135
+ zones.each do |zone|
136
+ results << format % [zone[:name], zone[:state]]
137
+ end
138
+
139
+ results.each {|r| logger.info r}
140
+ end
141
+
142
+
143
+ set :print_ip_command, "ifconfig eth0 | awk 'NR==2 {print $2}' | awk -F: '{print $2}'"
144
+
145
+ # Creates a new ec2 instance with the given alias and roles
146
+ # Configures aliases (/etc/hosts) on local and remote machines
147
+ def create_instance(instance_alias, instance_roles)
148
+ fatal "Instance already exists: #{instance_alias}" if rubber_instances[instance_alias]
149
+
150
+ role_names = instance_roles.collect{|x| x.name}
151
+ env = rubber_cfg.environment.bind(role_names, instance_alias)
152
+
153
+ # We need to use security_groups during create, so create them up front
154
+ setup_security_groups(instance_alias, role_names)
155
+ security_groups = get_assigned_security_groups(instance_alias, role_names)
156
+
157
+ ami = env.cloud_providers[env.cloud_provider].image_id
158
+ ami_type = env.cloud_providers[env.cloud_provider].image_type
159
+ availability_zone = env.availability_zone
160
+ logger.info "Creating instance #{ami}/#{ami_type}/#{security_groups.join(',') rescue 'Default'}/#{availability_zone || 'Default'}"
161
+ instance_id = cloud.create_instance(ami, ami_type, security_groups, availability_zone)
162
+
163
+ logger.info "Instance #{instance_id} created"
164
+
165
+ instance_item = Rubber::Configuration::InstanceItem.new(instance_alias, env.domain, instance_roles, instance_id, security_groups)
166
+ rubber_instances.add(instance_item)
167
+ rubber_instances.save()
168
+
169
+
170
+ print "Waiting for instance to start"
171
+ while true do
172
+ print "."
173
+ sleep 2
174
+ instance = cloud.describe_instances(instance_id).first
175
+
176
+ if instance[:state] == "running"
177
+ print "\n"
178
+ logger.info "Instance running, fetching hostname/ip data"
179
+ instance_item.external_host = instance[:external_host]
180
+ instance_item.external_ip = instance[:external_ip]
181
+ instance_item.internal_host = instance[:internal_host]
182
+ instance_item.zone = instance[:zone]
183
+ rubber_instances.save()
184
+
185
+ # setup amazon elastic ips if configured to do so
186
+ setup_static_ips
187
+
188
+ # Need to setup aliases so ssh doesn't give us errors when we
189
+ # later try? to connect to same ip but using alias
190
+ setup_local_aliases
191
+
192
+ # re-load the roles since we may have just defined new ones
193
+ load_roles() unless env.disable_auto_roles
194
+
195
+ # Connect to newly created instance and grab its internal ip
196
+ # so that we can update all aliases
197
+
198
+ task :_get_ip, :hosts => instance_item.external_ip do
199
+ instance_item.internal_ip = capture(print_ip_command).strip
200
+ rubber_instances.save()
201
+ end
202
+
203
+ # even though instance is running, sometimes ssh hasn't started yet,
204
+ # so retry on connect failure
205
+ begin
206
+ _get_ip
207
+ rescue ConnectionError
208
+ sleep 2
209
+ logger.info "Failed to connect to #{instance_alias} (#{instance_item.external_ip}), retrying"
210
+ retry
211
+ end
212
+
213
+ # Add the aliases for this instance to all other hosts
214
+ setup_remote_aliases
215
+ setup_dns_aliases
216
+
217
+ break
218
+ end
219
+ end
220
+ end
221
+
222
+ # Refreshes a ec2 instance with the given alias
223
+ # Configures aliases (/etc/hosts) on local and remote machines
224
+ def refresh_instance(instance_alias)
225
+ instance_item = rubber_instances[instance_alias]
226
+
227
+ fatal "Instance does not exist: #{instance_alias}" if ! instance_item
228
+
229
+ env = rubber_cfg.environment.bind(instance_item.role_names, instance_alias)
230
+
231
+ instance = cloud.describe_instances(instance_item.instance_id).first
232
+
233
+ if instance[:state] == "running"
234
+ logger.info "\nInstance running, fetching hostname/ip data"
235
+ instance_item.external_host = instance[:external_host]
236
+ instance_item.external_ip = instance[:external_ip]
237
+ instance_item.internal_host = instance[:internal_host]
238
+ instance_item.zone = instance[:zone]
239
+
240
+ # setup amazon elastic ips if configured to do so
241
+ setup_static_ips
242
+
243
+ # Need to setup aliases so ssh doesn't give us errors when we
244
+ # later try to connect to same ip but using alias
245
+ setup_local_aliases
246
+
247
+ # re-load the roles since we may have just defined new ones
248
+ load_roles() unless env.disable_auto_roles
249
+
250
+ # Connect to newly created instance and grab its internal ip
251
+ # so that we can update all aliases
252
+ task :_get_ip, :hosts => instance_item.external_ip do
253
+ instance_item.internal_ip = capture(print_ip_command).strip
254
+ rubber_instances.save()
255
+ end
256
+
257
+ # even though instance is running, sometimes ssh hasn't started yet,
258
+ # so retry on connect failure
259
+ begin
260
+ _get_ip
261
+ rescue ConnectionError
262
+ sleep 2
263
+ logger.info "Failed to connect to #{instance_alias} (#{instance_item.external_ip}), retrying"
264
+ retry
265
+ end
266
+
267
+
268
+ # Add the aliases for this instance to all other hosts
269
+ setup_remote_aliases
270
+ setup_dns_aliases
271
+ end
272
+ end
273
+
274
+
275
+ # Destroys the given ec2 instance
276
+ def destroy_instance(instance_alias)
277
+ instance_item = rubber_instances[instance_alias]
278
+ fatal "Instance does not exist: #{instance_alias}" if ! instance_item
279
+
280
+ env = rubber_cfg.environment.bind(instance_item.role_names, instance_item.name)
281
+
282
+ value = Capistrano::CLI.ui.ask("About to DESTROY #{instance_alias} (#{instance_item.instance_id}) in mode #{RUBBER_ENV}. Are you SURE [yes/NO]?: ")
283
+ fatal("Exiting", 0) if value != "yes"
284
+
285
+ if instance_item.static_ip
286
+ value = Capistrano::CLI.ui.ask("Instance has a static ip, do you want to release it? [y/N]?: ")
287
+ destroy_static_ip(instance_item.static_ip) if value =~ /^y/
288
+ end
289
+
290
+ if instance_item.volumes
291
+ value = Capistrano::CLI.ui.ask("Instance has persistent volumes, do you want to destroy them? [y/N]?: ")
292
+ if value =~ /^y/
293
+ instance_item.volumes.clone.each do |volume_id|
294
+ destroy_volume(volume_id)
295
+ end
296
+ end
297
+ end
298
+
299
+ logger.info "Destroying instance alias=#{instance_alias}, instance_id=#{instance_item.instance_id}"
300
+
301
+ cloud.destroy_instance(instance_item.instance_id)
302
+
303
+ rubber_instances.remove(instance_alias)
304
+ rubber_instances.save()
305
+
306
+ # re-load the roles since we just removed some and setup_remote_aliases
307
+ # shouldn't hit removed ones
308
+ load_roles() unless env.disable_auto_roles
309
+
310
+ setup_aliases
311
+ destroy_dyndns(instance_item)
312
+ cleanup_known_hosts(instance_item) unless env.disable_known_hosts_cleanup
313
+ end
314
+
315
+
316
+ # delete from ~/.ssh/known_hosts all lines that begin with ec2- or instance_alias
317
+ def cleanup_known_hosts(instance_item)
318
+ logger.info "Cleaning ~/.ssh/known_hosts"
319
+ File.open(File.expand_path('~/.ssh/known_hosts'), 'r+') do |f|
320
+ out = ""
321
+ f.each do |line|
322
+ line = case line
323
+ when /^ec2-/; ''
324
+ when /#{instance_item.full_name}/; ''
325
+ when /#{instance_item.external_host}/; ''
326
+ when /#{instance_item.external_ip}/; ''
327
+ else line;
328
+ end
329
+ out << line
330
+ end
331
+ f.pos = 0
332
+ f.print out
333
+ f.truncate(f.pos)
334
+ end
335
+ end
336
+
337
+ def get_role_dependencies
338
+ # convert string format of role_dependencies from rubber.yml into
339
+ # objects for use by expand_role_dependencies
340
+ deps = {}
341
+ rubber_env.role_dependencies.each do |k, v|
342
+ rhs = Array(v).collect {|r| Rubber::Configuration::RoleItem.parse(r)}
343
+ deps[Rubber::Configuration::RoleItem.parse(k)] = rhs
344
+ end if rubber_env.role_dependencies
345
+ return deps
346
+ end
347
+
348
+ end