Merge branch 'dje'

This commit is contained in:
geemus 2011-02-25 11:10:41 -08:00
commit d7f214705e
22 changed files with 715 additions and 1 deletions

View File

@ -67,3 +67,4 @@ require 'fog/bin/slicehost'
require 'fog/bin/terremark'
require 'fog/bin/voxel'
require 'fog/bin/zerigo'
require 'fog/bin/dnsimple'

30
lib/fog/bin/dnsimple.rb Normal file
View File

@ -0,0 +1,30 @@
class DNSimple < Fog::Bin
class << self
def class_for(key)
case key
when :dns
Fog::DNSimple::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 => 'DNSimple')
else
raise ArgumentError, "Unrecognized service: #{key.inspect}"
end
end
@@connections[service]
end
def services
Fog::DNSimple.services
end
end
end

View File

@ -79,6 +79,8 @@ An alternate file may be used by placing its path in the FOG_RC environment vari
:voxel_api_secret:
:zerigo_email:
:zerigo_token:
:dnsimple_email:
:dnsimple_password:
#
# End of Fog Credentials File
#######################################################

View File

@ -19,6 +19,9 @@ module Fog
when 'Zerigo'
require 'fog/dns/zerigo'
Fog::Zerigo::DNS.new(attributes)
when 'DNSimple'
require 'fog/dns/dnsimple'
Fog::DNSimple::DNS.new(attributes)
else
raise ArgumentError.new("#{provider} is not a recognized dns provider")
end

95
lib/fog/dns/dnsimple.rb Normal file
View File

@ -0,0 +1,95 @@
module Fog
module DNSimple
class DNS < Fog::Service
requires :dnsimple_email, :dnsimple_password
recognizes :host, :path, :port, :scheme, :persistent
recognizes :provider # remove post deprecation
model_path 'fog/dns/models/dnsimple'
model :record
collection :records
model :zone
collection :zones
request_path 'fog/dns/requests/dnsimple'
request :list_domains
request :create_domain
request :get_domain
request :delete_domain
request :create_record
request :list_records
request :update_record
request :delete_record
class Mock
def self.data
@data ||= Hash.new do |hash, key|
hash[key] = {}
end
end
def self.reset_data(keys=data.keys)
for key in [*keys]
data.delete(key)
end
end
def initialize(options={})
unless options.delete(:provider)
location = caller.first
warning = "[yellow][WARN] Fog::DNS::DNSimple.new is deprecated, use Fog::DNS.new(:provider => 'DNSimple') instead[/]"
warning << " [light_black](" << location << ")[/] "
Formatador.display_line(warning)
end
@dnsimple_email = options[:dnsimple_email]
@dnsimple_password = options[:dnsimple_password]
@data = self.class.data[@dnsimple_email]
@data = self.class.data[@dnsimple_password]
end
end
class Real
def initialize(options={})
unless options.delete(:provider)
location = caller.first
warning = "[yellow][WARN] Fog::DNSimple::DNS.new is deprecated, use Fog::DNS.new(:provider => 'DNSimple') instead[/]"
warning << " [light_black](" << location << ")[/] "
Formatador.display_line(warning)
end
require 'json'
@dnsimple_email = options[:dnsimple_email]
@dnsimple_password = options[:dnsimple_password]
@host = options[:host] || "dnsimple.com"
@port = options[:port] || 443
@scheme = options[:scheme] || 'https'
@connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}", options[:persistent])
end
def reload
@connection.reset
end
def request(params)
params[:headers] ||= {}
key = "#{@dnsimple_email}:#{@dnsimple_password}"
params[:headers].merge!({ "Authorization" => "Basic " + Base64.encode64(key).chomp,
"Accept" => "application/json",
"Content-Type" => "application/json" })
response = @connection.request(params.merge!({:host => @host}))
unless response.body.empty?
response.body = JSON.parse(response.body)
end
response
end
end
end
end
end

View File

@ -0,0 +1,54 @@
require 'fog/core/model'
module Fog
module DNSimple
class DNS
class Record < Fog::Model
identity :id
attribute :name
attribute :ip, :aliases => "content"
attribute :ttl
attribute :created_at
attribute :updated_at
attribute :zone_id, :aliases => "domain_id"
attribute :type, :aliases => "record_type"
attribute :priority, :aliases => "prio"
def initialize(attributes={})
self.ttl ||= 3600
super
end
def destroy
connection.delete_record(zone.domain, identity)
true
end
def zone
@zone
end
def save
requires :name, :type, :ip
options = {}
options[:prio] = priority if priority
options[:ttl] = ttl if ttl
data = connection.create_record(zone.domain, name, type, ip, options)
merge_attributes(data.body["record"])
true
end
private
def zone=(new_zone)
@zone = new_zone
end
end
end
end
end

View File

@ -0,0 +1,38 @@
require 'fog/core/collection'
require 'fog/dns/models/dnsimple/record'
module Fog
module DNSimple
class DNS
class Records < Fog::Collection
attribute :zone
model Fog::DNSimple::DNS::Record
def all
requires :zone
data = connection.list_records(zone.id).body
end
def get(record_id)
all.each do |record|
if record["record"]["id"] == record_id
return new(record)
end
end
nil
end
def new(attributes = {})
requires :zone
super({ :zone => zone }.merge!(attributes))
end
end
end
end
end

View File

@ -0,0 +1,50 @@
require 'fog/core/model'
require 'fog/dns/models/dnsimple/records'
module Fog
module DNSimple
class DNS
class Zone < Fog::Model
identity :id
attribute :domain, :aliases => "name"
attribute :created_at
attribute :updated_at
def destroy
connection.delete_domain(identity)
true
end
def records
@records ||= begin
Fog::DNSimple::DNS::Records.new(
:zone => self,
:connection => connection
)
end
end
def nameservers
[
"ns1.dnsimple.com",
"ns2.dnsimple.com",
"ns3.dnsimple.com",
"ns4.dnsimple.com",
]
end
def save
requires :domain
data = connection.create_domain(domain).body["domain"]
merge_attributes(data)
true
end
end
end
end
end

View File

@ -0,0 +1,28 @@
require 'fog/core/collection'
require 'fog/dns/models/dnsimple/zone'
module Fog
module DNSimple
class DNS
class Zones < Fog::Collection
model Fog::DNSimple::DNS::Zone
def all
data = connection.list_domains.body
load(data)
end
def get(zone_id)
data = connection.get_domain(zone_id).body["domain"]
new(data)
rescue Excon::Errors::NotFound
nil
end
end
end
end
end

View File

@ -0,0 +1,27 @@
module Fog
module DNSimple
class DNS
class Real
# Create a single domain in DNSimple in your account.
# ==== Parameters
# * name<~String> - domain name to host (ie example.com)
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# * 'name'<~String>
def create_domain(name)
body = { "domain" => { "name" => name } }
request(
:body => body.to_json,
:expects => 201,
:method => 'POST',
:path => '/domains'
)
end
end
end
end
end

View File

@ -0,0 +1,48 @@
module Fog
module DNSimple
class DNS
class Real
# Create a new host in the specified zone
#
# ==== Parameters
# * domain<~String>
# * name<~String>
# * type<~String>
# * content<~String>
# * options<~Hash> - optional
# * priority<~Integer>
# * ttl<~Integer>
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>
# * name<~String>
# * ttl<~Integer>
# * created_at<~String>
# * special_type<~String>
# * updated_at<~String>
# * domain_id<~Integer>
# * id<~Integer>
# * content<~String>
# * record_type<~String>
# * prio<~Integer>
def create_record(domain, name, type, content, options = {})
body = {
"record" => {
"name" => name,
"record_type" => type,
"content" => content } }
body["record"].merge!(options)
request( :body => body.to_json,
:expects => 201,
:method => 'POST',
:path => "/domains/#{domain}/records" )
end
end
end
end
end

View File

@ -0,0 +1,26 @@
module Fog
module DNSimple
class DNS
class Real
# Delete the given domain from your account. You may use
# either the domain ID or the domain name.
#
# Please note that for domains which are registered with
# DNSimple this will not delete the domain from the registry.
#
# ==== Parameters
# * name<~String> - domain name or numeric ID
#
def delete_domain(name)
request(
:expects => 200,
:method => 'DELETE',
:path => "/domains/#{name}"
)
end
end
end
end
end

View File

@ -0,0 +1,21 @@
module Fog
module DNSimple
class DNS
class Real
# Delete the record with the given ID for the given domain.
#
# ==== Parameters
# * domain<~String>
# * record_id<~String>
def delete_record(domain, record_id)
request( :expects => 200,
:method => "DELETE",
:path => "/domains/#{domain}/records/#{record_id}" )
end
end
end
end
end

View File

@ -0,0 +1,37 @@
module Fog
module DNSimple
class DNS
class Real
# Get the details for a specific domain in your account. You
# may pass either the domain numeric ID or the domain name
# itself.
#
# ==== Parameters
# * id<~String> - domain name or numeric ID
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# * 'domain'<~Hash>
# * 'name'<~String>
# * 'expires_at'<~String>
# * 'created_at'<~String>
# * 'registration_status'<~String>
# * 'updated_at'<~String>
# * 'registrant_id'<~Integer>
# * 'id'<~Integer>
# * 'user_id'<~Integer>
# * 'name_server_status'<~String>
def get_domain(id)
request(
:expects => 200,
:method => "GET",
:path => "/domains/#{id}"
)
end
end
end
end
end

View File

@ -0,0 +1,35 @@
module Fog
module DNSimple
class DNS
class Real
# Get the details for a specific domain in your account. You
# may pass either the domain numeric ID or the domain name itself.
# ==== Parameters
# * id<~String> - domain name or numeric ID
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# * 'domains'<~Array>
# * 'name'<~String>
# * 'expires_at'<~String>
# * 'created_at'<~String>
# * 'registration_status'<~String>
# * 'updated_at'<~String>
# * 'registrant_id'<~Integer>
# * 'id'<~Integer>
# * 'user_id'<~Integer>
# * 'name_server_status'<~String>
def list_domains
request(
:expects => 200,
:method => 'GET',
:path => '/domains'
)
end
end
end
end
end

View File

@ -0,0 +1,32 @@
module Fog
module DNSimple
class DNS
class Real
# Get the list of records for the specific domain.
#
# ==== Parameters
# * domain<~String>
# ==== Returns
# * response<~Excon::Response>:
# * records<Array~>
# * name<~String>
# * ttl<~Integer>
# * created_at<~String>
# * special_type<~String>
# * updated_at<~String>
# * domain_id<~Integer>
# * id<~Integer>
# * content<~String>
# * record_type<~String>
# * prio<~Integer>
def list_records(domain)
request( :expects => 200,
:method => "GET",
:path => "/domains/#{domain}/records" )
end
end
end
end
end

View File

@ -0,0 +1,42 @@
module Fog
module DNSimple
class DNS
class Real
# Update the given record for the given domain.
#
# ==== Parameters
# * domain<~String>
# * record_id<~String>
# * options<~Hash> - optional
# * type<~String>
# * content<~String>
# * priority<~Integer>
# * ttl<~Integer>
# ==== Returns
# * response<~Excon::Response>:
# * record<~Hash>
# * name<~String>
# * ttl<~Integer>
# * created_at<~String>
# * special_type<~String>
# * updated_at<~String>
# * domain_id<~Integer>
# * id<~Integer>
# * content<~String>
# * record_type<~String>
# * prio<~Integer>
def update_record(domain, record_id, options)
body = { "record" => options }
request( :body => body.to_json,
:expects => 200,
:method => "PUT",
:path => "/domains/#{domain}/records/#{record_id}" )
end
end
end
end
end

View File

@ -19,3 +19,4 @@ require 'fog/providers/rackspace'
require 'fog/providers/slicehost'
require 'fog/providers/voxel'
require 'fog/providers/zerigo'
require 'fog/providers/dnsimple'

View File

@ -0,0 +1,11 @@
require 'fog/core'
module Fog
module DNSimple
extend Fog::Provider
service(:dns, 'dns/dnsimple')
end
end

View File

@ -20,6 +20,9 @@ def dns_providers
},
Zerigo => {
:mocked => false
},
DNSimple => {
:mocked => false
}
}
end

View File

@ -0,0 +1,130 @@
Shindo.tests('DNSimple::dns | DNS requests', ['dnsimple', '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 = DNSimple[:dns].list_domains()
if response.status == 200
@domain_count = response.body.size
end
response.status == 200
end
test("create domain") do
pending if Fog.mocking?
domain = generate_unique_domain
response = DNSimple[:dns].create_domain(domain)
if response.status == 201
@domain = response.body["domain"]
end
response.status == 201
end
test("get domain by id") do
pending if Fog.mocking?
response = DNSimple[:dns].get_domain(@domain["id"])
response.status == 200
end
test("create an A resource record") do
pending if Fog.mocking?
domain = @domain["name"]
name = "www"
type = "A"
content = "1.2.3.4"
response = DNSimple[:dns].create_record(domain, name, type, content)
if response.status == 201
@record = response.body["record"]
end
response.status == 201
end
test("create a MX record") do
pending if Fog.mocking?
domain = @domain["name"]
name = ""
type = "MX"
content = "mail.#{domain}"
options = { :ttl => 60, :prio => 10 }
response = DNSimple[:dns].create_record(domain, name, type, content, options)
response.status == 201
end
test("update a record") do
pending if Fog.mocking?
domain = @domain["name"]
record_id = @record["id"]
options = { :content => "2.3.4.5", :ttl => 600 }
response = DNSimple[:dns].update_record(domain, record_id, options)
response.status == 200
end
test("list records") do
pending if Fog.mocking?
response = DNSimple[: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 = DNSimple[:dns].delete_record(domain, record["record"]["id"])
if(response.status != 200)
result = false
break
end
end
result
end
test("delete domain") do
pending if Fog.mocking?
response = DNSimple[:dns].delete_domain(@domain["name"])
response.status == 200
end
end
tests( 'failure') do
end
end

View File

@ -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', 'gogrid', 'google', 'linode', 'local', 'newservers', 'rackspace', 'slicehost', 'terremarkecloud', 'zerigo']
all_providers = ['aws', 'bluebox', 'brightbox', 'gogrid', 'google', 'linode', 'local', 'newservers', 'rackspace', 'slicehost', 'terremarkecloud', 'zerigo', 'dnsimple']
available_providers = Fog.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)[/]")