clouddns 0.0.2 → 0.0.3
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/bin/clouddns +25 -6
- data/clouddns.gemspec +3 -0
- data/lib/clouddns.rb +3 -4
- data/lib/clouddns/actions.rb +2 -0
- data/lib/clouddns/actions/migrate.rb +6 -7
- data/lib/clouddns/actions/print.rb +1 -4
- data/lib/clouddns/actions/zonefile.rb +29 -0
- data/lib/clouddns/dsl.rb +3 -14
- data/lib/clouddns/railtie.rb +9 -0
- data/lib/clouddns/tasks.rb +33 -0
- data/lib/clouddns/utils.rb +31 -0
- data/lib/clouddns/version.rb +1 -1
- data/lib/clouddns/zone_migration.rb +33 -15
- data/test/dsl_test.rb +12 -6
- metadata +40 -42
- data/lib/clouddns/actions/print_record.rb +0 -19
data/bin/clouddns
CHANGED
@@ -9,10 +9,16 @@ options = {
|
|
9
9
|
:force => false
|
10
10
|
}
|
11
11
|
|
12
|
-
OptionParser.new do |opts|
|
13
|
-
opts.banner =
|
12
|
+
option_parser = OptionParser.new do |opts|
|
13
|
+
opts.banner = [
|
14
|
+
"Usage: #{$0} [OPTIONS] print FILES # Pretty print contents of FILES",
|
15
|
+
" #{$0} [OPTIONS] migrate FILES # Update DNS servers",
|
16
|
+
" #{$0} [OPTIONS] zonefile FILES # Print FILES as zone files",
|
17
|
+
"",
|
18
|
+
""
|
19
|
+
].join("\n")
|
14
20
|
|
15
|
-
opts.on('-p', '--provider provider', "Override DNS provider (AWS,
|
21
|
+
opts.on('-p', '--provider provider', "Override DNS provider (AWS, bluebox, dnsimple, dnsmadeeasy, linode, slicehost, zerigo)") do |provider|
|
16
22
|
options[:fog][:provider] = provider
|
17
23
|
end
|
18
24
|
|
@@ -29,13 +35,26 @@ OptionParser.new do |opts|
|
|
29
35
|
puts opts
|
30
36
|
exit
|
31
37
|
end
|
32
|
-
end
|
38
|
+
end
|
39
|
+
|
40
|
+
option_parser.parse!
|
33
41
|
|
34
42
|
action = ARGV.slice!(0)
|
35
43
|
files = ARGV
|
36
44
|
|
37
|
-
|
38
|
-
|
45
|
+
if !action
|
46
|
+
error = "No action specified"
|
47
|
+
elsif files.empty?
|
48
|
+
error = "No files specified"
|
49
|
+
else
|
50
|
+
error = nil
|
51
|
+
end
|
52
|
+
|
53
|
+
if error
|
54
|
+
puts error
|
55
|
+
puts option_parser
|
56
|
+
exit 1
|
57
|
+
end
|
39
58
|
|
40
59
|
action = Clouddns::Actions.by_name(action)
|
41
60
|
|
data/clouddns.gemspec
CHANGED
data/lib/clouddns.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
-
require "fog"
|
2
|
-
|
3
1
|
require "clouddns/actions"
|
4
2
|
require "clouddns/dsl"
|
5
3
|
require "clouddns/record"
|
4
|
+
require "clouddns/utils"
|
6
5
|
require "clouddns/version"
|
7
6
|
require "clouddns/zone"
|
8
7
|
require "clouddns/zone_migration"
|
9
8
|
|
10
|
-
|
11
|
-
|
9
|
+
require 'clouddns/railtie' if defined?(Rails)
|
10
|
+
|
data/lib/clouddns/actions.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require 'clouddns/actions/generic_action'
|
3
3
|
require 'clouddns/actions/print'
|
4
4
|
require 'clouddns/actions/migrate'
|
5
|
+
require 'clouddns/actions/zonefile'
|
5
6
|
|
6
7
|
module Clouddns
|
7
8
|
module Actions
|
@@ -9,6 +10,7 @@ module Clouddns
|
|
9
10
|
case name.downcase
|
10
11
|
when 'print' then Print
|
11
12
|
when 'migrate' then Migrate
|
13
|
+
when 'zonefile' then Zonefile
|
12
14
|
else
|
13
15
|
raise "Unknown action: #{name}"
|
14
16
|
end
|
@@ -1,11 +1,10 @@
|
|
1
|
-
require 'clouddns/actions/print_record'
|
2
1
|
|
3
2
|
module Clouddns
|
4
3
|
module Actions
|
5
4
|
class Migrate < GenericAction
|
6
|
-
include PrintRecord
|
7
|
-
|
8
5
|
def run
|
6
|
+
require 'fog'
|
7
|
+
|
9
8
|
@fog = Fog::DNS.new(@options[:fog])
|
10
9
|
@fog_zone = @fog.zones.find { |z| z.domain == @zone.name }
|
11
10
|
|
@@ -52,15 +51,15 @@ module Clouddns
|
|
52
51
|
end
|
53
52
|
|
54
53
|
def print_changes
|
55
|
-
namelength = @migration.changes.map do |
|
56
|
-
record.name.length
|
54
|
+
namelength = @migration.changes.map do |change|
|
55
|
+
change.record.name.length
|
57
56
|
end.max
|
58
57
|
|
59
58
|
puts
|
60
59
|
puts "Changes:"
|
61
60
|
|
62
|
-
@migration.changes.each do |
|
63
|
-
|
61
|
+
@migration.changes.each do |change|
|
62
|
+
puts change.to_s(namelength)
|
64
63
|
end
|
65
64
|
end
|
66
65
|
|
@@ -1,10 +1,7 @@
|
|
1
|
-
require 'clouddns/actions/print_record'
|
2
1
|
|
3
2
|
module Clouddns
|
4
3
|
module Actions
|
5
4
|
class Print < GenericAction
|
6
|
-
include PrintRecord
|
7
|
-
|
8
5
|
def run
|
9
6
|
print_all
|
10
7
|
end
|
@@ -14,7 +11,7 @@ module Clouddns
|
|
14
11
|
puts "Zone '#{@zone.name}'"
|
15
12
|
namelength = @zone.records.map{ |x| x.name.length }.max
|
16
13
|
@zone.records.each do |record|
|
17
|
-
|
14
|
+
puts Utils::format_record record, :namelength => namelength
|
18
15
|
end
|
19
16
|
end
|
20
17
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
module Clouddns
|
3
|
+
module Actions
|
4
|
+
class Zonefile < GenericAction
|
5
|
+
def run
|
6
|
+
print_all
|
7
|
+
end
|
8
|
+
|
9
|
+
protected
|
10
|
+
def print_all
|
11
|
+
puts "$ORIGIN #{@zone.name}"
|
12
|
+
|
13
|
+
namelength = @zone.records.map{ |x| x.name.length }.max
|
14
|
+
@zone.records.each do |record|
|
15
|
+
record.value.each_with_index do |value, i|
|
16
|
+
print "%-18s " % record.name
|
17
|
+
print "%5i " % record.ttl
|
18
|
+
print "IN "
|
19
|
+
print "%-5s " % record.type
|
20
|
+
print "%s " % value
|
21
|
+
puts
|
22
|
+
end
|
23
|
+
end
|
24
|
+
puts
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
data/lib/clouddns/dsl.rb
CHANGED
@@ -3,9 +3,6 @@ module Clouddns
|
|
3
3
|
attr_reader :zones
|
4
4
|
attr_reader :fog_options
|
5
5
|
|
6
|
-
# This need not be too strict. Only exists to help catch typos.
|
7
|
-
DNS_REGEX = /\A.*\..*\.\z/
|
8
|
-
|
9
6
|
def initialize
|
10
7
|
@zones = []
|
11
8
|
@zone = nil
|
@@ -32,7 +29,8 @@ module Clouddns
|
|
32
29
|
end
|
33
30
|
|
34
31
|
def add_record type, name, value, options={}
|
35
|
-
name =
|
32
|
+
name = Utils::parse_domain(name)
|
33
|
+
options = @defaults.merge(options)
|
36
34
|
|
37
35
|
value = "\"#{value}\"" if type == 'TXT'
|
38
36
|
|
@@ -45,7 +43,7 @@ module Clouddns
|
|
45
43
|
def zone name
|
46
44
|
raise "zones cannot be nested" if @zone
|
47
45
|
|
48
|
-
@zone = Zone.new(
|
46
|
+
@zone = Zone.new(Utils::parse_domain(name))
|
49
47
|
@zones << @zone
|
50
48
|
yield
|
51
49
|
@zone = nil
|
@@ -66,15 +64,6 @@ module Clouddns
|
|
66
64
|
def provider name, options={}
|
67
65
|
@fog_options = options.merge({:provider => name})
|
68
66
|
end
|
69
|
-
|
70
|
-
private
|
71
|
-
def domainname name
|
72
|
-
if name.end_with? '.'
|
73
|
-
name
|
74
|
-
else
|
75
|
-
"#{name}."
|
76
|
-
end
|
77
|
-
end
|
78
67
|
end
|
79
68
|
end
|
80
69
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
require 'clouddns'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
namespace :dns do
|
6
|
+
desc "Print DNS entries from config/dns/*.rb"
|
7
|
+
task :print do
|
8
|
+
run_action Clouddns::Actions::Print
|
9
|
+
end
|
10
|
+
desc "Update DNS service with config/dns/*.rb"
|
11
|
+
task :migrate do
|
12
|
+
run_action Clouddns::Actions::Migrate
|
13
|
+
end
|
14
|
+
desc "Print config/dns/*.rb as zonefiles"
|
15
|
+
task :zonefile do
|
16
|
+
run_action Clouddns::Actions::Zonefile
|
17
|
+
end
|
18
|
+
def run_action action
|
19
|
+
root_path = defined?(Rails) ? Rails.root : Pathname.new('.')
|
20
|
+
dns_path = root_path.join('config', 'dns')
|
21
|
+
files = Dir[dns_path.join('**','*.rb')]
|
22
|
+
if files.empty?
|
23
|
+
raise "No DNS configuration. Please create config/dns/yourdomain.rb"
|
24
|
+
end
|
25
|
+
files.each do |file|
|
26
|
+
dsl = Clouddns::DSL.parse_file(file)
|
27
|
+
dsl.zones.each do |zone|
|
28
|
+
action.run(zone)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Clouddns
|
2
|
+
module Utils
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def parse_domain name
|
6
|
+
if name =~ /\A(.*?\..*?)\.?\z/
|
7
|
+
"#{$1}."
|
8
|
+
else
|
9
|
+
raise "Invalid domain: '#{name}'"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def format_record record, options={}
|
14
|
+
namelength = options[:namelength] || 20
|
15
|
+
prefix = options[:prefix] || ''
|
16
|
+
|
17
|
+
output = []
|
18
|
+
|
19
|
+
record.value.each_with_index do |value, i|
|
20
|
+
if i.zero?
|
21
|
+
args = [prefix, record.type, record.ttl, record.name, value]
|
22
|
+
else
|
23
|
+
args = [prefix, '', '', '', value]
|
24
|
+
end
|
25
|
+
output << "%s%5s %5s %#{namelength}s %s" % args
|
26
|
+
end
|
27
|
+
|
28
|
+
output.join("\n")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/clouddns/version.rb
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
module Clouddns
|
2
2
|
class ZoneMigration
|
3
|
+
module Change
|
4
|
+
class None < Struct.new(:record)
|
5
|
+
def perform! fog_zone
|
6
|
+
end
|
7
|
+
def print_prefix; ' '; end
|
8
|
+
def to_s length=30
|
9
|
+
Utils::format_record record, :prefix => print_prefix, :namelength => length
|
10
|
+
end
|
11
|
+
end
|
12
|
+
class Create < None
|
13
|
+
def perform! fog_zone
|
14
|
+
fog_zone.records.create(:type => record.type, :name => record.name, :value => record.value, :ttl => record.ttl)
|
15
|
+
end
|
16
|
+
def print_prefix; '+'; end
|
17
|
+
end
|
18
|
+
class Remove < None
|
19
|
+
def perform! fog_zone
|
20
|
+
record.destroy
|
21
|
+
end
|
22
|
+
def print_prefix; '-'; end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
3
26
|
def initialize zone, fog_zone
|
4
27
|
@zone = zone
|
5
28
|
@fog_zone = fog_zone
|
@@ -12,35 +35,31 @@ module Clouddns
|
|
12
35
|
@zone.records.each do |record|
|
13
36
|
if (fog_record = fog_records.delete([record.name, record.type]))
|
14
37
|
if records_equal?(record, fog_record)
|
15
|
-
@changes <<
|
38
|
+
@changes << Change::None.new(record)
|
16
39
|
else
|
17
|
-
@changes <<
|
18
|
-
@changes <<
|
40
|
+
@changes << Change::Remove.new(fog_record)
|
41
|
+
@changes << Change::Create.new(record)
|
19
42
|
end
|
20
43
|
else
|
21
|
-
@changes <<
|
44
|
+
@changes << Change::Create.new(record)
|
22
45
|
end
|
23
46
|
end
|
24
47
|
|
25
48
|
fog_records.each do |name, record|
|
26
|
-
@changes <<
|
49
|
+
@changes << Change::Remove.new(record)
|
27
50
|
end
|
28
51
|
@changes
|
29
52
|
end
|
30
53
|
|
31
54
|
def perform!
|
32
|
-
changes.each do |
|
33
|
-
|
34
|
-
@fog_zone.records.create(:type => record.type, :name => record.name, :ip => record.value, :ttl => record.ttl)
|
35
|
-
elsif action == '-'
|
36
|
-
record.destroy
|
37
|
-
end
|
55
|
+
changes.each do |change|
|
56
|
+
change.perform! @fog_zone
|
38
57
|
end
|
39
58
|
end
|
40
59
|
|
41
60
|
def completed?
|
42
|
-
changes.all? do |
|
43
|
-
|
61
|
+
changes.all? do |change|
|
62
|
+
change.class == Change::None
|
44
63
|
end
|
45
64
|
end
|
46
65
|
|
@@ -53,9 +72,8 @@ module Clouddns
|
|
53
72
|
# AWS replaces * with \052
|
54
73
|
record.name == fog_record_name(fog_record) &&
|
55
74
|
record.type == fog_record.type &&
|
56
|
-
record.value == fog_record.
|
75
|
+
record.value == fog_record.value &&
|
57
76
|
record.ttl.to_i == fog_record.ttl.to_i
|
58
77
|
end
|
59
|
-
|
60
78
|
end
|
61
79
|
end
|
data/test/dsl_test.rb
CHANGED
@@ -20,14 +20,20 @@ class DslTest < Test::Unit::TestCase
|
|
20
20
|
assert_equal ['1.2.3.4'], record.value
|
21
21
|
end
|
22
22
|
def test_trailing_dot_is_implied
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
for zonename in %w{example.com example.com.}
|
24
|
+
dsl = Clouddns::DSL.parse_string <<-EOL
|
25
|
+
zone "#{zonename}" do
|
26
|
+
A 'test1.example.com', '1.2.3.4'
|
27
|
+
A 'test2.example.com.', '1.2.3.4'
|
26
28
|
end
|
27
|
-
|
29
|
+
EOL
|
30
|
+
|
31
|
+
assert_equal 'example.com.', dsl.zones.first.name
|
28
32
|
|
29
|
-
|
30
|
-
|
33
|
+
records = dsl.zones.first.records
|
34
|
+
assert_equal 'test1.example.com.', records[0].name
|
35
|
+
assert_equal 'test2.example.com.', records[1].name
|
36
|
+
end
|
31
37
|
end
|
32
38
|
end
|
33
39
|
|
metadata
CHANGED
@@ -1,33 +1,35 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: clouddns
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 2
|
10
|
-
version: 0.0.2
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- John Hawthorn
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
date: 2011-11-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: fog
|
16
|
+
requirement: &18817680 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.9.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *18817680
|
21
25
|
description: A DSL for managing DNS through cloud services
|
22
|
-
email:
|
26
|
+
email:
|
23
27
|
- john.hawthorn@gmail.com
|
24
|
-
executables:
|
28
|
+
executables:
|
25
29
|
- clouddns
|
26
30
|
extensions: []
|
27
|
-
|
28
31
|
extra_rdoc_files: []
|
29
|
-
|
30
|
-
files:
|
32
|
+
files:
|
31
33
|
- .gitignore
|
32
34
|
- Gemfile
|
33
35
|
- README.md
|
@@ -39,9 +41,12 @@ files:
|
|
39
41
|
- lib/clouddns/actions/generic_action.rb
|
40
42
|
- lib/clouddns/actions/migrate.rb
|
41
43
|
- lib/clouddns/actions/print.rb
|
42
|
-
- lib/clouddns/actions/
|
44
|
+
- lib/clouddns/actions/zonefile.rb
|
43
45
|
- lib/clouddns/dsl.rb
|
46
|
+
- lib/clouddns/railtie.rb
|
44
47
|
- lib/clouddns/record.rb
|
48
|
+
- lib/clouddns/tasks.rb
|
49
|
+
- lib/clouddns/utils.rb
|
45
50
|
- lib/clouddns/version.rb
|
46
51
|
- lib/clouddns/zone.rb
|
47
52
|
- lib/clouddns/zone_migration.rb
|
@@ -49,37 +54,30 @@ files:
|
|
49
54
|
- test/test_helper.rb
|
50
55
|
homepage: https://github.com/jhawthorn/clouddns
|
51
56
|
licenses: []
|
52
|
-
|
53
57
|
post_install_message:
|
54
58
|
rdoc_options: []
|
55
|
-
|
56
|
-
require_paths:
|
59
|
+
require_paths:
|
57
60
|
- lib
|
58
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
62
|
none: false
|
60
|
-
requirements:
|
61
|
-
- -
|
62
|
-
- !ruby/object:Gem::Version
|
63
|
-
|
64
|
-
|
65
|
-
- 0
|
66
|
-
version: "0"
|
67
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
68
|
none: false
|
69
|
-
requirements:
|
70
|
-
- -
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
|
73
|
-
segments:
|
74
|
-
- 0
|
75
|
-
version: "0"
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
76
73
|
requirements: []
|
77
|
-
|
78
74
|
rubyforge_project:
|
79
|
-
rubygems_version: 1.8.
|
75
|
+
rubygems_version: 1.8.10
|
80
76
|
signing_key:
|
81
77
|
specification_version: 3
|
82
|
-
summary: A DSL and tools for managing DNS through any of the services supported by
|
83
|
-
|
78
|
+
summary: A DSL and tools for managing DNS through any of the services supported by
|
79
|
+
fog. Currently, this is Amazon Route 53, bluebox, DNSimple, DNS Made Easy, Linode
|
80
|
+
DNS, Slicehost DNS and Zerigo DNS
|
81
|
+
test_files:
|
84
82
|
- test/dsl_test.rb
|
85
83
|
- test/test_helper.rb
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Clouddns
|
2
|
-
module Actions
|
3
|
-
module PrintRecord
|
4
|
-
protected
|
5
|
-
def print_record record, namelength, prefix=''
|
6
|
-
values = record.respond_to?(:value) ? record.value : record.ip
|
7
|
-
values.each_with_index do |value, i|
|
8
|
-
if i.zero?
|
9
|
-
args = [prefix, record.type, record.ttl, record.name, value]
|
10
|
-
else
|
11
|
-
args = [prefix, '', '', '', value]
|
12
|
-
end
|
13
|
-
puts "%s%5s %5s %#{namelength}s %s" % args
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|