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.
- data/CHANGELOG +39 -0
- data/COPYING +339 -0
- data/README +6 -0
- data/TODO +11 -0
- data/VERSION +1 -0
- data/bin/vulcanize +41 -0
- data/generators/vulcanize/USAGE +6 -0
- data/generators/vulcanize/templates/apache/config/rubber/deploy-apache.rb +51 -0
- data/generators/vulcanize/templates/apache/config/rubber/role/apache/deflate.conf +10 -0
- data/generators/vulcanize/templates/apache/config/rubber/role/apache/expires.conf +9 -0
- data/generators/vulcanize/templates/apache/config/rubber/role/apache/headers.conf +6 -0
- data/generators/vulcanize/templates/apache/config/rubber/role/apache/monit-apache.conf +8 -0
- data/generators/vulcanize/templates/apache/config/rubber/role/apache/ports.conf +5 -0
- data/generators/vulcanize/templates/apache/config/rubber/role/apache/setenvif.conf +52 -0
- data/generators/vulcanize/templates/apache/config/rubber/role/web_tools/tools-apache-vhost.conf +62 -0
- data/generators/vulcanize/templates/apache/config/rubber/role/web_tools/tools-apache.auth +7 -0
- data/generators/vulcanize/templates/apache/config/rubber/role/web_tools/tools-index.html +30 -0
- data/generators/vulcanize/templates/apache/config/rubber/rubber-apache.yml +7 -0
- data/generators/vulcanize/templates/apache/templates.yml +1 -0
- data/generators/vulcanize/templates/base/Capfile +14 -0
- data/generators/vulcanize/templates/base/config/deploy.rb +55 -0
- data/generators/vulcanize/templates/base/config/rubber/common/crontab +16 -0
- data/generators/vulcanize/templates/base/config/rubber/common/profile.rc +9 -0
- data/generators/vulcanize/templates/base/config/rubber/deploy-setup.rb +104 -0
- data/generators/vulcanize/templates/base/config/rubber/rubber.yml +241 -0
- data/generators/vulcanize/templates/base/lib/tasks/rubber.rake +15 -0
- data/generators/vulcanize/templates/base/script/cron-rake +18 -0
- data/generators/vulcanize/templates/base/script/cron-runner +18 -0
- data/generators/vulcanize/templates/base/script/cron-sh +67 -0
- data/generators/vulcanize/templates/base/templates.yml +1 -0
- data/generators/vulcanize/templates/complete_mongrel_mysql/config/rubber/role/haproxy/haproxy-mongrel.conf +23 -0
- data/generators/vulcanize/templates/complete_mongrel_mysql/config/rubber/role/nginx/nginx-mongrel.conf +113 -0
- data/generators/vulcanize/templates/complete_mongrel_mysql/config/rubber/rubber-complete.yml +41 -0
- data/generators/vulcanize/templates/complete_mongrel_mysql/templates.yml +6 -0
- data/generators/vulcanize/templates/complete_passenger_mysql/config/rubber/role/haproxy/haproxy-passenger.conf +19 -0
- data/generators/vulcanize/templates/complete_passenger_mysql/config/rubber/rubber-complete.yml +40 -0
- data/generators/vulcanize/templates/complete_passenger_mysql/templates.yml +10 -0
- data/generators/vulcanize/templates/cruise/config/rubber/deploy-cruise.rb +72 -0
- data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/cruise +40 -0
- data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/my.cnf +165 -0
- data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/production.rb +8 -0
- data/generators/vulcanize/templates/cruise/config/rubber/role/cruise/site_config.rb +76 -0
- data/generators/vulcanize/templates/cruise/config/rubber/role/web_tools/cruise-nginx.conf +11 -0
- data/generators/vulcanize/templates/cruise/config/rubber/rubber-cruise.yml +18 -0
- data/generators/vulcanize/templates/cruise/templates.yml +1 -0
- data/generators/vulcanize/templates/haproxy/config/rubber/deploy-haproxy.rb +45 -0
- data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/haproxy-base.conf +26 -0
- data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/haproxy-default.conf +8 -0
- data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/monit-haproxy.conf +9 -0
- data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/syslog-haproxy.conf +6 -0
- data/generators/vulcanize/templates/haproxy/config/rubber/role/haproxy/syslogd-default.conf +17 -0
- data/generators/vulcanize/templates/haproxy/config/rubber/role/web_tools/haproxy-nginx.conf +10 -0
- data/generators/vulcanize/templates/haproxy/config/rubber/rubber-haproxy.yml +7 -0
- data/generators/vulcanize/templates/haproxy/templates.yml +1 -0
- data/generators/vulcanize/templates/memcached/config/memcached.yml +28 -0
- data/generators/vulcanize/templates/memcached/config/rubber/common/memcached.yml +14 -0
- data/generators/vulcanize/templates/memcached/config/rubber/role/memcached/memcached.conf +52 -0
- data/generators/vulcanize/templates/memcached/config/rubber/role/memcached/memcached_munin_plugin +249 -0
- data/generators/vulcanize/templates/memcached/config/rubber/rubber-memcached.yml +7 -0
- data/generators/vulcanize/templates/memcached/templates.yml +1 -0
- data/generators/vulcanize/templates/minimal_mysql/templates.yml +7 -0
- data/generators/vulcanize/templates/minimal_nodb/templates.yml +6 -0
- data/generators/vulcanize/templates/mongrel/config/rubber/deploy-mongrel.rb +75 -0
- data/generators/vulcanize/templates/mongrel/config/rubber/role/mongrel/mongrel_cluster.yml +12 -0
- data/generators/vulcanize/templates/mongrel/config/rubber/role/mongrel/monit-mongrel.conf +20 -0
- data/generators/vulcanize/templates/mongrel/config/rubber/rubber-mongrel.yml +9 -0
- data/generators/vulcanize/templates/mongrel/templates.yml +1 -0
- data/generators/vulcanize/templates/monit/config/rubber/common/monit-default.conf +15 -0
- data/generators/vulcanize/templates/monit/config/rubber/common/monit.conf +251 -0
- data/generators/vulcanize/templates/monit/config/rubber/deploy-monit.rb +32 -0
- data/generators/vulcanize/templates/monit/config/rubber/role/web_tools/monit-admin-nginx.conf +10 -0
- data/generators/vulcanize/templates/monit/config/rubber/rubber-monit.yml +6 -0
- data/generators/vulcanize/templates/monit/templates.yml +1 -0
- data/generators/vulcanize/templates/munin/config/rubber/common/monit-munin.conf +8 -0
- data/generators/vulcanize/templates/munin/config/rubber/common/munin-node.conf +48 -0
- data/generators/vulcanize/templates/munin/config/rubber/deploy-munin.rb +46 -0
- data/generators/vulcanize/templates/munin/config/rubber/role/web_tools/munin-nginx.conf +8 -0
- data/generators/vulcanize/templates/munin/config/rubber/role/web_tools/munin-plugins.conf +31 -0
- data/generators/vulcanize/templates/munin/config/rubber/role/web_tools/munin.conf +80 -0
- data/generators/vulcanize/templates/munin/config/rubber/rubber-munin.yml +8 -0
- data/generators/vulcanize/templates/munin/script/munin/example_mysql_query.rb +57 -0
- data/generators/vulcanize/templates/munin/script/munin/example_simple.rb +24 -0
- data/generators/vulcanize/templates/munin/templates.yml +1 -0
- data/generators/vulcanize/templates/mysql/config/rubber/common/database.yml +11 -0
- data/generators/vulcanize/templates/mysql/config/rubber/deploy-mysql.rb +156 -0
- data/generators/vulcanize/templates/mysql/config/rubber/role/db/crontab +14 -0
- data/generators/vulcanize/templates/mysql/config/rubber/role/db/monit-mysql.cnf +10 -0
- data/generators/vulcanize/templates/mysql/config/rubber/role/db/my.cnf +167 -0
- data/generators/vulcanize/templates/mysql/config/rubber/role/mysql_slave/mysql_slave_munin_plugin +51 -0
- data/generators/vulcanize/templates/mysql/config/rubber/rubber-mysql.yml +46 -0
- data/generators/vulcanize/templates/mysql/templates.yml +1 -0
- data/generators/vulcanize/templates/mysql_cluster/config/rubber/common/mysql_cluster_migrations.rb +13 -0
- data/generators/vulcanize/templates/mysql_cluster/config/rubber/deploy-mysql_cluster.rb +173 -0
- data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_data/my.cnf +15 -0
- data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_mgm/ndb_mgmd.cnf +39 -0
- data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_sql/monit-mysql_cluster_sql.cnf +10 -0
- data/generators/vulcanize/templates/mysql_cluster/config/rubber/role/mysql_sql/my.cnf +23 -0
- data/generators/vulcanize/templates/mysql_cluster/config/rubber/rubber-mysql_cluster.yml +32 -0
- data/generators/vulcanize/templates/mysql_cluster/templates.yml +1 -0
- data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/database.yml +16 -0
- data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/monit-mysql_proxy.cnf +10 -0
- data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/mysql-proxy +153 -0
- data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/mysql-proxy.conf +10 -0
- data/generators/vulcanize/templates/mysql_proxy/config/rubber/common/mysql-proxy.lua +5 -0
- data/generators/vulcanize/templates/mysql_proxy/config/rubber/deploy-mysql_proxy.rb +52 -0
- data/generators/vulcanize/templates/mysql_proxy/config/rubber/rubber-mysql_proxy.yml +11 -0
- data/generators/vulcanize/templates/mysql_proxy/templates.yml +1 -0
- data/generators/vulcanize/templates/nginx/config/rubber/deploy-nginx.rb +45 -0
- data/generators/vulcanize/templates/nginx/config/rubber/role/nginx/crontab +9 -0
- data/generators/vulcanize/templates/nginx/config/rubber/role/nginx/monit-nginx.conf +8 -0
- data/generators/vulcanize/templates/nginx/config/rubber/role/nginx/nginx.conf +42 -0
- data/generators/vulcanize/templates/nginx/config/rubber/role/web_tools/nginx-tools.conf +55 -0
- data/generators/vulcanize/templates/nginx/config/rubber/role/web_tools/tools-index.html +30 -0
- data/generators/vulcanize/templates/nginx/config/rubber/role/web_tools/tools-nginx.auth +7 -0
- data/generators/vulcanize/templates/nginx/config/rubber/rubber-nginx.yml +10 -0
- data/generators/vulcanize/templates/nginx/templates.yml +1 -0
- data/generators/vulcanize/templates/passenger/config/rubber/deploy-passenger.rb +37 -0
- data/generators/vulcanize/templates/passenger/config/rubber/role/passenger/munin-passenger-sudoers.conf +6 -0
- data/generators/vulcanize/templates/passenger/config/rubber/role/passenger/munin-passenger.conf +47 -0
- data/generators/vulcanize/templates/passenger/config/rubber/role/passenger/passenger-apache-vhost.conf +46 -0
- data/generators/vulcanize/templates/passenger/config/rubber/role/passenger/passenger.conf +10 -0
- data/generators/vulcanize/templates/passenger/config/rubber/rubber-passenger.yml +12 -0
- data/generators/vulcanize/templates/passenger/templates.yml +1 -0
- data/generators/vulcanize/templates/sphinx/config/rubber/common/sphinx.yml +46 -0
- data/generators/vulcanize/templates/sphinx/config/rubber/deploy-sphinx.rb +112 -0
- data/generators/vulcanize/templates/sphinx/config/rubber/role/sphinx/crontab +11 -0
- data/generators/vulcanize/templates/sphinx/config/rubber/role/sphinx/monit-sphinx.conf +10 -0
- data/generators/vulcanize/templates/sphinx/config/rubber/rubber-sphinx.yml +6 -0
- data/generators/vulcanize/templates/sphinx/templates.yml +1 -0
- data/generators/vulcanize/vulcanize_generator.rb +67 -0
- data/lib/capistrano/hostcmd.rb +12 -0
- data/lib/rubber.rb +38 -0
- data/lib/rubber/capistrano.rb +1 -0
- data/lib/rubber/cloud.rb +13 -0
- data/lib/rubber/cloud/aws.rb +305 -0
- data/lib/rubber/cloud/base.rb +16 -0
- data/lib/rubber/configuration.rb +47 -0
- data/lib/rubber/dns.rb +13 -0
- data/lib/rubber/dns/base.rb +69 -0
- data/lib/rubber/dns/dyndns.rb +63 -0
- data/lib/rubber/dns/nettica.rb +73 -0
- data/lib/rubber/dns/zerigo.rb +131 -0
- data/lib/rubber/environment.rb +161 -0
- data/lib/rubber/generator.rb +197 -0
- data/lib/rubber/instance.rb +165 -0
- data/lib/rubber/recipes/rubber.rb +89 -0
- data/lib/rubber/recipes/rubber/bundles.rb +28 -0
- data/lib/rubber/recipes/rubber/deploy.rb +90 -0
- data/lib/rubber/recipes/rubber/instances.rb +348 -0
- data/lib/rubber/recipes/rubber/load_balancers.rb +44 -0
- data/lib/rubber/recipes/rubber/security_groups.rb +189 -0
- data/lib/rubber/recipes/rubber/setup.rb +357 -0
- data/lib/rubber/recipes/rubber/static_ips.rb +107 -0
- data/lib/rubber/recipes/rubber/utils.rb +203 -0
- data/lib/rubber/recipes/rubber/volumes.rb +264 -0
- data/lib/rubber/tasks/rubber.rb +221 -0
- data/lib/rubber/util.rb +37 -0
- data/test/environment_test.rb +118 -0
- data/test/generator_test.rb +323 -0
- data/test/instance_test.rb +93 -0
- data/test/test_helper.rb +4 -0
- data/test/util_test.rb +16 -0
- metadata +274 -0
|
@@ -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,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
|