sml-rubber 0.9.1

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 (147) hide show
  1. data/COPYING +339 -0
  2. data/README +6 -0
  3. data/TODO +9 -0
  4. data/VERSION +1 -0
  5. data/generators/vulcanize/USAGE +6 -0
  6. data/generators/vulcanize/templates/apache/config/rubber/deploy-apache.rb +45 -0
  7. data/generators/vulcanize/templates/apache/config/rubber/role/web/deflate.conf +10 -0
  8. data/generators/vulcanize/templates/apache/config/rubber/role/web/expires.conf +9 -0
  9. data/generators/vulcanize/templates/apache/config/rubber/role/web/headers.conf +6 -0
  10. data/generators/vulcanize/templates/apache/config/rubber/role/web/setenvif.conf +52 -0
  11. data/generators/vulcanize/templates/apache/config/rubber/role/web/vhost.conf +27 -0
  12. data/generators/vulcanize/templates/apache/config/rubber/rubber-apache.yml +15 -0
  13. data/generators/vulcanize/templates/apache/templates.yml +1 -0
  14. data/generators/vulcanize/templates/base/Capfile +17 -0
  15. data/generators/vulcanize/templates/base/config/deploy.rb +77 -0
  16. data/generators/vulcanize/templates/base/config/rubber/common/crontab +16 -0
  17. data/generators/vulcanize/templates/base/config/rubber/common/profile.rc +9 -0
  18. data/generators/vulcanize/templates/base/config/rubber/deploy-setup.rb +56 -0
  19. data/generators/vulcanize/templates/base/config/rubber/rubber.yml +221 -0
  20. data/generators/vulcanize/templates/base/lib/tasks/rubber.rake +18 -0
  21. data/generators/vulcanize/templates/base/script/cron-rake +18 -0
  22. data/generators/vulcanize/templates/base/script/cron-runner +18 -0
  23. data/generators/vulcanize/templates/base/script/cron-sh +67 -0
  24. data/generators/vulcanize/templates/base/templates.yml +1 -0
  25. data/generators/vulcanize/templates/complete_mysql/templates.yml +6 -0
  26. data/generators/vulcanize/templates/complete_passenger_mysql/templates.yml +8 -0
  27. data/generators/vulcanize/templates/cruise/config/rubber/deploy-cruise.rb +74 -0
  28. data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/cruise +40 -0
  29. data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/my.cnf +165 -0
  30. data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/production.rb +8 -0
  31. data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/site_config.rb +76 -0
  32. data/generators/vulcanize/templates/cruise/config/rubber/role/web_tools/cruise-nginx.conf +11 -0
  33. data/generators/vulcanize/templates/cruise/config/rubber/rubber-cruise.yml +18 -0
  34. data/generators/vulcanize/templates/cruise/templates.yml +1 -0
  35. data/generators/vulcanize/templates/haproxy/config/rubber/deploy-haproxy.rb +45 -0
  36. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/haproxy-default.conf +8 -0
  37. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/haproxy.conf +44 -0
  38. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/monit-haproxy.conf +9 -0
  39. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/syslog-haproxy.conf +6 -0
  40. data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/syslogd-default.conf +17 -0
  41. data/generators/vulcanize/templates/haproxy/config/rubber/role/web_tools/haproxy-nginx.conf +10 -0
  42. data/generators/vulcanize/templates/haproxy/config/rubber/rubber-haproxy.yml +12 -0
  43. data/generators/vulcanize/templates/haproxy/templates.yml +1 -0
  44. data/generators/vulcanize/templates/memcached/config/memcached.yml +28 -0
  45. data/generators/vulcanize/templates/memcached/config/rubber/common/memcached.yml +14 -0
  46. data/generators/vulcanize/templates/memcached/config/rubber/role/memcached/memcached.conf +52 -0
  47. data/generators/vulcanize/templates/memcached/config/rubber/role/memcached/memcached_munin_plugin +249 -0
  48. data/generators/vulcanize/templates/memcached/config/rubber/rubber-memcached.yml +7 -0
  49. data/generators/vulcanize/templates/memcached/templates.yml +1 -0
  50. data/generators/vulcanize/templates/minimal_mysql/templates.yml +7 -0
  51. data/generators/vulcanize/templates/minimal_nodb/templates.yml +6 -0
  52. data/generators/vulcanize/templates/mongrel/config/rubber/deploy-mongrel.rb +75 -0
  53. data/generators/vulcanize/templates/mongrel/config/rubber/role/app/mongrel_cluster.yml +12 -0
  54. data/generators/vulcanize/templates/mongrel/config/rubber/role/app/monit-mongrel.conf +20 -0
  55. data/generators/vulcanize/templates/mongrel/config/rubber/rubber-mongrel.yml +9 -0
  56. data/generators/vulcanize/templates/mongrel/templates.yml +1 -0
  57. data/generators/vulcanize/templates/monit/config/rubber/common/monit-default.conf +15 -0
  58. data/generators/vulcanize/templates/monit/config/rubber/common/monit.conf +251 -0
  59. data/generators/vulcanize/templates/monit/config/rubber/deploy-monit.rb +32 -0
  60. data/generators/vulcanize/templates/monit/config/rubber/role/web_tools/monit-admin-nginx.conf +10 -0
  61. data/generators/vulcanize/templates/monit/config/rubber/rubber-monit.yml +6 -0
  62. data/generators/vulcanize/templates/monit/templates.yml +1 -0
  63. data/generators/vulcanize/templates/munin/config/rubber/common/monit-munin.conf +8 -0
  64. data/generators/vulcanize/templates/munin/config/rubber/common/munin-node.conf +48 -0
  65. data/generators/vulcanize/templates/munin/config/rubber/deploy-munin.rb +30 -0
  66. data/generators/vulcanize/templates/munin/config/rubber/role/web_tools/munin-nginx.conf +8 -0
  67. data/generators/vulcanize/templates/munin/config/rubber/role/web_tools/munin-plugins.conf +31 -0
  68. data/generators/vulcanize/templates/munin/config/rubber/role/web_tools/munin.conf +80 -0
  69. data/generators/vulcanize/templates/munin/config/rubber/rubber-munin.yml +8 -0
  70. data/generators/vulcanize/templates/munin/script/munin/example_mysql_query.rb +57 -0
  71. data/generators/vulcanize/templates/munin/script/munin/example_simple.rb +24 -0
  72. data/generators/vulcanize/templates/munin/templates.yml +1 -0
  73. data/generators/vulcanize/templates/mysql/config/rubber/common/database.yml +11 -0
  74. data/generators/vulcanize/templates/mysql/config/rubber/deploy-mysql.rb +178 -0
  75. data/generators/vulcanize/templates/mysql/config/rubber/role/db/crontab +14 -0
  76. data/generators/vulcanize/templates/mysql/config/rubber/role/db/monit-mysql.cnf +10 -0
  77. data/generators/vulcanize/templates/mysql/config/rubber/role/db/my.cnf +167 -0
  78. data/generators/vulcanize/templates/mysql/config/rubber/role/mysql_slave/mysql_slave_munin_plugin +51 -0
  79. data/generators/vulcanize/templates/mysql/config/rubber/rubber-mysql.yml +38 -0
  80. data/generators/vulcanize/templates/mysql/templates.yml +1 -0
  81. data/generators/vulcanize/templates/mysql_cluster/config/rubber/common/mysql_cluster_migrations.rb +13 -0
  82. data/generators/vulcanize/templates/mysql_cluster/config/rubber/deploy-mysql_cluster.rb +173 -0
  83. data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_data/my.cnf +15 -0
  84. data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_mgm/ndb_mgmd.cnf +39 -0
  85. data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_sql/monit-mysql_cluster_sql.cnf +10 -0
  86. data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_sql/my.cnf +23 -0
  87. data/generators/vulcanize/templates/mysql_cluster/config/rubber/rubber-mysql_cluster.yml +32 -0
  88. data/generators/vulcanize/templates/mysql_cluster/templates.yml +1 -0
  89. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/database.yml +16 -0
  90. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/monit-mysql_proxy.cnf +10 -0
  91. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/mysql-proxy +153 -0
  92. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/mysql-proxy.conf +10 -0
  93. data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/mysql-proxy.lua +5 -0
  94. data/generators/vulcanize/templates/mysql_proxy/config/rubber/deploy-mysql_proxy.rb +52 -0
  95. data/generators/vulcanize/templates/mysql_proxy/config/rubber/rubber-mysql_proxy.yml +11 -0
  96. data/generators/vulcanize/templates/mysql_proxy/templates.yml +1 -0
  97. data/generators/vulcanize/templates/nginx/config/rubber/deploy-nginx.rb +45 -0
  98. data/generators/vulcanize/templates/nginx/config/rubber/role/web/crontab +9 -0
  99. data/generators/vulcanize/templates/nginx/config/rubber/role/web/monit-nginx.conf +9 -0
  100. data/generators/vulcanize/templates/nginx/config/rubber/role/web/nginx.conf +133 -0
  101. data/generators/vulcanize/templates/nginx/config/rubber/role/web_tools/index.html +23 -0
  102. data/generators/vulcanize/templates/nginx/config/rubber/role/web_tools/nginx-tools.conf +74 -0
  103. data/generators/vulcanize/templates/nginx/config/rubber/rubber-nginx.yml +33 -0
  104. data/generators/vulcanize/templates/nginx/templates.yml +1 -0
  105. data/generators/vulcanize/templates/passenger/config/rubber/deploy-passenger.rb +27 -0
  106. data/generators/vulcanize/templates/passenger/config/rubber/role/web/passenger.conf +8 -0
  107. data/generators/vulcanize/templates/passenger/config/rubber/rubber-passenger.yml +4 -0
  108. data/generators/vulcanize/templates/passenger/templates.yml +1 -0
  109. data/generators/vulcanize/templates/sphinx/config/rubber/common/sphinx.yml +46 -0
  110. data/generators/vulcanize/templates/sphinx/config/rubber/deploy-sphinx.rb +112 -0
  111. data/generators/vulcanize/templates/sphinx/config/rubber/role/sphinx/crontab +11 -0
  112. data/generators/vulcanize/templates/sphinx/config/rubber/role/sphinx/monit-sphinx.conf +10 -0
  113. data/generators/vulcanize/templates/sphinx/config/rubber/rubber-sphinx.yml +6 -0
  114. data/generators/vulcanize/templates/sphinx/templates.yml +1 -0
  115. data/generators/vulcanize/vulcanize_generator.rb +67 -0
  116. data/lib/capistrano/hostcmd.rb +12 -0
  117. data/lib/rubber.rb +37 -0
  118. data/lib/rubber/capistrano.rb +1 -0
  119. data/lib/rubber/cloud.rb +13 -0
  120. data/lib/rubber/cloud/aws.rb +261 -0
  121. data/lib/rubber/cloud/base.rb +16 -0
  122. data/lib/rubber/configuration.rb +47 -0
  123. data/lib/rubber/dns.rb +13 -0
  124. data/lib/rubber/dns/base.rb +69 -0
  125. data/lib/rubber/dns/dyndns.rb +63 -0
  126. data/lib/rubber/dns/nettica.rb +56 -0
  127. data/lib/rubber/dns/zerigo.rb +121 -0
  128. data/lib/rubber/environment.rb +161 -0
  129. data/lib/rubber/generator.rb +197 -0
  130. data/lib/rubber/instance.rb +113 -0
  131. data/lib/rubber/recipes/rubber.rb +88 -0
  132. data/lib/rubber/recipes/rubber/bundles.rb +28 -0
  133. data/lib/rubber/recipes/rubber/deploy.rb +66 -0
  134. data/lib/rubber/recipes/rubber/instances.rb +298 -0
  135. data/lib/rubber/recipes/rubber/security_groups.rb +149 -0
  136. data/lib/rubber/recipes/rubber/setup.rb +285 -0
  137. data/lib/rubber/recipes/rubber/static_ips.rb +107 -0
  138. data/lib/rubber/recipes/rubber/utils.rb +195 -0
  139. data/lib/rubber/recipes/rubber/volumes.rb +263 -0
  140. data/lib/rubber/tasks/rubber.rb +218 -0
  141. data/lib/rubber/util.rb +33 -0
  142. data/test/environment_test.rb +118 -0
  143. data/test/generator_test.rb +323 -0
  144. data/test/instance_test.rb +38 -0
  145. data/test/test_helper.rb +4 -0
  146. data/test/util_test.rb +16 -0
  147. metadata +246 -0
@@ -0,0 +1,197 @@
1
+ require 'erb'
2
+ require 'find'
3
+ require 'fileutils'
4
+
5
+ module Rubber
6
+ module Configuration
7
+
8
+ # Handles selection and transformation of a set of config files
9
+ # based on the host/role they belong to
10
+ class Generator
11
+ attr_accessor :file_pattern
12
+ attr_accessor :no_post
13
+ attr_accessor :force
14
+ attr_accessor :fake_root
15
+ attr_accessor :stop_on_error_cmd
16
+
17
+ def initialize(config_dir, roles, host, options={})
18
+ @config_dir = config_dir
19
+ @roles = roles.to_a.reverse #First roles take precedence
20
+ @host = host || 'no_host'
21
+ @options=options
22
+ end
23
+
24
+ def run
25
+ config_dirs = []
26
+ config_dirs << "#{@config_dir}/common/**/**"
27
+ @roles.sort.each {|role| config_dirs << "#{@config_dir}/role/#{role}/**/**" }
28
+ config_dirs << "#{@config_dir}/host/#{@host}/**/**"
29
+
30
+ pat = Regexp.new(file_pattern) if file_pattern
31
+
32
+ config_dirs.each do |dir|
33
+ Dir[dir].sort.each do |f|
34
+ next if f =~ /\/(CVS|\.svn)\//
35
+ if File.file?(f) && (! pat || pat.match(f))
36
+ LOGGER.info{"Transforming #{f}"}
37
+ begin
38
+ transform(IO.read(f), @options)
39
+ rescue Exception => e
40
+ lines = e.backtrace.grep(/^\(erb\):([0-9]+)/) {|b| Regexp.last_match(1) }
41
+ LOGGER.error{"Transformation failed for #{f}#{':' + lines.first if lines.first}"}
42
+ LOGGER.error e.message
43
+ exit 1
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ # Transforms the ERB template given in srcfile and writes the result to
51
+ # dest_file (if not nil) before returning it
52
+ def transform(src_data, options={})
53
+ config = ConfigDescriptor.new
54
+
55
+ # for development/test, if we have a fake root, echo any
56
+ # calls to system
57
+ if fake_root
58
+ class << config
59
+ def system(*args)
60
+ puts ("Not running system command during a fake_root transformation: #{args.inspect}")
61
+ end
62
+ def open(*args)
63
+ if args.first && args.first =~ /^|/
64
+ puts ("Not running open/pipe command during a fake_root transformation: #{args.inspect}")
65
+ else
66
+ super
67
+ end
68
+ end
69
+ alias ` system
70
+ alias exec system
71
+ alias fork system
72
+ end
73
+ end
74
+
75
+ config.options = options
76
+ template = ERB.new(src_data, nil, "-")
77
+ result = template.result(config.get_binding())
78
+
79
+ return if config.skip
80
+
81
+ config_path = config.path
82
+
83
+ # for development/test, if we have a fake root, then send config
84
+ # output there, and also put write_cmd output there
85
+ if fake_root
86
+ config_path = "write_cmd_" + config.write_cmd.gsub(/[^a-z0-9_-]/i, '') if config.write_cmd
87
+ config_path = "#{fake_root}/#{config_path}" if config_path
88
+ end
89
+
90
+ if ! config_path && ! (config.read_cmd && config.write_cmd)
91
+ raise "Transformation requires either a output filename or command"
92
+ end
93
+
94
+ reader = config_path || "|#{config.read_cmd}"
95
+ orig = IO.read(reader) rescue ""
96
+
97
+ # When additive is set we need to only replace between our delimiters
98
+ if config.additive
99
+ additive = ["# start rubber #{@host}", "# end rubber #{@host}"] unless additive.is_a? Array
100
+ pat = /#{config.additive[0]}.*#{config.additive[1]}/m
101
+ new = "#{config.additive[0]}#{result}#{config.additive[1]}"
102
+ if orig =~ pat
103
+ result = orig.gsub(pat, new)
104
+ else
105
+ result = orig + new + "\n"
106
+ end
107
+ end
108
+
109
+ # Only do something if the transformed result is different than what
110
+ # is currently in the destination file
111
+ if orig != result || force
112
+ # create dirs as needed
113
+ FileUtils.mkdir_p(File.dirname(config_path)) if config_path
114
+
115
+ # Write a backup of original
116
+ open("#{config_path}.bak", 'w') { |f| f.write(orig) } if config_path
117
+
118
+ # Write out transformed file
119
+ writer = config_path || "|#{config.write_cmd}"
120
+ open(writer, 'w') do |pipe|
121
+ pipe.write(result)
122
+ end
123
+ if config.write_cmd && ! fake_root && $?.exitstatus != 0
124
+ raise "Config command failed execution: #{config.write_cmd}"
125
+ end
126
+
127
+ # Set file permissions and owner if needed
128
+ FileUtils.chmod(config.perms, config_path) if config.perms && config_path
129
+ FileUtils.chown(config.owner, config.group, config_path) if config_path && (config.owner || config.group)
130
+
131
+ # Run post transform command if needed
132
+ if config.post
133
+ if orig == result
134
+ LOGGER.info("Nothing to do, not running post command")
135
+ elsif no_post
136
+ LOGGER.info("Not running post command as no post specified")
137
+ elsif fake_root
138
+ LOGGER.info("Not running post command as a fake root was given: #{config.post}")
139
+ else
140
+ # this lets us abort a script if a command in the middle of it errors out
141
+ # stop_on_error_cmd = "function error_exit { exit 99; }; trap error_exit ERR"
142
+ config.post = "#{stop_on_error_cmd}\n#{config.post}" if stop_on_error_cmd
143
+
144
+ LOGGER.info{"Transformation executing post config command: #{config.post}"}
145
+ LOGGER.info `#{config.post}`
146
+ if $?.exitstatus != 0
147
+ raise "Post command failed execution: #{config.post}"
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ end
155
+
156
+ # Instances of this object are used accept settings from with
157
+ # a config file for when it is transformed by Generator
158
+ class ConfigDescriptor
159
+ # The output path to write the transformed config file to
160
+ attr_accessor :path
161
+ # The command to use for reading the original config file from (e.g. "crontab -l")
162
+ attr_accessor :read_cmd
163
+ # The command to use for piping the transformed config file to (e.g. "crontab -")
164
+ attr_accessor :write_cmd
165
+ # The command to run after generating the config file if it has changed
166
+ attr_accessor :post
167
+ # The owner the output file should have, e.g. "root"
168
+ attr_accessor :owner
169
+ # The group the output file should have, e.g. "system"
170
+ attr_accessor :group
171
+ # The permissions the output file should have, e.g. 0644 (octal, leading zero is significant)
172
+ attr_accessor :perms
173
+ # Sets transformation to be additive, only replaces between given delimiters, e/g/ additive = ["## start", "## end"]
174
+ attr_accessor :additive
175
+ # Lets one dynamically determine if a given file gets skipped during transformation
176
+ attr_accessor :skip
177
+ # use sudo to write the output file
178
+ # attr_accessor :sudo
179
+ # options passed in through code
180
+ attr_accessor :options
181
+
182
+ def get_binding
183
+ binding
184
+ end
185
+
186
+ def rubber_env()
187
+ Rubber::Configuration.rubber_env
188
+ end
189
+
190
+ def rubber_instances()
191
+ Rubber::Configuration.rubber_instances
192
+ end
193
+
194
+ end
195
+
196
+ end
197
+ end
@@ -0,0 +1,113 @@
1
+ require 'yaml'
2
+
3
+ module Rubber
4
+ module Configuration
5
+
6
+ # Contains the ec2 instance configuration defined in instance.yml
7
+ #
8
+ class Instance
9
+ attr_reader :file, :artifacts
10
+ include Enumerable
11
+
12
+ def initialize(file)
13
+ LOGGER.debug{"Reading rubber instances from #{file}"}
14
+ @file = file
15
+ @items = {}
16
+ @artifacts = {'volumes' => {}, 'static_ips' => {}}
17
+ if ENV['FILTER']
18
+ @filters = ENV['FILTER'].split(/\s*,\s*/)
19
+ end
20
+
21
+ if File.exist?(@file)
22
+ item_list = File.open(@file) { |f| YAML.load(f) }
23
+ if item_list
24
+ item_list.each do |i|
25
+ if i.is_a? InstanceItem
26
+ @items[i.name] = i
27
+ elsif i.is_a? Hash
28
+ @artifacts.merge!(i)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ def save()
36
+ data = []
37
+ data.push(*@items.values)
38
+ data.push(@artifacts)
39
+ File.open(@file, "w") { |f| f.write(YAML.dump(data)) }
40
+ end
41
+
42
+ def [](name)
43
+ @items[name] || @items[name.gsub(/\..*/, '')]
44
+ end
45
+
46
+ # gets the instances for the given role. If options is nil, all roles
47
+ # match, otherwise the role has to have options that match exactly
48
+ def for_role(role_name, options=nil)
49
+ @items.values.find_all {|ic| ic.roles.any? {|r| r.name == role_name && (! options || r.options == options)}}
50
+ end
51
+
52
+ def filtered()
53
+ @items.values.find_all {|ic| ! @filters || @filters.include?(ic.name)}
54
+ end
55
+
56
+ def all_roles()
57
+ @items.collect {|n, i| i.role_names}.flatten.uniq
58
+ end
59
+
60
+ def add(instance_item)
61
+ @items[instance_item.name] = instance_item
62
+ end
63
+
64
+ def remove(name)
65
+ @items.delete(name)
66
+ end
67
+
68
+ def each(&block)
69
+ @items.values.each &block
70
+ end
71
+
72
+ def size
73
+ @items.size
74
+ end
75
+ end
76
+
77
+ # The configuration for a single instance
78
+ class InstanceItem
79
+ attr_reader :name, :domain, :roles, :instance_id
80
+ attr_accessor :external_host, :external_ip
81
+ attr_accessor :internal_host, :internal_ip
82
+ attr_accessor :static_ip, :volumes, :partitions
83
+
84
+ def initialize(name, domain, roles, instance_id)
85
+ @name = name
86
+ @domain = domain
87
+ @roles = roles
88
+ @instance_id = instance_id
89
+ end
90
+
91
+ def full_name
92
+ "#@name.#@domain"
93
+ end
94
+
95
+ def role_names()
96
+ roles.collect {|r| r.name}
97
+ end
98
+ end
99
+
100
+ # The configuration for a single role contained in the list
101
+ # of roles in InstanceItem
102
+ class RoleItem
103
+ attr_reader :name, :options
104
+
105
+ def initialize(name, options={})
106
+ @name = name
107
+ @options = options
108
+ end
109
+ end
110
+
111
+ end
112
+ end
113
+
@@ -0,0 +1,88 @@
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
+ env = rubber_cfg.environment.bind()
50
+
51
+ set :cloud, Rubber::Cloud::get_provider(env.cloud_provider || "aws", env, self)
52
+
53
+ load_roles() unless rubber_cfg.environment.bind().disable_auto_roles
54
+ # NOTE: for some reason Capistrano requires you to have both the public and
55
+ # the private key in the same folder, the public key should have the
56
+ # extension ".pub".
57
+ ssh_options[:keys] = env.cloud_providers[env.cloud_provider].key_file
58
+ end
59
+
60
+
61
+ # Automatically load and define capistrano roles from instance config
62
+ def load_roles
63
+ top.roles.clear
64
+
65
+ # define empty roles for all known ones so tasks don't fail if a role
66
+ # doesn't exist due to a filter
67
+ all_roles = rubber_cfg.instance.all_roles
68
+ all_roles += rubber_cfg.environment.known_roles
69
+ all_roles.uniq!
70
+ all_roles.each {|name| top.roles[name.to_sym] = []}
71
+
72
+ # define capistrano host => role mapping for all instances
73
+ rubber_cfg.instance.filtered.each do |ic|
74
+ ic.roles.each do |role|
75
+ opts = Rubber::Util::symbolize_keys(role.options)
76
+ msg = "Auto role: #{role.name.to_sym} => #{ic.full_name}"
77
+ msg << ", #{opts.inspect}" if opts.inspect.size > 0
78
+ logger.info msg
79
+ top.role role.name.to_sym, ic.full_name, opts
80
+ end
81
+ end
82
+ end
83
+
84
+ end
85
+
86
+ Dir[File.join(File.dirname(__FILE__), 'rubber/*.rb')].each do |rubber_part|
87
+ load(rubber_part)
88
+ 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,66 @@
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
+ desc <<-DESC
28
+ Configures the deployed rails application by running the rubber configuration process
29
+ DESC
30
+ task :config do
31
+ opts = {}
32
+ opts['NO_POST'] = true if ENV['NO_POST']
33
+ opts['FILE'] = ENV['FILE'] if ENV['FILE']
34
+ opts['RUBBER_ENV'] = RUBBER_ENV
35
+
36
+ # when running deploy:migrations, we need to run config against release_path
37
+ opts[:deploy_path] = current_release if fetch(:migrate_target, :current).to_sym == :latest
38
+
39
+ run_config(opts)
40
+ end
41
+
42
+ def run_config(options={})
43
+ path = options.delete(:deploy_path) || current_path
44
+ extra_env = options.keys.inject("") {|all, k| "#{all} #{k}=\"#{options[k]}\""}
45
+
46
+ # Need to do this so we can work with staging instances without having to
47
+ # checkin instance file between create and bootstrap, as well as during a deploy
48
+ if fetch(:push_instance_config, false)
49
+ push_files = [rubber_cfg.instance.file] + rubber_cfg.environment.config_files
50
+ push_files.each do |file|
51
+ dest_file = file.sub(/^#{RUBBER_ROOT}\/?/, '')
52
+ put(File.read(file), File.join(path, dest_file))
53
+ end
54
+ end
55
+
56
+ # if the user has defined a secret config file, then push it into RUBBER_ROOT/config/rubber
57
+ secret = rubber_cfg.environment.config_secret
58
+ if secret && File.exist?(secret)
59
+ base = rubber_cfg.environment.config_root.sub(/^#{RUBBER_ROOT}\/?/, '')
60
+ put(File.read(secret), File.join(path, base, File.basename(secret)))
61
+ end
62
+
63
+ sudo "sh -c 'cd #{path} && #{extra_env} rake rubber:config'"
64
+ end
65
+
66
+ end