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,16 @@
1
+ module Rubber
2
+ module Cloud
3
+
4
+ class Base
5
+
6
+ attr_reader :env, :capistrano
7
+
8
+ def initialize(env, capistrano)
9
+ @env = env
10
+ @capistrano = capistrano
11
+ end
12
+
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,47 @@
1
+ require 'logger'
2
+ require 'rubber/environment'
3
+ require 'rubber/instance'
4
+ require 'rubber/generator'
5
+
6
+ module Rubber
7
+ module Configuration
8
+
9
+ @@configurations = {}
10
+
11
+ def self.get_configuration(env=nil, root=nil)
12
+ key = "#{env}-#{root}"
13
+ @@configurations[key] ||= ConfigHolder.new(env, root)
14
+ end
15
+
16
+ def self.rubber_env
17
+ raise "This convenience method needs RUBBER_ENV to be set" unless RUBBER_ENV
18
+ cfg = Rubber::Configuration.get_configuration(RUBBER_ENV)
19
+ host = cfg.environment.current_host
20
+ roles = cfg.instance[host].role_names rescue nil
21
+ cfg.environment.bind(roles, host)
22
+ end
23
+
24
+ def self.rubber_instances
25
+ raise "This convenience method needs RUBBER_ENV to be set" unless RUBBER_ENV
26
+ Rubber::Configuration.get_configuration(RUBBER_ENV).instance
27
+ end
28
+
29
+ class ConfigHolder
30
+ def initialize(env=nil, root=nil)
31
+ root = "#{RUBBER_ROOT}/config/rubber" unless root
32
+ instance_cfg = "#{root}/instance" + (env ? "-#{env}.yml" : ".yml")
33
+ @environment = Environment.new("#{root}")
34
+ @instance = Instance.new(instance_cfg)
35
+ end
36
+
37
+ def environment
38
+ @environment
39
+ end
40
+
41
+ def instance
42
+ @instance
43
+ end
44
+ end
45
+
46
+ end
47
+ end
data/lib/rubber/dns.rb ADDED
@@ -0,0 +1,13 @@
1
+ require "rubber/dns/base.rb"
2
+
3
+ module Rubber
4
+ module Dns
5
+
6
+ def self.get_provider(provider, env)
7
+ require "rubber/dns/#{provider}"
8
+ clazz = Rubber::Dns.const_get(provider.capitalize)
9
+ return clazz.new(env)
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,69 @@
1
+ module Rubber
2
+ module Dns
3
+
4
+ class Base
5
+
6
+ attr_reader :env
7
+
8
+ def initialize(env)
9
+ @env = env
10
+ end
11
+
12
+ def update(host, ip)
13
+ if up_to_date(host, ip)
14
+ puts "IP has not changed for #{host}, not updating dynamic DNS"
15
+ else
16
+ if ! host_exists?(host)
17
+ puts "Creating dynamic DNS: #{host} => #{ip}"
18
+ create_host_record(host, ip)
19
+ else
20
+ puts "Updating dynamic DNS: #{host} => #{ip}"
21
+ update_host_record(host, ip)
22
+ end
23
+ end
24
+ end
25
+
26
+ def destroy(host)
27
+ if host_exists?(host)
28
+ puts "Destroying dynamic DNS record: #{host}"
29
+ destroy_host_record(host)
30
+ end
31
+ end
32
+
33
+ def hostname(host)
34
+ "#{host}.#{@env.domain}"
35
+ end
36
+
37
+ def up_to_date(host, ip)
38
+ # This queries dns server directly instead of using hosts file
39
+ current_ip = nil
40
+ Resolv::DNS.open(:nameserver => [nameserver], :search => [], :ndots => 1) do |dns|
41
+ current_ip = dns.getaddress(hostname(host)).to_s rescue nil
42
+ end
43
+ return ip == current_ip
44
+ end
45
+
46
+ def nameserver()
47
+ raise "nameserver not implemented"
48
+ end
49
+
50
+ def host_exists?(host)
51
+ raise "host_exists? not implemented"
52
+ end
53
+
54
+ def create_host_record(host, ip)
55
+ raise "create_host_record not implemented"
56
+ end
57
+
58
+ def destroy_host_record(host)
59
+ raise "destroy_host_record not implemented"
60
+ end
61
+
62
+ def update_host_record(host, ip)
63
+ raise "update_host_record not implemented"
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,63 @@
1
+ module Rubber
2
+ module Dns
3
+
4
+ class Dyndns < Base
5
+
6
+ def initialize(env)
7
+ super(env)
8
+ @dyndns_env = env.dns_providers.dyndns
9
+ @user, @pass = @dyndns_env.user, @dyndns_env.password
10
+ @update_url = @dyndns_env.update_url || 'https://members.dyndns.org/nic/update?hostname=%host%&myip=%ip%'
11
+ @update_url = @update_url.gsub(/%([^%]+)%/, '#{\1}')
12
+ end
13
+
14
+ def nameserver
15
+ "ns1.mydyndns.org"
16
+ end
17
+
18
+ def host_exists?(host)
19
+ begin
20
+ Resolv::DNS.open(:nameserver => [nameserver], :search => [], :ndots => 1) do |dns|
21
+ dns.getresource(hostname(host), Resolv::DNS::Resource::IN::A)
22
+ end
23
+ rescue
24
+ raise "Domain needs to exist in dyndns as an A record before record can be updated"
25
+ end
26
+ return true
27
+ end
28
+
29
+ def create_host_record(host, ip)
30
+ puts "WARNING: No create record available for dyndns, you need to do so manually"
31
+ end
32
+
33
+ def destroy_host_record(host)
34
+ puts "WARNING: No destroy record available for dyndns, you need to do so manually"
35
+ end
36
+
37
+ def update_host_record(host, ip)
38
+ host = hostname(host)
39
+ update_url = eval('%Q{' + @update_url + '}')
40
+
41
+ # This header is required by dyndns.org
42
+ headers = {
43
+ "User-Agent" => "Capistrano - Rubber - 0.1"
44
+ }
45
+
46
+ uri = URI.parse(update_url)
47
+ http = Net::HTTP.new(uri.host, uri.port)
48
+ # switch on SSL
49
+ http.use_ssl = true if uri.scheme == "https"
50
+ # suppress verification warning
51
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
52
+ req = Net::HTTP::Get.new(update_url.gsub(/.*:\/\/[^\/]*/, ''), headers)
53
+ # authentication details
54
+ req.basic_auth @user, @pass
55
+ resp = http.request(req)
56
+ # print out the response for the update
57
+ puts "DynDNS Update result: #{resp.body}"
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,73 @@
1
+ require 'nettica/client'
2
+ module Rubber
3
+ module Dns
4
+
5
+ class Nettica < Base
6
+
7
+ def initialize(env)
8
+ super(env)
9
+ @nettica_env = @env.dns_providers.nettica
10
+ @client = ::Nettica::Client.new(@nettica_env.user, @nettica_env.password)
11
+ @ttl = (@nettica_env.ttl || 300).to_i
12
+ @record_type = @nettica_env.record_type || "A"
13
+ end
14
+
15
+ def nameserver
16
+ "dns1.nettica.com"
17
+ end
18
+
19
+ def check_status(response)
20
+ code = case
21
+ when response.respond_to?(:status)
22
+ response.status
23
+ when response.respond_to?(:result)
24
+ response.result.status
25
+ else
26
+ 500
27
+ end
28
+ if code < 200 || code > 299
29
+ msg = "Failed to access nettica api (http_status=#{code})"
30
+ msg += ", check dns_providers.nettica.user/password in rubber.yml" if code == 401
31
+ raise msg
32
+ end
33
+ return response
34
+ end
35
+
36
+ def host_exists?(host)
37
+ domain_info = check_status @client.list_domain(env.domain)
38
+ raise "Domain needs to exist in nettica before records can be updated" unless domain_info.record
39
+ return domain_info.record.any? { |r| r.hostName == host }
40
+ end
41
+
42
+ def create_host_record(host, ip)
43
+ new = @client.create_domain_record(env.domain, host, @record_type, ip, @ttl, 0)
44
+ check_status @client.add_record(new)
45
+ end
46
+
47
+ def destroy_host_record(host)
48
+ old_record = check_status(@client.list_domain(env.domain)).record.find {|r| r.hostName == host }
49
+ old = @client.create_domain_record(env.domain, host, old_record.recordType, old_record.data, old_record.tTL, old_record.priority)
50
+ check_status @client.delete_record(old)
51
+ end
52
+
53
+ def update_host_record(host, ip)
54
+ old_record = check_status(@client.list_domain(env.domain)).record.find {|r| r.hostName == host }
55
+ update_record(host, ip, old_record)
56
+ end
57
+
58
+ # update the top level domain record which has an empty hostName
59
+ def update_domain_record(ip)
60
+ old_record = check_status(@client.list_domain(env.domain)).record.find {|r| r.hostName == '' and r.recordType == 'A' and r.data =~ /\A\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\z/}
61
+ update_record('', ip, old_record)
62
+ end
63
+
64
+ def update_record(host, ip, old_record)
65
+ old = @client.create_domain_record(env.domain, host, old_record.recordType, old_record.data, old_record.tTL, old_record.priority)
66
+ new = @client.create_domain_record(env.domain, host, @record_type, ip, @ttl, 0)
67
+ check_status @client.update_record(old, new)
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,131 @@
1
+ require 'rubygems'
2
+ require 'httparty'
3
+
4
+ module Rubber
5
+ module Dns
6
+
7
+
8
+ class Zone
9
+ include HTTParty
10
+ format :xml
11
+
12
+ def initialize(customer_id, email, token, domain)
13
+ self.class.basic_auth email, token
14
+ self.class.base_uri "https://ns.zerigo.com/accounts/#{customer_id}"
15
+ @domain = domain
16
+ refresh()
17
+ end
18
+
19
+ def check_status(response)
20
+ code = response.code
21
+ if code < 200 || code > 299
22
+ msg = "Failed to access zerigo api (http_status=#{code})"
23
+ msg += ", check dns_providers.zerigo.customer_id/email/token in rubber.yml" if code == 401
24
+ raise msg
25
+ end
26
+ return response
27
+ end
28
+
29
+ def hosts
30
+ hosts = check_status self.class.get("/zones/#{@zone['id']}/hosts.xml")
31
+ return hosts['hosts']
32
+ end
33
+
34
+ def host(hostname)
35
+ hosts = check_status self.class.get("/zones/#{@zone['id']}/hosts.xml?fqdn=#{hostname}.#{@domain}")
36
+ return (hosts['hosts'] || []).first
37
+ end
38
+
39
+ def new_host
40
+ check_status(self.class.get("/zones/#{@zone['id']}/hosts/new.xml"))['host']
41
+ end
42
+
43
+ def create_host(host)
44
+ check_status self.class.post("/zones/#{@zone['id']}/hosts.xml", :body => {:host => host})
45
+ end
46
+
47
+ def update_host(host)
48
+ host_id = host['id']
49
+ check_status self.class.put("/zones/#{@zone['id']}/hosts/#{host_id}.xml", :body => {:host => host})
50
+ end
51
+
52
+ def delete_host(hostname)
53
+ host_id = host(hostname)['id']
54
+ check_status self.class.delete("/zones/#{@zone['id']}/hosts/#{host_id}.xml")
55
+ end
56
+
57
+ def refresh
58
+ zone_id = @zone['id'] rescue nil
59
+ if zone_id
60
+ @zone = check_status self.class.get("/zones/#{zone_id}.xml")
61
+ else
62
+ zones = check_status self.class.get('/zones.xml')
63
+ @zone = zones["zones"].find {|z| z["domain"] == @domain }
64
+ end
65
+ end
66
+
67
+ def data
68
+ return @zone
69
+ end
70
+
71
+ protected
72
+
73
+ def zones()
74
+ check_status self.class.get('/zones.xml')
75
+ end
76
+
77
+ def zone(domain_name)
78
+ zone = zones
79
+ return zone
80
+ end
81
+
82
+ end
83
+
84
+ class Zerigo < Base
85
+
86
+ def initialize(env)
87
+ super(env)
88
+ @zerigo_env = env.dns_providers.zerigo
89
+ @ttl = (@zerigo_env.ttl || 300).to_i
90
+ @record_type = @zerigo_env.record_type || "A"
91
+ @zone = Zone.new(@zerigo_env.customer_id, @zerigo_env.email, @zerigo_env.token, env.domain)
92
+ end
93
+
94
+ def nameserver
95
+ "a.ns.zerigo.net"
96
+ end
97
+
98
+ def host_exists?(host)
99
+ @zone.host(host)
100
+ end
101
+
102
+ def create_host_record(hostname, ip)
103
+ host = @zone.new_host()
104
+ host['host-type'] = @record_type
105
+ host['ttl'] = @ttl
106
+ host['hostname'] = hostname
107
+ host['data'] = ip
108
+ @zone.create_host(host)
109
+ end
110
+
111
+ def destroy_host_record(host)
112
+ @zone.delete_host(host)
113
+ end
114
+
115
+ def update_host_record(host, ip)
116
+ old = @zone.host(host)
117
+ old['data'] = ip
118
+ @zone.update_host(old)
119
+ end
120
+
121
+ # update the top level domain record which has an empty hostName
122
+ def update_domain_record(ip)
123
+ old = @zone.hosts.find {|h| h['hostname'].nil? }
124
+ old['data'] = ip
125
+ @zone.update_host(old)
126
+ end
127
+
128
+ end
129
+
130
+ end
131
+ end
@@ -0,0 +1,161 @@
1
+ require 'yaml'
2
+ require 'socket'
3
+ require 'delegate'
4
+
5
+ module Rubber
6
+ module Configuration
7
+ # Contains the configuration defined in rubber.yml
8
+ # Handles selecting of correct config values based on
9
+ # the host/role passed into bind
10
+ class Environment
11
+ attr_reader :config_root
12
+ attr_reader :config_files
13
+ attr_reader :config_secret
14
+
15
+ def initialize(config_root)
16
+ @config_root = config_root
17
+ @config_files = ["#{@config_root}/rubber.yml"] + Dir["#{@config_root}/rubber-*.yml"].sort
18
+ @items = {}
19
+ @config_files.each { |file| read_config(file) }
20
+ @config_secret = bind().rubber_secret
21
+ read_config(@config_secret) if @config_secret
22
+ end
23
+
24
+ def read_config(file)
25
+ LOGGER.debug{"Reading rubber configuration from #{file}"}
26
+ if File.exist?(file)
27
+ @items = Environment.combine(@items, YAML.load_file(file) || {})
28
+ end
29
+ end
30
+
31
+ def known_roles
32
+ roles_dir = File.join(@config_root, "role")
33
+ roles = Dir.entries(roles_dir)
34
+ roles.delete_if {|d| d =~ /(^\..*)/}
35
+ end
36
+
37
+ def current_host
38
+ Socket::gethostname.gsub(/\..*/, '')
39
+ end
40
+
41
+ def current_full_host
42
+ Socket::gethostname
43
+ end
44
+
45
+ def bind(roles = nil, host = nil)
46
+ BoundEnv.new(@items, roles, host)
47
+ end
48
+
49
+ # combine old and new into a single value:
50
+ # non-nil wins if other is nil
51
+ # arrays just get unioned
52
+ # hashes also get unioned, but the values of conflicting keys get combined
53
+ # All else, the new value wins
54
+ def self.combine(old, new)
55
+ return old if new.nil?
56
+ return new if old.nil?
57
+ value = old
58
+ if old.is_a?(Hash) && new.is_a?(Hash)
59
+ value = old.clone
60
+ new.each do |nk, nv|
61
+ value[nk] = combine(value[nk], nv)
62
+ end
63
+ elsif old.is_a?(Array) && new.is_a?(Array)
64
+ value = old | new
65
+ else
66
+ value = new
67
+ end
68
+ return value
69
+ end
70
+
71
+ class HashValueProxy < Hash
72
+ attr_reader :global
73
+
74
+ def initialize(global, receiver)
75
+ @global = global
76
+ super()
77
+ replace(receiver)
78
+ end
79
+
80
+ def [](name)
81
+ value = super(name)
82
+ value = global[name] if global && !value
83
+ return expand(value)
84
+ end
85
+
86
+ def each
87
+ each_key do |key|
88
+ yield key, self[key]
89
+ end
90
+ end
91
+
92
+ def method_missing(method_id)
93
+ key = method_id.id2name
94
+ return self[key]
95
+ end
96
+
97
+ def expand_string(val)
98
+ while val =~ /\#\{[^\}]+\}/
99
+ val = eval('%Q{' + val + '}', binding)
100
+ end
101
+ val = true if val =="true"
102
+ val = false if val == "false"
103
+ return val
104
+ end
105
+
106
+ def expand(value)
107
+ val = case value
108
+ when Hash
109
+ HashValueProxy.new(global || self, value)
110
+ when String
111
+ expand_string(value)
112
+ when Enumerable
113
+ value.collect {|v| expand(v) }
114
+ else
115
+ value
116
+ end
117
+ return val
118
+ end
119
+
120
+ end
121
+
122
+ class BoundEnv < HashValueProxy
123
+ attr_reader :roles
124
+ attr_reader :host
125
+ attr_reader :full_host
126
+
127
+ def initialize(global, roles, host)
128
+ @roles = roles
129
+ @host = host
130
+ bound_global = bind_config(global)
131
+ super(nil, bound_global)
132
+ @full_host = "#{host}.#{domain}" rescue nil
133
+ end
134
+
135
+ # Forces role/host overrides into config
136
+ def bind_config(global)
137
+ global = global.clone()
138
+ role_overrides = global.delete("roles") || {}
139
+ host_overrides = global.delete("hosts") || {}
140
+ roles.to_a.each do |role|
141
+ role_overrides[role].each do |k, v|
142
+ global[k] = Environment.combine(global[k], v)
143
+ end if role_overrides[role]
144
+ end
145
+ host_overrides[host].each do |k, v|
146
+ global[k] = Environment.combine(global[k], v)
147
+ end if host_overrides[host]
148
+ return global
149
+ end
150
+
151
+ def method_missing(method_id)
152
+ key = method_id.id2name
153
+ return self[key]
154
+ end
155
+
156
+ end
157
+
158
+ end
159
+
160
+ end
161
+ end