From 4a2da72eabcfeeae6e03c38f094a42b60e82795e Mon Sep 17 00:00:00 2001 From: geemus Date: Thu, 14 Jul 2011 19:22:43 -0500 Subject: [PATCH] [dns|dynect] cleanup of initial implementation --- lib/fog/bin.rb | 4 +- lib/fog/bin/dynect.rb | 2 +- lib/fog/dns.rb | 6 +- lib/fog/dns/dynect.rb | 45 +++--- lib/fog/dns/models/dynect/record.rb | 59 ++++++-- lib/fog/dns/models/dynect/records.rb | 42 ++--- lib/fog/dns/models/dynect/zone.rb | 40 ++++- lib/fog/dns/models/dynect/zones.rb | 20 +-- lib/fog/dns/parsers/dynect/anyrecord.rb | 25 --- lib/fog/dns/parsers/dynect/anyrecords.rb | 29 ---- lib/fog/dns/parsers/dynect/node_list.rb | 23 --- lib/fog/dns/parsers/dynect/session.rb | 25 --- lib/fog/dns/parsers/dynect/zone.rb | 25 --- lib/fog/dns/parsers/dynect/zones.rb | 23 --- lib/fog/dns/requests/dynect/delete_record.rb | 24 +++ lib/fog/dns/requests/dynect/delete_zone.rb | 21 +++ lib/fog/dns/requests/dynect/get_node_list.rb | 23 +++ lib/fog/dns/requests/dynect/get_record.rb | 25 +++ lib/fog/dns/requests/dynect/get_zone.rb | 48 ++---- .../dns/requests/dynect/list_any_records.rb | 59 -------- lib/fog/dns/requests/dynect/list_zones.rb | 33 ---- lib/fog/dns/requests/dynect/node_list.rb | 31 ---- lib/fog/dns/requests/dynect/post_record.rb | 27 ++++ lib/fog/dns/requests/dynect/post_session.rb | 36 +++++ lib/fog/dns/requests/dynect/post_zone.rb | 32 ++++ lib/fog/dns/requests/dynect/put_zone.rb | 26 ++++ lib/fog/dns/requests/dynect/session.rb | 42 ----- lib/fog/providers.rb | 2 +- tests/dns/helper.rb | 9 +- tests/dns/models/record_tests.rb | 5 +- tests/dns/models/records_tests.rb | 4 +- tests/dns/models/zone_tests.rb | 4 +- tests/dns/models/zones_tests.rb | 2 +- tests/dns/requests/dynect/dns_tests.rb | 143 ++++++++++++++---- 34 files changed, 492 insertions(+), 472 deletions(-) delete mode 100644 lib/fog/dns/parsers/dynect/anyrecord.rb delete mode 100644 lib/fog/dns/parsers/dynect/anyrecords.rb delete mode 100644 lib/fog/dns/parsers/dynect/node_list.rb delete mode 100644 lib/fog/dns/parsers/dynect/session.rb delete mode 100644 lib/fog/dns/parsers/dynect/zone.rb delete mode 100644 lib/fog/dns/parsers/dynect/zones.rb create mode 100644 lib/fog/dns/requests/dynect/delete_record.rb create mode 100644 lib/fog/dns/requests/dynect/delete_zone.rb create mode 100644 lib/fog/dns/requests/dynect/get_node_list.rb create mode 100644 lib/fog/dns/requests/dynect/get_record.rb delete mode 100644 lib/fog/dns/requests/dynect/list_any_records.rb delete mode 100644 lib/fog/dns/requests/dynect/list_zones.rb delete mode 100644 lib/fog/dns/requests/dynect/node_list.rb create mode 100644 lib/fog/dns/requests/dynect/post_record.rb create mode 100644 lib/fog/dns/requests/dynect/post_session.rb create mode 100644 lib/fog/dns/requests/dynect/post_zone.rb create mode 100644 lib/fog/dns/requests/dynect/put_zone.rb delete mode 100644 lib/fog/dns/requests/dynect/session.rb diff --git a/lib/fog/bin.rb b/lib/fog/bin.rb index 13db0f179..3d0e88f21 100644 --- a/lib/fog/bin.rb +++ b/lib/fog/bin.rb @@ -4,7 +4,7 @@ module Fog class << self def available_providers - @providers.select {|provider| Kernel.const_get(provider).available?} + @available_providers ||= @providers.select {|provider| Kernel.const_get(provider).available?}.sort end end @@ -58,6 +58,7 @@ require 'fog/bin/bluebox' require 'fog/bin/brightbox' require 'fog/bin/dnsimple' require 'fog/bin/dnsmadeeasy' +require 'fog/bin/dynect' require 'fog/bin/ecloud' require 'fog/bin/go_grid' require 'fog/bin/google' @@ -73,4 +74,3 @@ require 'fog/bin/vcloud' require 'fog/bin/virtual_box' require 'fog/bin/voxel' require 'fog/bin/zerigo' -require 'fog/bin/dynect' diff --git a/lib/fog/bin/dynect.rb b/lib/fog/bin/dynect.rb index 4c15f8818..110b52444 100644 --- a/lib/fog/bin/dynect.rb +++ b/lib/fog/bin/dynect.rb @@ -4,7 +4,7 @@ class Dynect < Fog::Bin def class_for(key) case key when :dns - Fog::Dynect::DNS + Fog::DNS::Dynect else raise ArgumentError, "Unrecognized service: #{key}" end diff --git a/lib/fog/dns.rb b/lib/fog/dns.rb index 2d9e42a12..76f29fe5d 100644 --- a/lib/fog/dns.rb +++ b/lib/fog/dns.rb @@ -20,6 +20,9 @@ module Fog when :dnsmadeeasy require 'fog/dns/dnsmadeeasy' Fog::DNS::DNSMadeEasy.new(attributes) + when :dynect + require 'fog/dns/dynect' + Fog::DNS::Dynect.new(attributes) when :linode require 'fog/dns/linode' Fog::DNS::Linode.new(attributes) @@ -29,9 +32,6 @@ module Fog when :zerigo require 'fog/dns/zerigo' Fog::DNS::Zerigo.new(attributes) - when 'Dynect' - require 'fog/dns/dynect' - Fog::Dynect::DNS.new(attributes) else raise ArgumentError.new("#{provider} is not a recognized dns provider") end diff --git a/lib/fog/dns/dynect.rb b/lib/fog/dns/dynect.rb index 6f7ba25e8..f110e8d88 100644 --- a/lib/fog/dns/dynect.rb +++ b/lib/fog/dns/dynect.rb @@ -1,6 +1,6 @@ module Fog - module Dynect - class DNS < Fog::Service + module DNS + class Dynect < Fog::Service requires :dynect_customer, :dynect_username, :dynect_password recognizes :timeout, :persistent @@ -13,15 +13,22 @@ module Fog collection :zones request_path 'fog/dns/requests/dynect' - request :session - request :list_zones + request :delete_record + request :delete_zone + request :get_node_list + request :get_record request :get_zone - request :list_any_records - request :node_list + request :post_record + request :post_session + request :post_zone + request :put_zone + + class Mock + end class Real def initialize(options={}) - require 'builder' + require 'multi_json' @dynect_customer = options[:dynect_customer] @dynect_username = options[:dynect_username] @@ -36,18 +43,23 @@ module Fog end def auth_token - @auth_token ||= session.body['Auth-Token'] + @auth_token ||= post_session.body['data']['token'] end def request(params) begin params[:headers] ||= {} - params[:headers]['Content-Type'] = 'text/xml' + params[:headers]['Content-Type'] = 'application/json' params[:headers]['API-Version'] = @version params[:headers]['Auth-Token'] = auth_token unless params[:path] == "Session" params[:path] = "#{@path}/#{params[:path]}" response = @connection.request(params.merge!({:host => @host})) - response = handle_redirect(response) if response.status == 307 + + unless response.body.empty? + response.body = MultiJson.decode(response.body) + end + response + rescue Excon::Errors::HTTPStatusError => error raise error end @@ -56,19 +68,6 @@ module Fog end end - def handle_redirect(response) - raise request({ - :expects => 200, - :method => "GET", - :path => response.body - }) - - - end - - # class Mock - # end - end end end diff --git a/lib/fog/dns/models/dynect/record.rb b/lib/fog/dns/models/dynect/record.rb index 9f0965f90..7478d207f 100644 --- a/lib/fog/dns/models/dynect/record.rb +++ b/lib/fog/dns/models/dynect/record.rb @@ -1,28 +1,65 @@ require 'fog/core/model' module Fog - module Dynect - class DNS + module DNS + class Dynect class Record < Fog::Model extend Fog::Deprecation - deprecate :ip, :value - deprecate :ip=, :value= - identity :id, :aliases => "record_id" - attribute :name, :aliases => "fqdn" - attribute :value, :aliases => "rdata" + identity :id + attribute :name, :aliases => [:fqdn, 'fqdn'] + attribute :rdata + attribute :serial_style attribute :ttl - attribute :zone_id, :aliases => "zone" - attribute :type, :aliases => "record_type" + attribute :type, :aliases => 'record_type' + attribute :value def destroy - raise 'destroy not implemented' + requires :identity, :name, :type, :zone + connection.delete_record(type, zone.identity, name, identity) + true end def save - raise 'save not implemented' + requires :name, :type, :value, :zone + + options = { + :ttl => ttl + } + options.delete_if {|key, value| value.nil?} + + data = connection.post_record(type, zone.identity, name, {'address' => value}, options).body['data'] + # avoid overwriting zone object with zone string + data = data.reject {|key, value| key == 'zone'} + merge_attributes(data) + + zone.publish + records = connection.get_record(type, zone.identity, name).body['data'] + # data in format ['/REST/xRecord/domain/fqdn/identity] + records.map! do |record| + tokens = record.split('/') + { + :identity => tokens.last, + :type => tokens[2][0...-6] # everything before 'Record' + } + end + record = records.detect {|record| record[:type] == type} + merge_attributes(record) + + true end + + def zone + @zone + end + + private + + def zone=(new_zone) + @zone = new_zone + end + end end diff --git a/lib/fog/dns/models/dynect/records.rb b/lib/fog/dns/models/dynect/records.rb index 67afcc53e..900f6a092 100644 --- a/lib/fog/dns/models/dynect/records.rb +++ b/lib/fog/dns/models/dynect/records.rb @@ -2,30 +2,43 @@ require 'fog/core/collection' require 'fog/dns/models/dynect/record' module Fog - module Dynect - class DNS + module DNS + class Dynect class Records < Fog::Collection attribute :zone - model Fog::Dynect::DNS::Record + model Fog::DNS::Dynect::Record - def all(filter=nil) - selected_nodes = nodes - selected_nodes = nodes.select do |node| - node =~ /#{Regexp.escape(filter)}$/ - end if filter + def all + requires :zone + data = [] + connection.get_node_list(zone.domain).body['data'].each do |fqdn| + records = connection.get_record('ANY', zone.domain, fqdn).body['data'] - data = selected_nodes.inject([]) do |m, node| - m += connection.list_any_records(zone.id, node).map(&:body) - m + # data in format ['/REST/xRecord/domain/fqdn/identity] + records.map! do |record| + tokens = record.split('/') + { + :identity => tokens.last, + :fqdn => fqdn, + :type => tokens[2][0...-6] # everything before 'Record' + } + end + + data.concat(records) end + # leave out the default, read only records + data = data.reject {|record| ['NS', 'SOA'].include?(record[:type])} + load(data) end def get(record_id) + # FIXME: can this be done more efficiently? + all.detect {|record| record.identity == record_id} end def new(attributes = {}) @@ -33,13 +46,6 @@ module Fog super({ :zone => zone }.merge!(attributes)) end - private - - def nodes - requires :zone - Array(connection.node_list(zone.id).body) - end - end end diff --git a/lib/fog/dns/models/dynect/zone.rb b/lib/fog/dns/models/dynect/zone.rb index afeff966b..c9a6bf204 100644 --- a/lib/fog/dns/models/dynect/zone.rb +++ b/lib/fog/dns/models/dynect/zone.rb @@ -2,22 +2,44 @@ require 'fog/core/model' require 'fog/dns/models/dynect/records' module Fog - module Dynect - class DNS + module DNS + class Dynect class Zone < Fog::Model - identity :id, :aliases => "zone" + identity :domain + + attribute :domain, :aliases => 'zone' + attribute :email, :aliases => 'rname' attribute :serial - attribute :zone_type attribute :serial_style + attribute :ttl + attribute :type, :aliases => 'zone_type' + + def initialize(attributes={}) + self.ttl ||= 3600 + super + end def destroy - raise 'destroy Not Implemented' + requires :domain + connection.delete_zone(domain) + true + end + + undef_method :domain= + def domain=(new_domain) + attributes[:domain] = new_domain.split('/').last + end + + def publish + requires :identity + data = connection.put_zone(identity, :publish => true) + true end def records - @records ||= Fog::Dynect::DNS::Records.new(:zone => self, :connection => connection) + @records ||= Fog::DNS::Dynect::Records.new(:zone => self, :connection => connection) end def nameservers @@ -25,8 +47,10 @@ module Fog end def save - #raise 'Not Implemented' - 'dynect save' + requires :domain, :email, :ttl + data = connection.post_zone(email, ttl, domain).body['data'] + merge_attributes(data) + true end end diff --git a/lib/fog/dns/models/dynect/zones.rb b/lib/fog/dns/models/dynect/zones.rb index 3eed7805e..b922ea5aa 100644 --- a/lib/fog/dns/models/dynect/zones.rb +++ b/lib/fog/dns/models/dynect/zones.rb @@ -2,24 +2,24 @@ require 'fog/core/collection' require 'fog/dns/models/dynect/zone' module Fog - module Dynect - class DNS + module DNS + class Dynect class Zones < Fog::Collection - model Fog::Dynect::DNS::Zone + model Fog::DNS::Dynect::Zone def all - zone_names = connection.list_zones.body["zones"] - load(zone_names.map {|name| - { - "id" => name - } - }) + data = connection.get_zone.body['data'].map do |zone| + { :domain => zone } + end + load(data) end def get(zone_id) - new(connection.get_zone(zone_id).body) + new(connection.get_zone('zone' => zone_id).body['data']) + rescue Excon::Errors::NotFound + nil end end diff --git a/lib/fog/dns/parsers/dynect/anyrecord.rb b/lib/fog/dns/parsers/dynect/anyrecord.rb deleted file mode 100644 index dd6310a9c..000000000 --- a/lib/fog/dns/parsers/dynect/anyrecord.rb +++ /dev/null @@ -1,25 +0,0 @@ -module Fog - module Parsers - module Dynect - module DNS - - class AnyRecord < Fog::Parsers::Base - - def reset - @response = {} - end - - def end_element(name) - case name - when 'zone', 'fqdn', 'record_type', 'record_id', 'rdata', 'address', 'txtdata' - @response[name] = @value - when 'ttl' - @response[name] = @value.to_i - end - end - - end - end - end - end -end diff --git a/lib/fog/dns/parsers/dynect/anyrecords.rb b/lib/fog/dns/parsers/dynect/anyrecords.rb deleted file mode 100644 index 1a7c23064..000000000 --- a/lib/fog/dns/parsers/dynect/anyrecords.rb +++ /dev/null @@ -1,29 +0,0 @@ -module Fog - module Parsers - module Dynect - module DNS - - class AnyRecords < Fog::Parsers::Base - - def reset - @response = [] - end - - def end_element(name) - case name - when /.+RecordURI$/ - matches = @value.match(/\/REST\/(.+)Record\/(.+)\/(.+)\/(.+)/).to_a - _, record_type, zone, fqdn, recordid = matches - - @response << ({"zone" => zone, - "fqdn" => fqdn, - "recordid" => recordid, - "record_type" => record_type}) - end - end - - end - end - end - end -end diff --git a/lib/fog/dns/parsers/dynect/node_list.rb b/lib/fog/dns/parsers/dynect/node_list.rb deleted file mode 100644 index 813a75455..000000000 --- a/lib/fog/dns/parsers/dynect/node_list.rb +++ /dev/null @@ -1,23 +0,0 @@ -module Fog - module Parsers - module Dynect - module DNS - - class NodeList < Fog::Parsers::Base - - def reset - @response = [] - end - - def end_element(name) - case name - when 'item' - @response << @value unless @value == "INFO" - end - end - - end - end - end - end -end diff --git a/lib/fog/dns/parsers/dynect/session.rb b/lib/fog/dns/parsers/dynect/session.rb deleted file mode 100644 index fd5b72de5..000000000 --- a/lib/fog/dns/parsers/dynect/session.rb +++ /dev/null @@ -1,25 +0,0 @@ -module Fog - module Parsers - module Dynect - module DNS - - class Session < Fog::Parsers::Base - - def reset - @response = {} - end - - def end_element(name) - case name - when 'token' - @response['Auth-Token'] = @value - when 'version' - @response['API-Version'] = @value - end - end - - end - end - end - end -end diff --git a/lib/fog/dns/parsers/dynect/zone.rb b/lib/fog/dns/parsers/dynect/zone.rb deleted file mode 100644 index e0fa5ecce..000000000 --- a/lib/fog/dns/parsers/dynect/zone.rb +++ /dev/null @@ -1,25 +0,0 @@ -module Fog - module Parsers - module Dynect - module DNS - - class Zone < Fog::Parsers::Base - - def reset - @response = {} - end - - def end_element(name) - case name - when 'zone', 'zone_type', 'serial_style' - @response[name] = @value - when 'serial' - @response['serial'] = @value.to_i - end - end - - end - end - end - end -end diff --git a/lib/fog/dns/parsers/dynect/zones.rb b/lib/fog/dns/parsers/dynect/zones.rb deleted file mode 100644 index 298782257..000000000 --- a/lib/fog/dns/parsers/dynect/zones.rb +++ /dev/null @@ -1,23 +0,0 @@ -module Fog - module Parsers - module Dynect - module DNS - - class Zones < Fog::Parsers::Base - - def reset - @response = {"zones" => []} - end - - def end_element(name) - case name - when 'ZoneURI' - @response['zones'] << @value.match(/\/REST\/Zone\/(.+)\//)[1] - end - end - - end - end - end - end -end diff --git a/lib/fog/dns/requests/dynect/delete_record.rb b/lib/fog/dns/requests/dynect/delete_record.rb new file mode 100644 index 000000000..824e35d7c --- /dev/null +++ b/lib/fog/dns/requests/dynect/delete_record.rb @@ -0,0 +1,24 @@ +module Fog + module DNS + class Dynect + class Real + + # Delete a record + # + # ==== Parameters + # * 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'] + # * zone<~String> - zone of record + # * fqdn<~String> - fqdn of record + # * record_id<~String> - id of record + + def delete_record(type, zone, fqdn, record_id) + request( + :expects => 200, + :method => :delete, + :path => ["#{type.to_s.upcase}Record", zone, fqdn, record_id].join('/') + ) + end + end + end + end +end diff --git a/lib/fog/dns/requests/dynect/delete_zone.rb b/lib/fog/dns/requests/dynect/delete_zone.rb new file mode 100644 index 000000000..8a8968d99 --- /dev/null +++ b/lib/fog/dns/requests/dynect/delete_zone.rb @@ -0,0 +1,21 @@ +module Fog + module DNS + class Dynect + class Real + + # Delete a zone + # + # ==== Parameters + # * zone<~String> - zone to host + + def delete_zone(zone) + request( + :expects => 200, + :method => :delete, + :path => "Zone/#{zone}" + ) + end + end + end + end +end diff --git a/lib/fog/dns/requests/dynect/get_node_list.rb b/lib/fog/dns/requests/dynect/get_node_list.rb new file mode 100644 index 000000000..07192dc3d --- /dev/null +++ b/lib/fog/dns/requests/dynect/get_node_list.rb @@ -0,0 +1,23 @@ +module Fog + module DNS + class Dynect + class Real + + # Get one or more node lists + # + # ==== Parameters + # * zone<~String> - zone to lookup node lists for + # * options<~Hash> + # * fqdn<~String> - fully qualified domain name of node to lookup + + def get_node_list(zone, options = {}) + request( + :expects => 200, + :method => :get, + :path => ['NodeList', zone, options['fqdn']].compact.join('/') + ) + end + end + end + end +end diff --git a/lib/fog/dns/requests/dynect/get_record.rb b/lib/fog/dns/requests/dynect/get_record.rb new file mode 100644 index 000000000..e4dc932a8 --- /dev/null +++ b/lib/fog/dns/requests/dynect/get_record.rb @@ -0,0 +1,25 @@ +module Fog + module DNS + class Dynect + class Real + + # List records of a given type + # + # ==== Parameters + # * 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'] + # * zone<~String> - name of zone to lookup + # * fqdn<~String> - name of fqdn to lookup + # * options<~Hash>: + # * record_id<~String> - id of record + + def get_record(type, zone, fqdn, options = {}) + request( + :expects => 200, + :method => :get, + :path => ["#{type.to_s.upcase}Record", zone, fqdn, options['record_id']].compact.join('/') + ) + end + end + end + end +end diff --git a/lib/fog/dns/requests/dynect/get_zone.rb b/lib/fog/dns/requests/dynect/get_zone.rb index 750e7fc9a..282201820 100644 --- a/lib/fog/dns/requests/dynect/get_zone.rb +++ b/lib/fog/dns/requests/dynect/get_zone.rb @@ -1,48 +1,22 @@ module Fog - module Dynect - class DNS + module DNS + class Dynect class Real - require 'fog/dns/parsers/dynect/zone' - - # GET information for the given zone - # ==== Parameters - # * name<~String> - zone name (ie example.com) + # Get one or more zones # - # ==== Returns - # * response<~Excon::Response>: - # * body<~Hash>: - # * 'zone_type'<~String> - # * 'serial_style'<~String> - # * 'serial'<~Integer> - # * 'zone'<~String> + # ==== Parameters + # * options<~Hash>: + # * zone<~String> - name of zone to lookup, or omit to return list of zones - def get_zone(zone_name) + def get_zone(options = {}) request( - :parser => Fog::Parsers::Dynect::DNS::Zone.new, - :expects => 200, - :method => "GET", - :path => "Zone/#{zone_name}/", - ) + :expects => 200, + :method => :get, + :path => ['Zone', options['zone']].compact.join('/') + ) end end - - class Mock - - def get_zone(zone_name) - response = Excon::Response.new - response.status = 200 - response.body = { - "zone" => "example.com", - "serial" => 100, - "zone_type" => "Primary", - "serial_type" => "increment" - } - response - end - - end - end end end diff --git a/lib/fog/dns/requests/dynect/list_any_records.rb b/lib/fog/dns/requests/dynect/list_any_records.rb deleted file mode 100644 index 3573b355e..000000000 --- a/lib/fog/dns/requests/dynect/list_any_records.rb +++ /dev/null @@ -1,59 +0,0 @@ -module Fog - module Dynect - class DNS - class Real - - require 'fog/dns/parsers/dynect/anyrecords' - require 'fog/dns/parsers/dynect/anyrecord' - - # Get the list of records for the specific domain. - # - # ==== Parameters - # * domain<~String> - # ==== Returns - # * response<~Excon::Response>: - # * records - # * fqdn<~String> - # * address<~String> - # * record_type<~String> - # * ttl<~Integer> - # * zone<~String> - def list_any_records(zone, fqdn) - all_records = request( - :parser => Fog::Parsers::Dynect::DNS::AnyRecords.new, - :expects => [200, 307], - :method => "GET", - :path => "ANYRecord/#{zone}/#{fqdn}", - ) - - all_records.body.inject([]) do |results, record| - results << request( - :parser => Fog::Parsers::Dynect::DNS::AnyRecord.new, - :expects => [200, 307], - :method => "GET", - :path => "#{record['record_type']}Record/#{record['zone']}/#{record['fqdn']}/#{record['recordid']}", - ) - results - end - end - end - - class Mock - - def list_any_records - response = Excon::Response.new - response.body = [{ - "fqdn" => "example.com", - "address" => "127.0.0.1", - "zone" => "example.com", - "record_type" => "A", - "ttl" => 30 - }] - response - end - - end - - end - end -end diff --git a/lib/fog/dns/requests/dynect/list_zones.rb b/lib/fog/dns/requests/dynect/list_zones.rb deleted file mode 100644 index 27d84e108..000000000 --- a/lib/fog/dns/requests/dynect/list_zones.rb +++ /dev/null @@ -1,33 +0,0 @@ -module Fog - module Dynect - class DNS - class Real - - require 'fog/dns/parsers/dynect/zones' - - def list_zones - request( - :parser => Fog::Parsers::Dynect::DNS::Zones.new, - :expects => 200, - :method => "GET", - :path => "Zone", - ) - end - end - - class Mock - - def list_zones - response = Excon::Response.new - response.status = 200 - response.body = { - "zones" => ["example.com"] - } - response - end - - end - - end - end -end diff --git a/lib/fog/dns/requests/dynect/node_list.rb b/lib/fog/dns/requests/dynect/node_list.rb deleted file mode 100644 index af153a7e8..000000000 --- a/lib/fog/dns/requests/dynect/node_list.rb +++ /dev/null @@ -1,31 +0,0 @@ -module Fog - module Dynect - class DNS - class Real - - require 'fog/dns/parsers/dynect/node_list' - - def node_list(zone) - request( - :parser => Fog::Parsers::Dynect::DNS::NodeList.new, - :expects => 200, - :method => "GET", - :path => "NodeList/#{zone}", - ) - end - end - - class Mock - - def node_list(zone) - response = Excon::Response.new - response.status = 200 - response.body = [zone] - response - end - - end - - end - end -end diff --git a/lib/fog/dns/requests/dynect/post_record.rb b/lib/fog/dns/requests/dynect/post_record.rb new file mode 100644 index 000000000..b234e31f3 --- /dev/null +++ b/lib/fog/dns/requests/dynect/post_record.rb @@ -0,0 +1,27 @@ +module Fog + module DNS + class Dynect + class Real + + # Create a record + # + # ==== Parameters + # * 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'] + # * zone<~String> - zone of record + # * rdata<~Hash> - rdata for record + # * options<~Hash>: (options vary by type, listing below includes common parameters) + # * ttl<~Integer> - ttl for the record, defaults to zone ttl + + def post_record(type, zone, fqdn, rdata, options = {}) + options.merge!('rdata' => rdata) + request( + :body => MultiJson.encode(options), + :expects => 200, + :method => :post, + :path => ["#{type.to_s.upcase}Record", zone, fqdn].join('/') + ) + end + end + end + end +end diff --git a/lib/fog/dns/requests/dynect/post_session.rb b/lib/fog/dns/requests/dynect/post_session.rb new file mode 100644 index 000000000..828ddf947 --- /dev/null +++ b/lib/fog/dns/requests/dynect/post_session.rb @@ -0,0 +1,36 @@ +module Fog + module DNS + class Dynect + class Real + + def post_session + request( + :expects => 200, + :method => :post, + :path => "Session", + :body => MultiJson.encode({ + :customer_name => @dynect_customer, + :user_name => @dynect_username, + :password => @dynect_password + }) + ) + end + end + + class Mock + + def post_session + response = Excon::Response.new + response.status = 200 + response.body = { + 'API-Version' => '2.3.1', + 'Auth-Token' => 'thetoken==' + } + response + end + + end + + end + end +end diff --git a/lib/fog/dns/requests/dynect/post_zone.rb b/lib/fog/dns/requests/dynect/post_zone.rb new file mode 100644 index 000000000..b8090721c --- /dev/null +++ b/lib/fog/dns/requests/dynect/post_zone.rb @@ -0,0 +1,32 @@ +module Fog + module DNS + class Dynect + class Real + + # Create a zone + # + # ==== Parameters + # * rname<~String> - administrative contact + # * ttl<~Integer> - time to live (in seconds) for records in this zone + # * zone<~String> - name of zone to host + # * options<~Hash>: + # * serial_style<~String> - style of serial number, in ['day', 'epoch', 'increment', 'minute']. Defaults to increment + + def post_zone(rname, ttl, zone, options = {}) + body = MultiJson.encode({ + :rname => rname, + :token => auth_token, + :ttl => ttl + }.merge!(options)) + + request( + :body => body, + :expects => 200, + :method => :post, + :path => 'Zone/' << zone + ) + end + end + end + end +end diff --git a/lib/fog/dns/requests/dynect/put_zone.rb b/lib/fog/dns/requests/dynect/put_zone.rb new file mode 100644 index 000000000..78ff7aefe --- /dev/null +++ b/lib/fog/dns/requests/dynect/put_zone.rb @@ -0,0 +1,26 @@ +module Fog + module DNS + class Dynect + class Real + + # Update a zone + # + # ==== Parameters + # * zone<~String> - name or id of zone + # * options<~Hash>: + # * freeze<~Boolean> - causes zone to become frozen + # * publish<~Boolean> - causes all pending changes to be pushed to nameservers + # * thaw<~Boolean> - causes zone to cease being frozen + + def put_zone(zone, options = {}) + request( + :body => MultiJson.encode(options), + :expects => 200, + :method => :put, + :path => 'Zone/' << zone + ) + end + end + end + end +end diff --git a/lib/fog/dns/requests/dynect/session.rb b/lib/fog/dns/requests/dynect/session.rb deleted file mode 100644 index 7bf30247e..000000000 --- a/lib/fog/dns/requests/dynect/session.rb +++ /dev/null @@ -1,42 +0,0 @@ -module Fog - module Dynect - class DNS - class Real - - require 'fog/dns/parsers/dynect/session' - - def session - builder = Builder::XmlMarkup.new - xml = builder.parameters do |root| - root.customer_name(@dynect_customer) - root.user_name( @dynect_username) - root.password(@dynect_password) - end - - request( - :parser => Fog::Parsers::Dynect::DNS::Session.new, - :expects => 200, - :method => "POST", - :path => "Session", - :body => xml - ) - end - end - - class Mock - - def session - response = Excon::Response.new - response.status = 200 - response.body = { - 'API-Version' => '2.3.1', - 'Auth-Token' => 'thetoken==' - } - response - end - - end - - end - end -end diff --git a/lib/fog/providers.rb b/lib/fog/providers.rb index 496e638e6..22809ba6a 100644 --- a/lib/fog/providers.rb +++ b/lib/fog/providers.rb @@ -11,6 +11,7 @@ require 'fog/providers/bluebox' require 'fog/providers/brightbox' require 'fog/providers/dnsimple' require 'fog/providers/dnsmadeeasy' +require 'fog/providers/dynect' require 'fog/providers/ecloud' require 'fog/providers/go_grid' require 'fog/providers/google' @@ -25,4 +26,3 @@ require 'fog/providers/vcloud' require 'fog/providers/virtual_box' require 'fog/providers/voxel' require 'fog/providers/zerigo' -require 'fog/providers/dynect' diff --git a/tests/dns/helper.rb b/tests/dns/helper.rb index 4ab2f8656..d31337eeb 100644 --- a/tests/dns/helper.rb +++ b/tests/dns/helper.rb @@ -15,6 +15,12 @@ def dns_providers :dnsmadeeasy => { :mocked => false }, + :dynect => { + :mocked => false, + :zone_attributes => { + :email => 'fog@example.com' + } + }, :linode => { :mocked => false, :zone_attributes => { @@ -26,9 +32,6 @@ def dns_providers }, :zerigo => { :mocked => false - }, - Dynect => { - :mocked => false } } end diff --git a/tests/dns/models/record_tests.rb b/tests/dns/models/record_tests.rb index 8bef12506..791a3db1e 100644 --- a/tests/dns/models/record_tests.rb +++ b/tests/dns/models/record_tests.rb @@ -3,7 +3,7 @@ for provider, config in dns_providers # FIXME: delay/timing breaks things :( next if [:dnsmadeeasy].include?(provider) - Shindo.tests("Fog::DNS[:#{provider}] | record", [provider]) do + Shindo.tests("Fog::DNS[:#{provider}] | record", [provider.to_s]) do record_attributes = { :name => 'www.fogrecordtests.com', @@ -17,6 +17,7 @@ for provider, config in dns_providers }.merge(config[:zone_attributes] || {}) @zone = Fog::DNS[provider].zones.create(zone_attributes) + model_tests(@zone.records, record_attributes, config[:mocked]) @zone.destroy @@ -24,4 +25,4 @@ for provider, config in dns_providers end -end \ No newline at end of file +end diff --git a/tests/dns/models/records_tests.rb b/tests/dns/models/records_tests.rb index 2c77f828b..a44e192f1 100644 --- a/tests/dns/models/records_tests.rb +++ b/tests/dns/models/records_tests.rb @@ -3,7 +3,7 @@ for provider, config in dns_providers # FIXME: delay/timing breaks things :( next if [:dnsmadeeasy].include?(provider) - Shindo.tests("Fog::DNS[:#{provider}] | records", [provider]) do + Shindo.tests("Fog::DNS[:#{provider}] | records", [provider.to_s]) do record_attributes = { :name => 'www.fogrecordstests.com', @@ -25,4 +25,4 @@ for provider, config in dns_providers end -end \ No newline at end of file +end diff --git a/tests/dns/models/zone_tests.rb b/tests/dns/models/zone_tests.rb index a055455ab..364b24368 100644 --- a/tests/dns/models/zone_tests.rb +++ b/tests/dns/models/zone_tests.rb @@ -3,7 +3,7 @@ for provider, config in dns_providers # FIXME: delay/timing breaks things :( next if [:dnsmadeeasy].include?(provider) - Shindo.tests("Fog::DNS[:#{provider}] | zone", [provider]) do + Shindo.tests("Fog::DNS[:#{provider}] | zone", [provider.to_s]) do zone_attributes = { :domain => 'fogzonetests.com' @@ -13,4 +13,4 @@ for provider, config in dns_providers end -end \ No newline at end of file +end diff --git a/tests/dns/models/zones_tests.rb b/tests/dns/models/zones_tests.rb index f6674057c..867403e6b 100644 --- a/tests/dns/models/zones_tests.rb +++ b/tests/dns/models/zones_tests.rb @@ -3,7 +3,7 @@ for provider, config in dns_providers # FIXME: delay/timing breaks things :( next if [:dnsmadeeasy].include?(provider) - Shindo.tests("Fog::DNS[:#{provider}] | zones", [provider]) do + Shindo.tests("Fog::DNS[:#{provider}] | zones", [provider.to_s]) do zone_attributes = { :domain => 'fogzonestests.com' diff --git a/tests/dns/requests/dynect/dns_tests.rb b/tests/dns/requests/dynect/dns_tests.rb index 7d2a80284..9199aa4fe 100644 --- a/tests/dns/requests/dynect/dns_tests.rb +++ b/tests/dns/requests/dynect/dns_tests.rb @@ -1,53 +1,130 @@ Shindo.tests('Dynect::dns | DNS requests', ['dynect', 'dns']) do + + shared_format = { + 'job_id' => Integer, + 'msgs' => [{ + 'ERR_CD' => Fog::Nullable::String, + 'INFO' => String, + 'LVL' => String, + 'SOURCE' => String + }], + 'status' => String + } + tests "success" do - def zone - ENV['DYNECT_ZONE'] + + @dns = Fog::DNS[:dynect] + @domain = generate_unique_domain + @fqdn = "www.#{@domain}" + + post_session_format = shared_format.merge({ + 'data' => { + 'token' => String, + 'version' => String + } + }) + + tests("post_session").formats(post_session_format) do + @dns.post_session.body end - def fqdn - ENV['DYNECT_FQDN'] + post_zone_format = shared_format.merge({ + 'data' => { + 'serial' => Integer, + 'zone' => String, + 'zone_type' => String, + 'serial_style' => String + } + }) + + tests("post_zone('netops@#{@domain}', 3600, '#{@domain}')").formats(post_zone_format) do + @dns.post_zone("netops@#{@domain}", 3600, @domain).body end - tests "start api session" do - response = Dynect[:dns].session - returns(true) { response.body['Auth-Token'] =~ /.+=$/ && true } - returns(true) { response.body['API-Version'] == "2.3.1" } - returns(true) { response.status == 200 } + get_zones_format = shared_format.merge({ + 'data' => [String] + }) + + tests("get_zone").formats(get_zones_format) do + @dns.get_zone.body end - tests "list zones" do - response = Dynect[:dns].list_zones - returns(true) { response.body['zones'].first =~ /\.com/ && true } - returns(true) { response.status == 200 } + get_zone_format = shared_format.merge({ + 'data' => { + "serial" => Integer, + "serial_style" => String, + "zone" => String, + "zone_type" => String + } + }) + + tests("get_zone('zone' => '#{@domain}')").formats(get_zone_format) do + @dns.get_zone('zone' => @domain).body end - tests "get zone" do - response = Dynect[:dns].get_zone(zone) - returns(true) { response.body['zone'] == zone } - returns(true) { response.body['serial'] > 0 } - returns(true) { response.body['zone_type'] == "Primary" } - returns(true) { response.body['serial_style'] == "increment" } + post_record_format = shared_format.merge({ + 'data' => { + 'fqdn' => String, + 'rdata' => { + 'address' => String + }, + 'record_id' => Integer, + 'record_type' => String, + 'ttl' => Integer, + 'zone' => String + } + }) + + tests("post_record('A', '#{@domain}', '#{@fqdn}', 'address' => '1.2.3.4')").formats(post_record_format) do + @dns.post_record('A', @domain, @fqdn, {'address' => '1.2.3.4'}, {}).body end - tests "list records" do - responses = Dynect[:dns].list_any_records(zone, fqdn) - returns(3) { responses.size } - returns(30) { responses.map(&:body).first['ttl'] } + put_zone_format = shared_format.merge({ + 'data' => { + 'serial' => Integer, + 'serial_style' => String, + 'zone' => String, + 'zone_type' => String + } + }) + + tests("put_zone('#{@domain}', :publish => true)").formats(put_zone_format) do + @dns.put_zone(@domain, :publish => true).body end - tests "list zone nodes" do - response = Dynect[:dns].node_list(zone) - returns(zone) { response.body.first } + get_node_list_format = shared_format.merge({ + 'data' => [String] + }) + + tests("get_node_list('#{@domain}')").formats(get_node_list_format) do + @dns.get_node_list(@domain).body end - tests "model" do - records = Fog::DNS.new(:provider => "Dynect").zones.get(zone).records.all(fqdn) - returns("127.0.0.2") { records.last.value } + get_records_format = shared_format.merge({ + 'data' => [String] + }) + + tests("get_record('A', '#{@domain}', '#{@fqdn}')").formats(get_records_format) do + data = @dns.get_record('A', @domain, @fqdn).body + @record_id = data['data'].first.split('/').last + data + end + + delete_record_format = shared_format.merge({ + 'data' => {} + }) + + tests("delete_record('A', '#{@domain}', '#{@fqdn}', '#{@record_id}')").formats(delete_record_format) do + @dns.delete_record('A', @domain, "#{@fqdn}", @record_id).body + end + + delete_zone_format = shared_format.merge({ + 'data' => {} + }) + + tests("delete_zone('#{@domain}')").formats(delete_zone_format) do + @dns.delete_zone(@domain).body end - tests "create record" - tests "delete record" - tests "update record" - tests "list jobs" end end