fog-dynect 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +15 -0
- data/CHANGELOG.md +3 -0
- data/CONTRIBUTING.md +18 -0
- data/CONTRIBUTORS.md +27 -0
- data/Gemfile +4 -0
- data/LICENSE.md +20 -0
- data/README.md +58 -0
- data/Rakefile +8 -0
- data/fog-dynect.gemspec +29 -0
- data/gemfiles/Gemfile-1.8.7 +6 -0
- data/lib/fog/dynect.rb +1 -0
- data/lib/fog/dynect/core.rb +27 -0
- data/lib/fog/dynect/dns.rb +157 -0
- data/lib/fog/dynect/models/dns/record.rb +67 -0
- data/lib/fog/dynect/models/dns/records.rb +48 -0
- data/lib/fog/dynect/models/dns/zone.rb +56 -0
- data/lib/fog/dynect/models/dns/zones.rb +25 -0
- data/lib/fog/dynect/requests/dns/delete_record.rb +55 -0
- data/lib/fog/dynect/requests/dns/delete_zone.rb +41 -0
- data/lib/fog/dynect/requests/dns/get_all_records.rb +56 -0
- data/lib/fog/dynect/requests/dns/get_node_list.rb +55 -0
- data/lib/fog/dynect/requests/dns/get_record.rb +83 -0
- data/lib/fog/dynect/requests/dns/get_zone.rb +57 -0
- data/lib/fog/dynect/requests/dns/post_record.rb +71 -0
- data/lib/fog/dynect/requests/dns/post_session.rb +43 -0
- data/lib/fog/dynect/requests/dns/post_zone.rb +70 -0
- data/lib/fog/dynect/requests/dns/put_record.rb +76 -0
- data/lib/fog/dynect/requests/dns/put_zone.rb +76 -0
- data/lib/fog/dynect/version.rb +5 -0
- data/tests/dns/helper.rb +22 -0
- data/tests/dns/models/record_tests.rb +44 -0
- data/tests/dns/models/records_tests.rb +30 -0
- data/tests/dns/models/zone_tests.rb +18 -0
- data/tests/dns/models/zones_tests.rb +18 -0
- data/tests/dynect/requests/dns/dns_tests.rb +258 -0
- data/tests/helper.rb +13 -0
- metadata +168 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'fog/core/collection'
|
2
|
+
require 'fog/dynect/models/dns/record'
|
3
|
+
|
4
|
+
module Fog
|
5
|
+
module DNS
|
6
|
+
class Dynect
|
7
|
+
class Records < Fog::Collection
|
8
|
+
attribute :zone
|
9
|
+
|
10
|
+
model Fog::DNS::Dynect::Record
|
11
|
+
|
12
|
+
def all(options = {})
|
13
|
+
requires :zone
|
14
|
+
data = []
|
15
|
+
service.get_all_records(zone.domain, options).body['data'].each do |records|
|
16
|
+
(type, list) = records
|
17
|
+
list.each do |record|
|
18
|
+
data << {
|
19
|
+
:identity => record['record_id'],
|
20
|
+
:fqdn => record['fqdn'],
|
21
|
+
:type => record['record_type'],
|
22
|
+
:rdata => record['rdata']
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
load(data)
|
28
|
+
end
|
29
|
+
|
30
|
+
def get(record_id)
|
31
|
+
requires :zone
|
32
|
+
|
33
|
+
# there isn't a way to look up by just id
|
34
|
+
# must have type and domain for 'get_record' request
|
35
|
+
# so we pick it from the list returned by 'all'
|
36
|
+
|
37
|
+
list = all
|
38
|
+
list.detect {|e| e.id == record_id}
|
39
|
+
end
|
40
|
+
|
41
|
+
def new(attributes = {})
|
42
|
+
requires :zone
|
43
|
+
super({:zone => zone}.merge!(attributes))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'fog/core/model'
|
2
|
+
require 'fog/dynect/models/dns/records'
|
3
|
+
|
4
|
+
module Fog
|
5
|
+
module DNS
|
6
|
+
class Dynect
|
7
|
+
class Zone < Fog::Model
|
8
|
+
identity :domain
|
9
|
+
|
10
|
+
attribute :domain, :aliases => 'zone'
|
11
|
+
attribute :email, :aliases => 'rname'
|
12
|
+
attribute :serial
|
13
|
+
attribute :serial_style
|
14
|
+
attribute :ttl
|
15
|
+
attribute :type, :aliases => 'zone_type'
|
16
|
+
|
17
|
+
def initialize(attributes={})
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def destroy
|
22
|
+
requires :domain
|
23
|
+
service.delete_zone(domain)
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
undef_method :domain=
|
28
|
+
def domain=(new_domain)
|
29
|
+
attributes[:domain] = new_domain.split('/').last
|
30
|
+
end
|
31
|
+
|
32
|
+
def publish
|
33
|
+
requires :identity
|
34
|
+
data = service.put_zone(identity, 'publish' => true)
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
def records
|
39
|
+
@records ||= Fog::DNS::Dynect::Records.new(:zone => self, :service => service)
|
40
|
+
end
|
41
|
+
|
42
|
+
def nameservers
|
43
|
+
raise 'nameservers Not Implemented'
|
44
|
+
end
|
45
|
+
|
46
|
+
def save
|
47
|
+
self.ttl ||= 3600
|
48
|
+
requires :domain, :email, :ttl
|
49
|
+
data = service.post_zone(email, ttl, domain).body['data']
|
50
|
+
merge_attributes(data)
|
51
|
+
true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'fog/core/collection'
|
2
|
+
require 'fog/dynect/models/dns/zone'
|
3
|
+
|
4
|
+
module Fog
|
5
|
+
module DNS
|
6
|
+
class Dynect
|
7
|
+
class Zones < Fog::Collection
|
8
|
+
model Fog::DNS::Dynect::Zone
|
9
|
+
|
10
|
+
def all
|
11
|
+
data = service.get_zone.body['data'].map do |zone|
|
12
|
+
{ :domain => zone }
|
13
|
+
end
|
14
|
+
load(data)
|
15
|
+
end
|
16
|
+
|
17
|
+
def get(zone_id)
|
18
|
+
new(service.get_zone('zone' => zone_id).body['data'])
|
19
|
+
rescue Excon::Errors::NotFound
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Fog
|
2
|
+
module DNS
|
3
|
+
class Dynect
|
4
|
+
class Real
|
5
|
+
# Delete a record
|
6
|
+
#
|
7
|
+
# ==== Parameters
|
8
|
+
# * type<~String> - type of record in ['AAAA', 'ANY', 'A', 'CNAME', 'DHCID', 'DNAME', 'DNSKEY', 'DS', 'KEY', 'LOC', 'MX', 'NSA', 'NS', 'PTR', 'PX', 'RP', 'SOA', 'SPF', 'SRV', 'SSHFP', 'TXT']
|
9
|
+
# * zone<~String> - zone of record
|
10
|
+
# * fqdn<~String> - fqdn of record
|
11
|
+
# * record_id<~String> - id of record
|
12
|
+
|
13
|
+
def delete_record(type, zone, fqdn, record_id)
|
14
|
+
request(
|
15
|
+
:expects => 200,
|
16
|
+
:idempotent => true,
|
17
|
+
:method => :delete,
|
18
|
+
:path => ["#{type.to_s.upcase}Record", zone, fqdn, record_id].join('/')
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Mock
|
24
|
+
def delete_record(type, zone, fqdn, record_id)
|
25
|
+
raise Fog::DNS::Dynect::NotFound unless zone = self.data[:zones][zone]
|
26
|
+
|
27
|
+
raise Fog::DNS::Dynect::NotFound unless zone[:records][type].find { |record| record[:fqdn] == fqdn && record[:record_id] == record_id.to_i }
|
28
|
+
|
29
|
+
zone[:records_to_delete] << {
|
30
|
+
:type => type,
|
31
|
+
:fqdn => fqdn,
|
32
|
+
:record_id => record_id.to_i
|
33
|
+
}
|
34
|
+
|
35
|
+
response = Excon::Response.new
|
36
|
+
response.status = 200
|
37
|
+
|
38
|
+
response.body = {
|
39
|
+
"status" => "success",
|
40
|
+
"data" => {},
|
41
|
+
"job_id" => Fog::Dynect::Mock.job_id,
|
42
|
+
"msgs" => [{
|
43
|
+
"INFO" => "delete: Record will be deleted on zone publish",
|
44
|
+
"SOURCE" => "BLL",
|
45
|
+
"ERR_CD" => nil,
|
46
|
+
"LVL" => "INFO"
|
47
|
+
}]
|
48
|
+
}
|
49
|
+
|
50
|
+
response
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Fog
|
2
|
+
module DNS
|
3
|
+
class Dynect
|
4
|
+
class Real
|
5
|
+
# Delete a zone
|
6
|
+
#
|
7
|
+
# ==== Parameters
|
8
|
+
# * zone<~String> - zone to host
|
9
|
+
|
10
|
+
def delete_zone(zone)
|
11
|
+
request(
|
12
|
+
:expects => 200,
|
13
|
+
:method => :delete,
|
14
|
+
:path => "Zone/#{zone}"
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Mock
|
20
|
+
def delete_zone(zone)
|
21
|
+
self.data[:zones].delete(zone)
|
22
|
+
|
23
|
+
response = Excon::Response.new
|
24
|
+
response.status = 200
|
25
|
+
response.body = {
|
26
|
+
"status" => "success",
|
27
|
+
"data" => {},
|
28
|
+
"job_id" => Fog::Dynect::Mock.job_id,
|
29
|
+
"msgs" => [{
|
30
|
+
"ERR_CD" => '',
|
31
|
+
"INFO" => '',
|
32
|
+
"LVL" => '',
|
33
|
+
"SOURCE" => ''
|
34
|
+
}]
|
35
|
+
}
|
36
|
+
response
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Fog
|
2
|
+
module DNS
|
3
|
+
class Dynect
|
4
|
+
class Real
|
5
|
+
# Get one or more node lists
|
6
|
+
#
|
7
|
+
# ==== Parameters
|
8
|
+
# * zone<~String> - zone to lookup node lists for
|
9
|
+
# * options<~Hash>
|
10
|
+
# * fqdn<~String> - fully qualified domain name of node to lookup
|
11
|
+
|
12
|
+
def get_all_records(zone, options = {})
|
13
|
+
requested_fqdn = options['fqdn'] || options[:fqdn]
|
14
|
+
request(
|
15
|
+
:expects => 200,
|
16
|
+
:idempotent => true,
|
17
|
+
:method => :get,
|
18
|
+
:path => ['AllRecord', zone, requested_fqdn].compact.join('/'),
|
19
|
+
:query => {'detail' => 'Y'} # return full records, instead of just resource URLs
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Mock
|
25
|
+
def get_all_records(zone, options = {})
|
26
|
+
raise Fog::DNS::Dynect::NotFound unless zone = self.data[:zones][zone]
|
27
|
+
|
28
|
+
response = Excon::Response.new
|
29
|
+
response.status = 200
|
30
|
+
|
31
|
+
data = [zone[:zone]]
|
32
|
+
|
33
|
+
if fqdn = options[:fqdn]
|
34
|
+
data = data | zone[:records].map { |type, records| records.select { |record| record[:fqdn] == fqdn } }.flatten.compact
|
35
|
+
else
|
36
|
+
data = data | zone[:records].map { |type, records| records.map { |record| record[:fqdn] } }.flatten
|
37
|
+
end
|
38
|
+
|
39
|
+
response.body = {
|
40
|
+
"status" => "success",
|
41
|
+
"data" => data,
|
42
|
+
"job_id" => Fog::Dynect::Mock.job_id,
|
43
|
+
"msgs" => [{
|
44
|
+
"INFO" => "get_tree: Here is your zone tree",
|
45
|
+
"SOURCE" => "BLL",
|
46
|
+
"ERR_CD" => nil,
|
47
|
+
"LVL" => "INFO"
|
48
|
+
}]
|
49
|
+
}
|
50
|
+
|
51
|
+
response
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Fog
|
2
|
+
module DNS
|
3
|
+
class Dynect
|
4
|
+
class Real
|
5
|
+
# Get one or more node lists
|
6
|
+
#
|
7
|
+
# ==== Parameters
|
8
|
+
# * zone<~String> - zone to lookup node lists for
|
9
|
+
# * options<~Hash>
|
10
|
+
# * fqdn<~String> - fully qualified domain name of node to lookup
|
11
|
+
|
12
|
+
def get_node_list(zone, options = {})
|
13
|
+
requested_fqdn = options['fqdn'] || options[:fqdn]
|
14
|
+
request(
|
15
|
+
:expects => 200,
|
16
|
+
:idempotent => true,
|
17
|
+
:method => :get,
|
18
|
+
:path => ['AllRecord', zone, requested_fqdn].compact.join('/')
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Mock
|
24
|
+
def get_node_list(zone, options = {})
|
25
|
+
raise Fog::DNS::Dynect::NotFound unless zone = self.data[:zones][zone]
|
26
|
+
|
27
|
+
response = Excon::Response.new
|
28
|
+
response.status = 200
|
29
|
+
|
30
|
+
data = [zone[:zone]]
|
31
|
+
|
32
|
+
if fqdn = options[:fqdn]
|
33
|
+
data = data | zone[:records].map { |type, records| records.select { |record| record[:fqdn] == fqdn } }.flatten.compact
|
34
|
+
else
|
35
|
+
data = data | zone[:records].map { |type, records| records.map { |record| record[:fqdn] } }.flatten
|
36
|
+
end
|
37
|
+
|
38
|
+
response.body = {
|
39
|
+
"status" => "success",
|
40
|
+
"data" => data,
|
41
|
+
"job_id" => Fog::Dynect::Mock.job_id,
|
42
|
+
"msgs" => [{
|
43
|
+
"INFO" => "get_tree: Here is your zone tree",
|
44
|
+
"SOURCE" => "BLL",
|
45
|
+
"ERR_CD" => nil,
|
46
|
+
"LVL" => "INFO"
|
47
|
+
}]
|
48
|
+
}
|
49
|
+
|
50
|
+
response
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Fog
|
2
|
+
module DNS
|
3
|
+
class Dynect
|
4
|
+
class Real
|
5
|
+
# List records of a given type
|
6
|
+
#
|
7
|
+
# ==== Parameters
|
8
|
+
# * type<~String> - type of record in ['AAAA', 'ANY', 'A', 'CNAME', 'DHCID', 'DNAME', 'DNSKEY', 'DS', 'KEY', 'LOC', 'MX', 'NSA', 'NS', 'PTR', 'PX', 'RP', 'SOA', 'SPF', 'SRV', 'SSHFP', 'TXT']
|
9
|
+
# * zone<~String> - name of zone to lookup
|
10
|
+
# * fqdn<~String> - name of fqdn to lookup
|
11
|
+
# * options<~Hash>:
|
12
|
+
# * record_id<~String> - id of record
|
13
|
+
|
14
|
+
def get_record(type, zone, fqdn, options = {})
|
15
|
+
request(
|
16
|
+
:expects => 200,
|
17
|
+
:idempotent => true,
|
18
|
+
:method => :get,
|
19
|
+
:path => ["#{type.to_s.upcase}Record", zone, fqdn, options['record_id']].compact.join('/')
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Mock
|
25
|
+
def get_record(type, zone, fqdn, options = {})
|
26
|
+
raise ArgumentError unless [
|
27
|
+
'AAAA', 'ANY', 'A', 'CNAME',
|
28
|
+
'DHCID', 'DNAME', 'DNSKEY',
|
29
|
+
'DS', 'KEY', 'LOC', 'MX',
|
30
|
+
'NSA', 'NS', 'PTR', 'PX',
|
31
|
+
'RP', 'SOA', 'SPF', 'SRV',
|
32
|
+
'SSHFP', 'TXT'
|
33
|
+
].include? type
|
34
|
+
raise Fog::DNS::Dynect::NotFound unless zone = self.data[:zones][zone]
|
35
|
+
|
36
|
+
response = Excon::Response.new
|
37
|
+
response.status = 200
|
38
|
+
|
39
|
+
if record_id = options['record_id']
|
40
|
+
raise Fog::DNS::Dynect::NotFound unless record = zone[:records][type].find { |record| record[:record_id] == record_id.to_i }
|
41
|
+
response.body = {
|
42
|
+
"status" => "success",
|
43
|
+
"data" => {
|
44
|
+
"zone" => record[:zone][:zone],
|
45
|
+
"ttl" => record[:ttl],
|
46
|
+
"fqdn" => record[:fqdn],
|
47
|
+
"record_type" => type,
|
48
|
+
"rdata" => record[:rdata],
|
49
|
+
"record_id" => record[:record_id]
|
50
|
+
},
|
51
|
+
"job_id" => Fog::Dynect::Mock.job_id,
|
52
|
+
"msgs" => [{
|
53
|
+
"INFO" => "get: Found the record",
|
54
|
+
"SOURCE" => "API-B",
|
55
|
+
"ERR_CD" => nil,
|
56
|
+
"LVL" => "INFO"
|
57
|
+
}]
|
58
|
+
}
|
59
|
+
else
|
60
|
+
records = if type == "ANY"
|
61
|
+
zone[:records].values.flatten.select { |record| record[:fqdn] == fqdn }
|
62
|
+
else
|
63
|
+
zone[:records][type].select { |record| record[:fqdn] == fqdn }
|
64
|
+
end
|
65
|
+
response.body = {
|
66
|
+
"status" => "success",
|
67
|
+
"data" => records.map { |record| "/REST/#{record[:type]}Record/#{record[:zone][:zone]}/#{record[:fqdn]}/#{record[:record_id]}" },
|
68
|
+
"job_id" => Fog::Dynect::Mock.job_id,
|
69
|
+
"msgs" => [{
|
70
|
+
"INFO" => "detail: Found #{records.size} record",
|
71
|
+
"SOURCE" => "BLL",
|
72
|
+
"ERR_CD" => nil,
|
73
|
+
"LVL" => "INFO"
|
74
|
+
}]
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
response
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Fog
|
2
|
+
module DNS
|
3
|
+
class Dynect
|
4
|
+
class Real
|
5
|
+
# Get one or more zones
|
6
|
+
#
|
7
|
+
# ==== Parameters
|
8
|
+
# * options<~Hash>:
|
9
|
+
# * zone<~String> - name of zone to lookup, or omit to return list of zones
|
10
|
+
|
11
|
+
def get_zone(options = {})
|
12
|
+
request(
|
13
|
+
:expects => 200,
|
14
|
+
:idempotent => true,
|
15
|
+
:method => :get,
|
16
|
+
:path => ['Zone', options['zone']].compact.join('/')
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Mock
|
22
|
+
def get_zone(options = {})
|
23
|
+
if options['zone']
|
24
|
+
raise Fog::DNS::Dynect::NotFound unless zone = self.data[:zones][options['zone']]
|
25
|
+
data = {
|
26
|
+
"zone_type" => zone[:zone_type],
|
27
|
+
"serial_style" => zone[:serial_style],
|
28
|
+
"serial" => zone[:serial],
|
29
|
+
"zone" => zone[:zone]
|
30
|
+
}
|
31
|
+
info = "get: Your zone, #{zone[:zone]}"
|
32
|
+
else
|
33
|
+
data = self.data[:zones].map { |zone, data| "/REST/Zone/#{zone}/" }
|
34
|
+
info = "get: Your #{data.size} zones"
|
35
|
+
end
|
36
|
+
|
37
|
+
response = Excon::Response.new
|
38
|
+
response.status = 200
|
39
|
+
|
40
|
+
response.body = {
|
41
|
+
"status" => "success",
|
42
|
+
"data" => data,
|
43
|
+
"job_id" => Fog::Dynect::Mock.job_id,
|
44
|
+
"msgs" => [{
|
45
|
+
"INFO" => info,
|
46
|
+
"SOURCE" => "BLL",
|
47
|
+
"ERR_CD" => nil,
|
48
|
+
"LVL" => "INFO"
|
49
|
+
}]
|
50
|
+
}
|
51
|
+
|
52
|
+
response
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|