diff --git a/lib/fog/bin.rb b/lib/fog/bin.rb index 22ba04247..81e995cea 100644 --- a/lib/fog/bin.rb +++ b/lib/fog/bin.rb @@ -57,6 +57,7 @@ require 'fog/bin/aws' require 'fog/bin/bluebox' require 'fog/bin/brightbox' require 'fog/bin/dnsimple' +require 'fog/bin/dnsmadeeasy' require 'fog/bin/ecloud' require 'fog/bin/go_grid' require 'fog/bin/google' diff --git a/lib/fog/bin/dnsmadeeasy.rb b/lib/fog/bin/dnsmadeeasy.rb new file mode 100644 index 000000000..6f591ef1d --- /dev/null +++ b/lib/fog/bin/dnsmadeeasy.rb @@ -0,0 +1,30 @@ +class DNSMadeEasy < Fog::Bin + class << self + + def class_for(key) + case key + when :dns + Fog::DNSMadeEasy::DNS + else + raise ArgumentError, "Unrecognized service: #{key}" + end + end + + def [](service) + @@connections ||= Hash.new do |hash, key| + hash[key] = case key + when :dns + Fog::DNS.new(:provider => 'DNSMadeEasy') + else + raise ArgumentError, "Unrecognized service: #{key.inspect}" + end + end + @@connections[service] + end + + def services + Fog::DNSMadeEasy.services + end + + end +end diff --git a/lib/fog/core/errors.rb b/lib/fog/core/errors.rb index 46ed8e62c..31cf2c6b5 100644 --- a/lib/fog/core/errors.rb +++ b/lib/fog/core/errors.rb @@ -61,6 +61,8 @@ An alternate file may be used by placing its path in the FOG_RC environment vari :zerigo_token: :dnsimple_email: :dnsimple_password: + :dnsmadeeasy_api_key: + :dnsmadeeasy_secret_key: # # End of Fog Credentials File ####################################################### diff --git a/lib/fog/dns.rb b/lib/fog/dns.rb index 1842107c3..3248af42a 100644 --- a/lib/fog/dns.rb +++ b/lib/fog/dns.rb @@ -13,6 +13,9 @@ module Fog when 'DNSimple' require 'fog/dns/dnsimple' Fog::DNSimple::DNS.new(attributes) + when 'DNSMadeEasy' + require 'fog/dns/dnsmadeeasy' + Fog::DNSMadeEasy::DNS.new(attributes) when 'Linode' require 'fog/dns/linode' Fog::Linode::DNS.new(attributes) diff --git a/lib/fog/dns/dnsmadeeasy.rb b/lib/fog/dns/dnsmadeeasy.rb new file mode 100644 index 000000000..cdba501ca --- /dev/null +++ b/lib/fog/dns/dnsmadeeasy.rb @@ -0,0 +1,148 @@ +module Fog + module DNSMadeEasy + class DNS < Fog::Service + + requires :dnsmadeeasy_api_key, :dnsmadeeasy_secret_key + recognizes :host, :path, :port, :scheme, :persistent + recognizes :provider # remove post deprecation + + model_path 'fog/dns/models/dnsmadeeasy' + model :record + collection :records + model :zone + collection :zones + + request_path 'fog/dns/requests/dnsmadeeasy' + request :list_domains + request :get_domain + request :create_domain + request :delete_domain + + request :list_records + request :create_record + request :update_record + request :get_record + request :delete_record + + request :list_secondary + request :delete_all_secondary + request :get_secondary + request :create_secondary + request :update_secondary + request :delete_secondary + + class Mock + def self.data + @data ||= Hash.new do |hash, key| + hash[key] = {} + end + end + + def self.reset + @data = nil + end + + def initialize(options={}) + unless options.delete(:provider) + location = caller.first + warning = "[yellow][WARN] Fog::DNSMadeEasy::DNS.new is deprecated, use Fog::DNS.new(:provider => 'DNSMadeEasy') instead[/]" + warning << " [light_black](" << location << ")[/] " + Formatador.display_line(warning) + end + + @dnsmadeeasy_api_key = options[:dnsmadeeasy_api_key] + @dnsmadeeasy_secret_key = options[:dnsmadeeasy_secret_key] + end + + def data + self.class.data[@dnsmadeeasy_api_key] + end + + def reset_data + self.class.data.delete(@dnsmadeeasy_api_key) + end + end + + class Real + + # Initialize connection to DNS Made Easy + # + # ==== Notes + # options parameter must include values for :dnsmadeeasy_api_key and + # :dnsmadeeasy_secret_key in order to create a connection + # + # ==== Examples + # dns = Fog::DNSMadeEasy::DNS.new( + # :dnsmadeeasy_api_key => your_dnsmadeeasy_api_key, + # :dnsmadeeasy_secret_key => your_dnsmadeeasy_secret_key + # ) + # + # ==== Parameters + # * options<~Hash> - config arguments for connection. Defaults to {}. + # + # ==== Returns + # * dns object with connection to aws. + def initialize(options={}) + unless options.delete(:provider) + location = caller.first + warning = "[yellow][WARN] Fog::DNSMadeEasy::DNS.new is deprecated, use Fog::DNS.new(:provider => 'DNSMadeEasy') instead[/]" + warning << " [light_black](" << location << ")[/] " + Formatador.display_line(warning) + end + + require 'fog/core/parser' + require 'json' + + @dnsmadeeasy_api_key = options[:dnsmadeeasy_api_key] + @dnsmadeeasy_secret_key = options[:dnsmadeeasy_secret_key] + @host = options[:host] || 'api.dnsmadeeasy.com' + @port = options[:port] || 80 #443 Not yet + @scheme = options[:scheme] || 'http' #'https Not yet + unless options.has_key?(:persistent) + options[:persistent] = true + end + @connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}", options[:persistent]) + end + + def reload + @connection.reset + end + + private + + def request(params) + params[:headers] ||= {} + params[:headers]['x-dnsme-apiKey'] = @dnsmadeeasy_api_key + params[:headers]['x-dnsme-requestDate'] = Fog::Time.now.to_date_header + params[:headers]['x-dnsme-hmac'] = signature(params) + params[:headers]['Accept'] = 'application/json' + params[:headers]['Content-Type'] = 'application/json' + + begin + response = @connection.request(params) + + rescue Excon::Errors::HTTPStatusError => error + raise case error + when Excon::Errors::NotFound + Fog::DNSMadeEasy::DNS::NotFound.slurp(error) + else + error + end + end + + unless response.body.empty? + response.body = JSON.parse(response.body) + end + + response + + end + + def signature(params) + string_to_sign = params[:headers]['x-dnsme-requestDate'] + signed_string = OpenSSL::HMAC.hexdigest('sha1', @dnsmadeeasy_secret_key, string_to_sign) + end + end + end + end +end diff --git a/lib/fog/dns/models/dnsmadeeasy/record.rb b/lib/fog/dns/models/dnsmadeeasy/record.rb new file mode 100644 index 000000000..a2dc18607 --- /dev/null +++ b/lib/fog/dns/models/dnsmadeeasy/record.rb @@ -0,0 +1,79 @@ +require 'fog/core/model' + +module Fog + module DNSMadeEasy + class DNS + + class Record < Fog::Model + extend Fog::Deprecation + deprecate :ip, :value + deprecate :ip=, :value= + + identity :id + + attribute :name + attribute :type + attribute :ttl + attribute :gtd_location, :aliases => "gtdLocation" + attribute :password + attribute :description + attribute :keywords + attribute :title + attribute :redirect_type, :aliases => "redirectType" + attribute :hard_link, :aliases => "hardLink" + + attribute :value, :aliases => "data" + + def initialize(attributes={}) + self.ttl ||= 1800 + super + end + + def destroy + connection.delete_record(zone.domain, identity) + true + end + + def zone + @zone + end + + def save + requires :name, :type, :value, :ttl + options = {} + options[:ttl] = ttl if ttl + options[:gtdLocation] = gtd_location if gtd_location + + if type.upcase == 'A' + options[:password] = password if password + end + + if type.upcase == 'HTTPRED' + options[:description] = description if description + options[:keywords] = keywords if keywords + options[:title] = title if title + options[:redirectType] = redirect_type if redirect_type + options[:hardLink] = hard_link if hard_link + end + + if id.nil? + data = connection.create_record(zone.domain, name, type, value, options).body + else + data = connection.update_record(zone.domain, id, options).body + end + + merge_attributes(data) + true + end + + private + + def zone=(new_zone) + @zone = new_zone + end + + end + + end + end +end diff --git a/lib/fog/dns/models/dnsmadeeasy/records.rb b/lib/fog/dns/models/dnsmadeeasy/records.rb new file mode 100644 index 000000000..9ae6f20e9 --- /dev/null +++ b/lib/fog/dns/models/dnsmadeeasy/records.rb @@ -0,0 +1,36 @@ +require 'fog/core/collection' +require 'fog/dns/models/dnsmadeeasy/record' + +module Fog + module DNSMadeEasy + class DNS + + class Records < Fog::Collection + + attribute :zone + + model Fog::DNSMadeEasy::DNS::Record + + def all + requires :zone + data = connection.list_records(zone.identity).body + load(data) + end + + def get(record_id) + data = connection.get_record(zone.identity, record_id).body + new(data) + rescue Fog::Service::NotFound + nil + end + + def new(attributes = {}) + requires :zone + super({ :zone => zone }.merge!(attributes)) + end + + end + + end + end +end diff --git a/lib/fog/dns/models/dnsmadeeasy/zone.rb b/lib/fog/dns/models/dnsmadeeasy/zone.rb new file mode 100644 index 000000000..7ee0a5f79 --- /dev/null +++ b/lib/fog/dns/models/dnsmadeeasy/zone.rb @@ -0,0 +1,42 @@ +require 'fog/core/model' +require 'fog/dns/models/dnsmadeeasy/records' + +module Fog + module DNSMadeEasy + class DNS + + class Zone < Fog::Model + + identity :id + attribute :domain, :aliases => 'name' + attribute :gtd_enabled, :aliases => 'gtdEnabled' + attribute :nameservers, :aliases => 'nameServer' + + def destroy + requires :identity + connection.delete_domain(identity) + true + end + + def records + @records ||= begin + Fog::DNSMadeEasy::DNS::Records.new( + :zone => self, + :connection => connection + ) + end + end + + def save + requires :domain + data = connection.create_domain(domain).body + self.identity = data['name'] + merge_attributes(data) + true + end + + end + + end + end +end diff --git a/lib/fog/dns/models/dnsmadeeasy/zones.rb b/lib/fog/dns/models/dnsmadeeasy/zones.rb new file mode 100644 index 000000000..3254e54d9 --- /dev/null +++ b/lib/fog/dns/models/dnsmadeeasy/zones.rb @@ -0,0 +1,30 @@ +require 'fog/core/collection' +require 'fog/dns/models/dnsmadeeasy/zone' + +module Fog + module DNSMadeEasy + class DNS + + class Zones < Fog::Collection + + model Fog::DNSMadeEasy::DNS::Zone + + def all + clear + data = connection.list_domains.body['list'].collect{|domain| {:id => domain}} + load(data) + end + + def get(zone_id) + data = connection.get_domain(zone_id).body + data.merge!(:id => data['name']) + new(data) + rescue Excon::Errors::NotFound + nil + end + + end + + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/create_domain.rb b/lib/fog/dns/requests/dnsmadeeasy/create_domain.rb new file mode 100644 index 000000000..9ec57eff8 --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/create_domain.rb @@ -0,0 +1,29 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Creates a domain entry with the specified name. Returns errors if name is not valid or conflicts with another domain. + # + # ==== Parameters + # * domain<~String> - domain name + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * name<~String> The domain name. + # * nameServer<~Array> List of strings, Name servers associated with this domain e.g. ["ns1.dnsmadeeasy.com", "ns2.dnsmadeeasy.com"] + # * gtdEnabled<~Boolean> true | false - Indicator of whether or not this domain uses the Global Traffic Director. + # * status<~Integer> - 201 - domain successfully created, 400 - domain name not valid, see errors in response content + def create_domain(domain) + request( + :expects => 201, + :method => 'PUT', + :path => "/V1.2/domains/#{domain}" + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/create_record.rb b/lib/fog/dns/requests/dnsmadeeasy/create_record.rb new file mode 100644 index 000000000..32c4ad854 --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/create_record.rb @@ -0,0 +1,62 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Creates a record with the representation specified in the request content. Returns errors if record is not valid. + # Note that a record ID will be generated by the system with this request and any ID that is sent will be ignored. Records are not modifiable for domains that are locked to a template. + # + # ==== Parameters + # * domain<~String> Domain name. + # * name<~String> Record name. + # * type<~String> Record type. Values: A, AAAA, CNAME, HTTPRED, MX, NS, PTR, SRV, TXT + # * data<~String> Record data + # * options<~Hash> - optional + # * ttl<~Integer> Time to live. The amount of time a record will be cached before being refreshed. Default: 1800 (30 mins) + # * gtdLocation<~String> Global Traffic Director location. Values: DEFAULT, US_EAST, US_WEST, EUROPE + # * password<~String> For A records. Password used to authenticate for dynamic DNS. + # * description<~String> For HTTPRED records. A description of the HTTPRED record. + # * keywords<~String> For HTTPRED records. Keywords associated with the HTTPRED record. + # * title<~String> For HTTPRED records. The title of the HTTPRED record. + # * redirectType<~String> For HTTPRED records. Type of redirection performed. Values: Hidden Frame Masked, Standard - 302, Standard - 301 + # * hardLink<~Boolean> For HTTPRED records. + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * id<~Integer> Unique record identifier + # * name<~String> + # * type<~String> + # * data<~String> + # * ttl<~Integer> + # * gtdLocation<~String> + # * password<~String> + # * description<~String> + # * keywords<~String> + # * title<~String> + # * redirectType<~String> + # * hardLink<~Boolean> + # * 'status'<~Integer> - 201 - record successfully created, 400 - record not valid, see errors in response content, 404 - domain not found + def create_record(domain, name, type, data, options = {}) + + body = { + "name" => name, + "type" => type, + "data" => data, + "ttl" => 1800 + } + + body.merge!(options) + + request( + :expects => 201, + :method => "POST", + :path => "/V1.2/domains/#{domain}/records", + :body => body.to_json + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/create_secondary.rb b/lib/fog/dns/requests/dnsmadeeasy/create_secondary.rb new file mode 100644 index 000000000..62294464a --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/create_secondary.rb @@ -0,0 +1,36 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Creates a secondary entry with the specified name. Returns errors if name is not valid or conflicts with another domain. + # + # ==== Parameters + # * secondary_name<~String> - secondary name + # * ip_addresses<~Array> - List of secondary ip addresses + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * name<~String> Secondary name. + # * ip<~Array> List of strings, IP addresses for your master nameserver associated with this secondary entry. e.g. ["10.10.10.10", "10.10.10.11"] + # * gtdLocation<~String> Global Traffic Director location. Values: DEFAULT, US_EAST, US_WEST, EUROPE + # * status<~Integer> - 201 - secondary entry successfully created or modified, 400 - secondary entry name or IP addresses not valid, see errors in response content + def create_secondary(secondary_name, ip_addresses) + + body = { + "ip" => [*ip_addresses] + } + + request( + :expects => 201, + :method => 'PUT', + :path => "/V1.2/secondary/#{secondary_name}", + :body => body.to_json + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/delete_all_domains.rb b/lib/fog/dns/requests/dnsmadeeasy/delete_all_domains.rb new file mode 100644 index 000000000..b2563f875 --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/delete_all_domains.rb @@ -0,0 +1,23 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Deletes all domains for your account. + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * status<~Integer> - 200 - OK + def delete_all_domains + request( + :expects => 200, + :method => 'GET', + :path => '/V1.2/domains' + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/delete_all_secondary.rb b/lib/fog/dns/requests/dnsmadeeasy/delete_all_secondary.rb new file mode 100644 index 000000000..e55c5d867 --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/delete_all_secondary.rb @@ -0,0 +1,22 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Deletes all secondary entries for your account. + # + # ==== Returns + # * response<~Excon::Response>: + # * status<~Integer> 200 - OK + def delete_all_secondary + request( + :expects => 200, + :method => 'DELETE', + :path => '/V1.2/secondary' + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/delete_domain.rb b/lib/fog/dns/requests/dnsmadeeasy/delete_domain.rb new file mode 100644 index 000000000..3b08688fc --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/delete_domain.rb @@ -0,0 +1,25 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Delete the given domain from your account. + # + # ==== Parameters + # * domain<~String> - domain name + # + # ==== Returns + # * response<~Excon::Response>: + # * status<~Integer> 200 - OK, 404 - specified domain name is not found + def delete_domain(domain) + request( + :expects => 200, + :method => 'DELETE', + :path => "/V1.2/domains/#{domain}" + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/delete_record.rb b/lib/fog/dns/requests/dnsmadeeasy/delete_record.rb new file mode 100644 index 000000000..4f82cd05c --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/delete_record.rb @@ -0,0 +1,26 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Deletes the record with the specified id. Note that records are not modifiable for domains that are locked to a template. + # + # ==== Parameters + # * domain<~String> - domain name + # * record_id<~String> - record id + # + # ==== Returns + # * response<~Excon::Response>: + # * status<~Integer> 200 - OK, 404 - specified domain name or record id is not found + def delete_record(domain, record_id) + request( + :expects => 200, + :method => 'DELETE', + :path => "/V1.2/domains/#{domain}/records/#{record_id}" + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/delete_secondary.rb b/lib/fog/dns/requests/dnsmadeeasy/delete_secondary.rb new file mode 100644 index 000000000..355167b20 --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/delete_secondary.rb @@ -0,0 +1,25 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Deletes the specified secondary entry. + # + # ==== Parameters + # * secondary_name<~String> - secondary domain name + # + # ==== Returns + # * response<~Excon::Response>: + # * status<~Integer> 200 - OK, 404 - specified secondary entry name is not found + def delete_secondary(secondary_name) + request( + :expects => 200, + :method => 'DELETE', + :path => "/V1.2/secondary/#{secondary_name}" + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/get_domain.rb b/lib/fog/dns/requests/dnsmadeeasy/get_domain.rb new file mode 100644 index 000000000..075178cb8 --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/get_domain.rb @@ -0,0 +1,29 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Get the details for a specific domain in your account. + # + # ==== Parameters + # * domain<~String> - domain name + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * name<~String> The domain name. + # * nameServer<~Array> List of strings, Name servers associated with this domain e.g. ["ns1.dnsmadeeasy.com", "ns2.dnsmadeeasy.com"] + # * gtdEnabled<~Boolean> Indicator of whether or not this domain uses the Global Traffic Director. + # * status<~Integer> 200 - OK, 404 - specified domain name is not found + def get_domain(domain) + request( + :expects => 200, + :method => "GET", + :path => "/V1.2/domains/#{domain}" + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/get_record.rb b/lib/fog/dns/requests/dnsmadeeasy/get_record.rb new file mode 100644 index 000000000..a3f78ed22 --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/get_record.rb @@ -0,0 +1,38 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Returns a record object representing the record with the specified id. + # + # ==== Parameters + # * domain<~String> + # * record_id<~Integer> + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * id<~Integer> Unique record identifier + # * name<~String> Record name. + # * type<~String> Record type. Values: A, AAAA, CNAME, HTTPRED, MX, NS, PTR, SRV, TXT + # * data<~String> Record data + # * ttl<~Integer> Time to live. The amount of time a record will be cached before being refreshed. Default: 1800 + # * gtdLocation<~String> Global Traffic Director location. Values: DEFAULT, US_EAST, US_WEST, EUROPE + # * password<~String> For A records. Password used to authenticate for dynamic DNS. + # * description<~String> For HTTPRED records. A description of the HTTPRED record. + # * keywords<~String> For HTTPRED records. Keywords associated with the HTTPRED record. + # * title<~String> For HTTPRED records. The title of the HTTPRED record. + # * redirectType<~String> For HTTPRED records. Type of redirection performed. Values: Hidden Frame Masked, Standard - 302, Standard - 301 + # * hardLink<~Boolean> For HTTPRED records. + # * status<~Integer> - 200 - OK, 404 - specified domain name or record id is not found + def get_record(domain, record_id) + request( + :expects => 200, + :method => "GET", + :path => "/V1.2/domains/#{domain}/records/#{record_id}" + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/get_secondary.rb b/lib/fog/dns/requests/dnsmadeeasy/get_secondary.rb new file mode 100644 index 000000000..11f83afe6 --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/get_secondary.rb @@ -0,0 +1,29 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Returns the secondary entry object representation of the specified secondary entry. + # + # ==== Parameters + # * secondary_name<~String> - secondary name + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * name<~String> Secondary name. + # * ip<~Array> List of strings, IP addresses for your master nameserver associated with this secondary entry. e.g. ["10.10.10.10", "10.10.10.11"] + # * gtdLocation<~String> Global Traffic Director location. Values: DEFAULT, US_EAST, US_WEST, EUROPE + # * status<~Integer> - 200 - OK, 404 - specified secondary entry name is not found + def get_secondary(secondary_name) + request( + :expects => 200, + :method => "GET", + :path => "/V1.2/secondary/#{secondary_name}" + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/list_domains.rb b/lib/fog/dns/requests/dnsmadeeasy/list_domains.rb new file mode 100644 index 000000000..d433e4b39 --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/list_domains.rb @@ -0,0 +1,24 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Returns a list of all domain names for your account. + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * list<~Array> e.g. ["domain1.com","domain2.com", "domain3.com"] + # * status<~Integer> - 200 - OK + def list_domains + request( + :expects => 200, + :method => 'GET', + :path => '/V1.2/domains' + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/list_records.rb b/lib/fog/dns/requests/dnsmadeeasy/list_records.rb new file mode 100644 index 000000000..c9f204130 --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/list_records.rb @@ -0,0 +1,42 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Returns a list of record objects containing all records for the specified domain + # + # ==== Parameters + # * domain<~String> + # * options<~Hash> + # * gtdLocation<~String> Global Traffic Director location. Values: DEFAULT, US_EAST, US_WEST, EUROPE + # * type<~String> Record type. Values: A, AAAA, CNAME, HTTPRED, MX, NS, PTR, SRV, TXT + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * id<~Integer> Unique record identifier + # * name<~String> Record name. + # * type<~String> Record type. Values: A, AAAA, CNAME, HTTPRED, MX, NS, PTR, SRV, TXT + # * data<~String> + # * ttl<~Integer> Time to live. The amount of time a record will be cached before being refreshed. + # * gtdLocation<~String> Global Traffic Director location. Values: DEFAULT, US_EAST, US_WEST, EUROPE + # * password<~String> For A records. Password used to authenticate for dynamic DNS. + # * description<~String> For HTTPRED records. A description of the HTTPRED record. + # * keywords<~String> For HTTPRED records. Keywords associated with the HTTPRED record. + # * title<~String> For HTTPRED records. The title of the HTTPRED record. + # * redirectType<~String> For HTTPRED records. Type of redirection performed. Values: Hidden Frame Masked, Standard - 302, Standard - 301 + # * hardLink<~Boolean> For HTTPRED records. + # * status<~Integer> - 200 - OK, 404 - specified domain name is not found + def list_records(domain, options = {}) + request( + :expects => 200, + :method => "GET", + :path => "/V1.2/domains/#{domain}/records", + :query => options + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/list_secondary.rb b/lib/fog/dns/requests/dnsmadeeasy/list_secondary.rb new file mode 100644 index 000000000..32c8c7966 --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/list_secondary.rb @@ -0,0 +1,24 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Returns a list of all secondary entry names for your account. + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * list<~Array> e.g. ["xxx.domain.com", "xxx.domain.com"] + # * status<~Integer> 200 - OK + def list_secondary + request( + :expects => 200, + :method => 'GET', + :path => '/V1.2/secondary' + ) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/update_record.rb b/lib/fog/dns/requests/dnsmadeeasy/update_record.rb new file mode 100644 index 000000000..e1d5176df --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/update_record.rb @@ -0,0 +1,58 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Updates a record with the representation specified in the request content. Returns errors if record is not valid. + # Note that a record ID will be generated by the system with this request and any ID that is sent will be ignored. Records are not modifiable for domains that are locked to a template. + # + # DNS Made Easy has no update record method but they plan to add it in the next update! + # They sent a reponse suggesting, there going to internaly delete/create a new record when we make update record call, so I've done the same here for now! + # If want to update a record, it might be better to manually destroy and then create a new record + # + # ==== Parameters + # * domain<~String> Domain name. + # * id<~Integer> Record id. + # * data<~String> Record data + # * options<~Hash> + # * name<~String> Record name. + # * type<~String> Record type. Values: A, AAAA, CNAME, HTTPRED, MX, NS, PTR, SRV, TXT + # * ttl<~Integer> Time to live. The amount of time a record will be cached before being refreshed. Default: 1800 (30 mins) + # * gtdLocation<~String> Global Traffic Director location. Values: DEFAULT, US_EAST, US_WEST, EUROPE + # * password<~String> For A records. Password used to authenticate for dynamic DNS. + # * description<~String> For HTTPRED records. A description of the HTTPRED record. + # * keywords<~String> For HTTPRED records. Keywords associated with the HTTPRED record. + # * title<~String> For HTTPRED records. The title of the HTTPRED record. + # * redirectType<~String> For HTTPRED records. Type of redirection performed. Values: Hidden Frame Masked, Standard - 302, Standard - 301 + # * hardLink<~Boolean> For HTTPRED records. + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * id<~Integer> Unique record identifier + # * name<~String> + # * type<~String> + # * data<~String> + # * ttl<~Integer> + # * gtdLocation<~String> + # * password<~String> + # * description<~String> + # * keywords<~String> + # * title<~String> + # * redirectType<~String> + # * hardLink<~Boolean> + # * 'status'<~Integer> - 201 - record successfully created, 400 - record not valid, see errors in response content, 404 - domain not found + def update_record(domain, id, options = {}) + delete_record(domain, id) + + name = options.delete(:name) {|el|''} + type = options.delete(:type) + ip = options.delete(:ip) + + create_record(domain, name, type, ip, options) + end + + end + end + end +end diff --git a/lib/fog/dns/requests/dnsmadeeasy/update_secondary.rb b/lib/fog/dns/requests/dnsmadeeasy/update_secondary.rb new file mode 100644 index 000000000..eb9b32677 --- /dev/null +++ b/lib/fog/dns/requests/dnsmadeeasy/update_secondary.rb @@ -0,0 +1,36 @@ +module Fog + module DNSMadeEasy + class DNS + class Real + + # Modifies a secondary entry with the specified name. Returns errors if name is not valid or conflicts with another domain. + # + # ==== Parameters + # * secondary_name<~String> - secondary name + # * ip_addresses<~Array> - List of secondary ip addresses + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * name<~String> Secondary name. + # * ip<~Array> List of strings, IP addresses for your master nameserver associated with this secondary entry. e.g. ["10.10.10.10", "10.10.10.11"] + # * gtdLocation<~String> Global Traffic Director location. Values: DEFAULT, US_EAST, US_WEST, EUROPE + # * status<~Integer> - 201 - secondary entry successfully created or modified, 400 - secondary entry name or IP addresses not valid, see errors in response content + def update_secondary(secondary_name, ip_addresses) + + body = { + "ip" => [*ip_addresses] + } + + request( + :expects => 201, + :method => 'PUT', + :path => "/V1.2/secondary/#{secondary_name}", + :body => body.to_json + ) + end + + end + end + end +end diff --git a/lib/fog/providers.rb b/lib/fog/providers.rb index cfb564a44..30bb74f04 100644 --- a/lib/fog/providers.rb +++ b/lib/fog/providers.rb @@ -10,6 +10,7 @@ require 'fog/providers/aws' require 'fog/providers/bluebox' require 'fog/providers/brightbox' require 'fog/providers/dnsimple' +require 'fog/providers/dnsmadeeasy' require 'fog/providers/ecloud' require 'fog/providers/go_grid' require 'fog/providers/google' diff --git a/lib/fog/providers/dnsmadeeasy.rb b/lib/fog/providers/dnsmadeeasy.rb new file mode 100644 index 000000000..f01007e7a --- /dev/null +++ b/lib/fog/providers/dnsmadeeasy.rb @@ -0,0 +1,11 @@ +require 'fog/core' + +module Fog + module DNSMadeEasy + + extend Fog::Provider + + service(:dns, 'dns/dnsmadeeasy') + + end +end diff --git a/tests/dns/helper.rb b/tests/dns/helper.rb index bd66abf60..f4dc96a18 100644 --- a/tests/dns/helper.rb +++ b/tests/dns/helper.rb @@ -23,6 +23,9 @@ def dns_providers }, DNSimple => { :mocked => false + }, + DNSMadeEasy => { + :mocked => false } } end diff --git a/tests/dns/requests/dnsmadeeasy/dns_tests.rb b/tests/dns/requests/dnsmadeeasy/dns_tests.rb new file mode 100644 index 000000000..9603a790c --- /dev/null +++ b/tests/dns/requests/dnsmadeeasy/dns_tests.rb @@ -0,0 +1,142 @@ +Shindo.tests('DNSMadeEasy::dns | DNS requests', ['dnsmadeeasy', 'dns']) do + + @domain = '' + @domain_count = 0 + + def generate_unique_domain( with_trailing_dot = false) + #get time (with 1/100th of sec accuracy) + #want unique domain name and if provider is fast, this can be called more than once per second + time= (Time.now.to_f * 100).to_i + domain = 'test-' + time.to_s + '.com' + if with_trailing_dot + domain+= '.' + end + + domain + end + + tests("success") do + + test("get current domain count") do + pending if Fog.mocking? + + response = DNSMadeEasy[:dns].list_domains() + if response.status == 200 + @domain_count = response.body['list'].size + end + + response.status == 200 + end + + test("create domain") do + pending if Fog.mocking? + + domain = generate_unique_domain + response = DNSMadeEasy[:dns].create_domain(domain) + if response.status == 201 + @domain = response.body + end + + response.status == 201 + end + + test("get domain by name") do + pending if Fog.mocking? + + response = DNSMadeEasy[:dns].get_domain(@domain["name"]) + response.status == 200 + end + + test("create an A resource record") do + pending if Fog.mocking? + + domain = @domain["name"] + name = "www" + type = "A" + data = "1.2.3.4" + response = DNSMadeEasy[:dns].create_record(domain, name, type, data) + + if response.status == 201 + @record = response.body + end + + response.status == 201 + + end + + test("create a MX record") do + pending if Fog.mocking? + + domain = @domain["name"] + name = "" + type = "MX" + data = "10 mail.#{domain}" + options = { :ttl => 60 } + response = DNSMadeEasy[:dns].create_record(domain, name, type, data, options) + + response.status == 201 + end + + test("update a record - - check IP/TTL parameters") do + pending if Fog.mocking? + + domain = @domain["name"] + record_id = @record["id"] + options = {:name => '', :type => 'A', :data => "2.3.4.5", :ttl => 600} + result = false + + response = DNSMadeEasy[:dns].update_record(domain, record_id, options) + @record = response.body + + if response.status == 201 && @record['data'] == '2.3.4.5' && @record['ttl'] == 600 + result = true + end + + result + end + + test("list records") do + pending if Fog.mocking? + + response = DNSMadeEasy[:dns].list_records(@domain["name"]) + + if response.status == 200 + @records = response.body + end + + (response.status == 200) and (response.body.size == 2) + end + + test("delete records") do + pending if Fog.mocking? + domain = @domain["name"] + + result = true + @records.each do |record| + response = DNSMadeEasy[:dns].delete_record(domain, record["id"]) + if(response.status != 200) + result = false + break + end + end + + result + end + + test("delete domain") do + pending if Fog.mocking? + + puts "DNS Made Easy - Sleeping for 10 seconds, otherwise test fails because DNS Made Easy queues requests, it still might fail if DNS Made Easy is busy! MOCK IT!" + puts "THIS MOST LIKELY WILL FAIL ON LIVE because it can take while for DNS Made Easy to create a domain/zone, changing the host to api.sandbox.dnsmadeeasy.com should make it work" + sleep 10 + + response = DNSMadeEasy[:dns].delete_domain(@domain["name"]) + response.status == 200 + end + + end + + tests( 'failure') do + end + +end diff --git a/tests/helper.rb b/tests/helper.rb index b076f52d6..e87f6c183 100644 --- a/tests/helper.rb +++ b/tests/helper.rb @@ -8,7 +8,7 @@ def lorem_file end # check to see which credentials are available and add others to the skipped tags list -all_providers = ['aws', 'bluebox', 'brightbox', 'dnsimple', 'ecloud', 'gogrid', 'google', 'linode', 'local', 'newservers', 'rackspace', 'slicehost', 'stormondemand', 'voxel', 'zerigo'] +all_providers = ['aws', 'bluebox', 'brightbox', 'dnsimple', 'dnsmadeeasy', 'ecloud', 'gogrid', 'google', 'linode', 'local', 'newservers', 'rackspace', 'slicehost', 'stormondemand', 'voxel', 'zerigo'] available_providers = Fog.available_providers.map {|provider| provider.downcase} for provider in (all_providers - available_providers) Formatador.display_line("[yellow]Skipping tests for [bold]#{provider}[/] [yellow]due to lacking credentials (add some to '~/.fog' to run them)[/]")