class Fog::DNS::AWS::Mock

Public Class Methods

data() click to toggle source
# File lib/fog/aws/dns.rb, line 31
def self.data
  @data ||= Hash.new do |hash, region|
    hash[region] = Hash.new do |region_hash, key|
      region_hash[key] = {
        :buckets => {},
        :limits => {
          :duplicate_domains => 5
        },
        :zones => {},
        :changes => {}
      }
    end
  end
end
new(options={}) click to toggle source
# File lib/fog/aws/dns.rb, line 50
def initialize(options={})
  @use_iam_profile = options[:use_iam_profile]
  setup_credentials(options)
  @region             = options[:region]
end
reset() click to toggle source
# File lib/fog/aws/dns.rb, line 46
def self.reset
  @data = nil
end

Public Instance Methods

change_resource_record_sets(zone_id, change_batch, options = {}) click to toggle source
# File lib/fog/aws/requests/dns/change_resource_record_sets.rb, line 153
def change_resource_record_sets(zone_id, change_batch, options = {})
  response = Excon::Response.new
  errors   = []

  if (zone = self.data[:zones][zone_id])
    response.status = 200

    change_id = Fog::AWS::Mock.change_id
    change_batch.each do |change|
      case change[:action]
      when "CREATE"
        if zone[:records][change[:type]].nil?
          zone[:records][change[:type]] = {}
        end

        if zone[:records][change[:type]][change[:name]].nil?
          # raise change.to_s if change[:resource_records].nil?
          zone[:records][change[:type]][change[:name]] =
          if change[:alias_target]
            record = {
              :alias_target => change[:alias_target]
            }
          else
            record = {
              :ttl => change[:ttl].to_s,
            }
          end
          zone[:records][change[:type]][change[:name]] = {
            :change_id => change_id,
            :resource_records => change[:resource_records] || [],
            :name => change[:name],
            :type => change[:type]
          }.merge(record)
        else
          errors << "Tried to create resource record set #{change[:name]}. type #{change[:type]}, but it already exists"
        end
      when "DELETE"
        if zone[:records][change[:type]].nil? || zone[:records][change[:type]].delete(change[:name]).nil?
          errors << "Tried to delete resource record set #{change[:name]}. type #{change[:type]}, but it was not found"
        end
      end
    end

    if errors.empty?
      change = {
        :id => change_id,
        :status => 'PENDING',
        :submitted_at => Time.now.utc.iso8601
      }
      self.data[:changes][change[:id]] = change
      response.body = {
        'Id' => change[:id],
        'Status' => change[:status],
        'SubmittedAt' => change[:submitted_at]
      }
      response
    else
      response.status = 400
      response.body = "<?xml version=\"1.0\"?><InvalidChangeBatch xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Messages>#{errors.map {|e| "<Message>#{e}</Message>"}.join()}</Messages></InvalidChangeBatch>"
      raise(Excon::Errors.status_error({:expects => 200}, response))
    end
  else
    response.status = 404
    response.body = "<?xml version=\"1.0\"?><Response><Errors><Error><Code>NoSuchHostedZone</Code><Message>A hosted zone with the specified hosted zone ID does not exist.</Message></Error></Errors><RequestID>#{Fog::AWS::Mock.request_id}</RequestID></Response>"
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end
end
create_hosted_zone(name, options = {}) click to toggle source
# File lib/fog/aws/requests/dns/create_hosted_zone.rb, line 57
def create_hosted_zone(name, options = {})
  # Append a trailing period to the name if absent.
  name = name + "." unless name.end_with?(".")

  response = Excon::Response.new
  if list_hosted_zones.body['HostedZones'].select {|z| z['Name'] == name}.size < self.data[:limits][:duplicate_domains]
    response.status = 201
    if options[:caller_ref]
      caller_ref = options[:caller_ref]
    else
      #make sure we have a unique call reference
      caller_ref = "ref-#{rand(1000000).to_s}"
    end
    zone_id = "/hostedzone/#{Fog::AWS::Mock.zone_id}"
    self.data[:zones][zone_id] = {
      :id => zone_id,
      :name => name,
      :reference => caller_ref,
      :comment => options[:comment],
      :records => {}
    }
    change = {
      :id => Fog::AWS::Mock.change_id,
      :status => 'PENDING',
      :submitted_at => Time.now.utc.iso8601
    }
    self.data[:changes][change[:id]] = change
    response.body = {
      'HostedZone' => {
        'Id' => zone_id,
        'Name' => name,
        'CallerReference' => caller_ref,
        'Comment' => options[:comment]
      },
      'ChangeInfo' => {
        'Id' => change[:id],
        'Status' => change[:status],
        'SubmittedAt' => change[:submitted_at]
      },
      'NameServers' => Fog::AWS::Mock.nameservers
    }
    response
  else
    response.status = 400
    response.body = "<?xml version=\"1.0\"?><Response><Errors><Error><Code>DelegationSetNotAvailable</Code><Message>Amazon Route 53 allows some duplication, but Amazon Route 53 has a maximum threshold of duplicated domains. This error is generated when you reach that threshold. In this case, the error indicates that too many hosted zones with the given domain name exist. If you want to create a hosted zone and Amazon Route 53 generates this error, contact Customer Support.</Message></Error></Errors><RequestID>#{Fog::AWS::Mock.request_id}</RequestID></Response>"
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end
end
data() click to toggle source
# File lib/fog/aws/dns.rb, line 56
def data
  self.class.data[@region][@aws_access_key_id]
end
delete_hosted_zone(zone_id) click to toggle source
# File lib/fog/aws/requests/dns/delete_hosted_zone.rb, line 37
def delete_hosted_zone(zone_id)
  response = Excon::Response.new
  key = [zone_id, "/hostedzone/#{zone_id}"].find{|k| !self.data[:zones][k].nil?}
  if key
    change = {
      :id => Fog::AWS::Mock.change_id,
      :status => 'INSYNC',
      :submitted_at => Time.now.utc.iso8601
    }
    self.data[:changes][change[:id]] = change
    response.status = 200
    response.body = {
      'ChangeInfo' => {
        'Id' => change[:id],
        'Status' => change[:status],
        'SubmittedAt' => change[:submitted_at]
      }
    }
    self.data[:zones].delete(key)
    response
  else
    response.status = 404
    response.body = "<?xml version=\"1.0\"?><ErrorResponse xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Error><Type>Sender</Type><Code>NoSuchHostedZone</Code><Message>The specified hosted zone does not exist.</Message></Error><RequestId>#{Fog::AWS::Mock.request_id}</RequestId></ErrorResponse>"
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end
end
get_change(change_id) click to toggle source
# File lib/fog/aws/requests/dns/get_change.rb, line 34
def get_change(change_id)
  response = Excon::Response.new
  # find the record with matching change_id
  # records = data[:zones].values.map{|z| z[:records].values.map{|r| r.values}}.flatten
  change = self.data[:changes][change_id]

  if change
    response.status = 200
    submitted_at = Time.parse(change[:submitted_at])
    response.body = {
      'Id' => change[:id],
      # set as insync after some time
      'Status' => (submitted_at + Fog::Mock.delay) < Time.now ? 'INSYNC' : change[:status],
      'SubmittedAt' => change[:submitted_at]
    }
    response
  else
    response.status = 404
    response.body = "<?xml version=\"1.0\"?><ErrorResponse xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Error><Type>Sender</Type><Code>NoSuchChange</Code><Message>Could not find resource with ID: #{change_id}</Message></Error><RequestId>#{Fog::AWS::Mock.request_id}</RequestId></ErrorResponse>"
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end
end
get_hosted_zone(zone_id) click to toggle source
# File lib/fog/aws/requests/dns/get_hosted_zone.rb, line 38
def get_hosted_zone(zone_id)
  response = Excon::Response.new
  if (zone = self.data[:zones][zone_id])
    response.status = 200
    response.body = {
      'HostedZone' => {
        'Id' => zone[:id],
        'Name' => zone[:name],
        'CallerReference' => zone[:reference],
        'Comment' => zone[:comment]
      },
      'NameServers' => Fog::AWS::Mock.nameservers
    }
    response
  else
    response.status = 404
    response.body = "<?xml version=\"1.0\"?><ErrorResponse xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Error><Type>Sender</Type><Code>NoSuchHostedZone</Code><Message>The specified hosted zone does not exist.</Message></Error><RequestId>#{Fog::AWS::Mock.request_id}</RequestId></ErrorResponse>"
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end
end
list_hosted_zones(options = {}) click to toggle source
# File lib/fog/aws/requests/dns/list_hosted_zones.rb, line 50
def list_hosted_zones(options = {})
  maxitems = [options[:max_items]||100,100].min

  if options[:marker].nil?
    start = 0
  else
    start = self.data[:zones].find_index {|z| z[:id] == options[:marker]}
  end

  zones     = self.data[:zones].values[start, maxitems]
  next_zone = self.data[:zones].values[start + maxitems]
  truncated = !next_zone.nil?

  response = Excon::Response.new
  response.status = 200
  response.body = {
    'HostedZones' => zones.map do |z|
      {
        'Id' => z[:id],
        'Name' => z[:name],
        'CallerReference' => z[:reference],
        'Comment' => z[:comment],
      }
    end,
    'Marker' => options[:marker].to_s,
    'MaxItems' => maxitems,
    'IsTruncated' => truncated
  }

  if truncated
    response.body['NextMarker'] = next_zone[:id]
  end

  response
end
list_resource_record_sets(zone_id, options = {}) click to toggle source
# File lib/fog/aws/requests/dns/list_resource_record_sets.rb, line 61
def list_resource_record_sets(zone_id, options = {})
  maxitems = [options[:max_items]||100,100].min

  response = Excon::Response.new

  zone = self.data[:zones][zone_id]
  if zone.nil?
    response.status = 404
    response.body = "<?xml version=\"1.0\"?>\n<ErrorResponse xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Error><Type>Sender</Type><Code>NoSuchHostedZone</Code><Message>No hosted zone found with ID: #{zone_id}</Message></Error><RequestId>#{Fog::AWS::Mock.request_id}</RequestId></ErrorResponse>"
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end

  records = if options[:type]
    records_type = zone[:records][options[:type]]
    records_type.values if records_type
  else
    zone[:records].values.map{|r| r.values}.flatten
  end

  records ||= []

  # sort for pagination
  records.sort! { |a,b| a[:name].gsub(zone[:name],"") <=> b[:name].gsub(zone[:name],"") }

  if options[:name]
    name = options[:name].gsub(zone[:name],"")
    records = records.select{|r| r[:name].gsub(zone[:name],"") >= name }
    require 'pp'
  end

  next_record  = records[maxitems]
  records      = records[0, maxitems]
  truncated    = !next_record.nil?

  response.status = 200
  response.body = {
    'ResourceRecordSets' => records.map do |r|
      if r[:alias_target]
        record = {
          'AliasTarget' => {
            'HostedZoneId' => r[:alias_target][:hosted_zone_id],
            'DNSName' => r[:alias_target][:dns_name]
          }
        }
      else
        record = {
          'TTL' => r[:ttl]
        }
      end
      {
        'ResourceRecords' => r[:resource_records],
        'Name' => r[:name],
        'Type' => r[:type]
      }.merge(record)
    end,
    'MaxItems' => maxitems,
    'IsTruncated' => truncated
  }

  if truncated
    response.body['NextRecordName'] = next_record[:name]
    response.body['NextRecordType'] = next_record[:type]
  end

  response
end
reset_data() click to toggle source
# File lib/fog/aws/dns.rb, line 60
def reset_data
  self.class.data[@region].delete(@aws_access_key_id)
end
setup_credentials(options) click to toggle source
# File lib/fog/aws/dns.rb, line 68
def setup_credentials(options)
  @aws_access_key_id  = options[:aws_access_key_id]
end
signature(params) click to toggle source
# File lib/fog/aws/dns.rb, line 64
def signature(params)
  "foo"
end