class PDNS::Zone

Zone on a server.

Attributes

id[R]

@return [String] the ID of the zone.

Public Class Methods

new(http, parent, id, info = {}) click to toggle source

Creates a Zone object.

@param http [HTTP] An HTTP object for interaction with the PowerDNS server. @param parent [API] This object's parent. @param id [String] ID of the zone. @param info [Hash] Optional information of the zone.

# File lib/pdns_api/zone.rb, line 39
def initialize(http, parent, id, info = {})
  @class  = :zones
  @http   = http
  @parent = parent
  @id     = id
  @info   = info
  @url    = "#{parent.url}/#{@class}/#{id}"
end

Public Instance Methods

add(*rrsets) click to toggle source

Adds records to the ones already existing in the zone.

The existing records are retrieved and merged with the ones given in rrsets.

Elements of rrsets can contain :records, which can be:

  • A String containing a single record value.

  • An Array containing record values.

  • An Array containing hashes as specified in the PowerDNS API.

@param rrsets [Array<Object>] Array of Hashes containing records to replace.

@return [Hash] Hash containing result of the operation.

@example

zone.add({
  name: 'www0.example.com.',
  type: 'A',
  ttl:  86_400,
  records: '127.0.1.1',
}, {
  name: 'www1.example.com.',
  type: 'A',
  ttl:  86_400,
  records: ['127.0.1.1', '127.0.0.1'],
}, {
  name: 'www2.example.com.',
  type: 'A',
  ttl:  86_400,
  records: [{content: '127.0.1.1'},{content: '127.0.0.1', disabled: true}],
})
# File lib/pdns_api/zone.rb, line 136
def add(*rrsets)
  # Get current zone data
  data = get

  # Return any errors
  return data if data.key?(:error)

  # Add these records to the rrset
  rrsets.map! do |rrset|
    # Get current data from rrset
    current = current_records(rrset, data)

    # Merge data
    rrset[:records]    = current + ensure_array(rrset[:records])
    rrset[:changetype] = 'REPLACE'
    rrset
  end
  modify(rrsets)
end
axfr_retrieve() click to toggle source

Retrieves the data for a zone. Only works for domains for which the server is a slave. @return [Hash] the result of the retrieval.

# File lib/pdns_api/zone.rb, line 84
def axfr_retrieve
  @http.put "#{@url}/axfr-retrieve"
end
check() click to toggle source

Checks the zone for errors. @return [Hash] the result of the check.

# File lib/pdns_api/zone.rb, line 100
def check
  @http.get "#{@url}/check"
end
cryptokeys(id = nil) click to toggle source

Returns existing or creates a CryptoKey object.

@param id [Integer, nil] ID of a CryptoKey.

@return [Hash, CryptoKey] Hash of CryptoKeys or a single CryptoKey.

- If +id+ is not set the current servers are returned in a hash
  containing +CryptoKey+ objects.
- If +id+ is set a +CryptoKey+ object with the provided ID is returned.

@example

ckeys = zone.cryptokeys
ckey  = zone.cryptokey(12)
# File lib/pdns_api/zone.rb, line 275
def cryptokeys(id = nil)
  return CryptoKey.new(@http, self, id) unless id.nil?

  # Get all current metadata
  cryptokeys = @http.get("#{@url}/cryptokeys")

  # Convert cryptokeys to hash
  cryptokeys.map { |c| [c[:id], CryptoKey.new(@http, self, c[:id], c)] }.to_h
end
export() click to toggle source

Exports the zone as a bind zone file. @return [Hash] containing the Bind formatted zone in :result.

# File lib/pdns_api/zone.rb, line 91
def export
  data = @http.get "#{@url}/export"
  data.delete(:error) if data[:error] == 'Non-JSON response'
  data
end
metadata(kind = nil, value = nil) click to toggle source

Returns existing metadata or creates a Metadata object.

@param kind [String, nil] The kind of metadata. @param value [String, nil] The value of the metadata.

@return [Metadata, Hash] Hash containing all metadata, or single Metadata object.

- If +kind+ is not set the current metadata is returned in a +Hash+.
- If +kind+ is set a +Metadata+ object is returned using the provided +kind+.
- If +value+ is set as well, a complete Metadata object is returned.

@example

# Retrieve all metadata in a hash
zone.metadata
# Create a metadata object
meta = zone.metadata('ALLOW-AXFR-FROM')
puts meta.get
# Create a metadata object with a value
meta = zone.metadata('ALLOW-AXFR-FROM','AUTO-NS')
meta.change
# File lib/pdns_api/zone.rb, line 243
def metadata(kind = nil, value = nil)
  return Metadata.new(@http, self, kind, value) unless kind.nil? || value.nil?
  return Metadata.new(@http, self, kind) unless kind.nil?

  # Get all current metadata
  metadata = @http.get("#{@url}/metadata")

  # Check for errors
  return metadata if metadata.is_a?(Hash) && metadata.key?(:error)

  # Convert metadata to hash
  metadata.map { |c| [c[:kind], c[:metadata]] }.to_h
end
modify(rrsets) click to toggle source

Modifies information (records) of a zone. Also formats records to match the API requirements.

@param rrsets [Array] Changeset to send to the PowerDNS API.

@return [Hash] result of the changeset.

@example

zone.modify([
   changetype: 'DELETE',
   name: 'www.example.com.',
   type: 'A'
])
# File lib/pdns_api/zone.rb, line 63
def modify(rrsets)
  rrsets.map! do |rrset|
    rrset = format_records(rrset) if rrset.key?(:records)
    rrset
  end

  @http.patch(@url, rrsets: rrsets)
end
notify() click to toggle source

Notifies slaves for a zone. Only works for domains for which the server is a master. @return [Hash] the result of the notification.

# File lib/pdns_api/zone.rb, line 76
def notify
  @http.put "#{@url}/notify"
end
remove(*rrsets) click to toggle source

Removes all records for a name/type combination from the zone.

@param rrsets [Array<Object>] Array of Hashes to delete.

The Hash(es) in the Array should contain +:name+ and +:type+.

@return [Hash] Hash containing result of the operation.

@example

zone.remove({
  name: 'www0.example.com.',
  type: 'A'
}, {
  name: 'www1.example.com.',
  type: 'A'
})
# File lib/pdns_api/zone.rb, line 213
def remove(*rrsets)
  # Set type and format records
  rrsets.map! do |rrset|
    rrset[:changetype] = 'DELETE'
    rrset
  end
  modify(rrsets)
end
update(*rrsets) click to toggle source

Updates (replaces) records for a name/type combination in the zone.

Elements of rrsets can contain :records, which can be:

  • A String containing a single record value.

  • An Array containing record values.

  • An Array containing hashes as specified in the PowerDNS API.

@param rrsets [Array<Object>] Array of Hashes containing records to replace.

@return [Hash] Hash containing result of the operation.

@example

zone.update({
  name: 'www0.example.com.',
  type: 'A',
  ttl:  86_400,
  records: '127.0.1.1'
}, {
  name: 'www1.example.com.',
  type: 'A',
  ttl:  86_400,
  records: ['127.0.1.1', '127.0.0.1']
}, {
  name: 'www2.example.com.',
  type: 'A',
  ttl:  86_400,
  records: [{content: '127.0.1.1'},{content: '127.0.0.1', disabled: true}]
})
# File lib/pdns_api/zone.rb, line 186
def update(*rrsets)
  # Set type and format records
  rrsets.map! do |rrset|
    rrset[:changetype] = 'REPLACE'
    rrset[:records] = ensure_array(rrset[:records])
    rrset
  end
  modify(rrsets)
end

Private Instance Methods

current_records(rrset, data) click to toggle source

Returns the records matching the ones in rrset from data.

@param rrset [Hash] RRset to match current records with. @param data [Hash] RRsets currently on the server. Should be the result from get. @return [Array] Currently existing records.

# File lib/pdns_api/zone.rb, line 336
def current_records(rrset, data) # rubocop:disable Metrics/AbcSize
  # Get the records from the data, `records` is v0, `rrsets` is v1
  records = data[:records] || data[:rrsets]

  # Select records matching type/name
  current = records.select { |r| r[:name] == rrset[:name] && r[:type] == rrset[:type] }

  # Get only content/disabled for API v0
  if @http.version.zero?
    current.map! { |record| { content: record[:content], disabled: record[:disabled] } }
  end

  # For API v1 there is only one element containing all records
  current = current.first[:records] unless current.empty? || @http.version.zero?

  # Return the records
  current
end
format_records(rrset) click to toggle source

Format the records in an RRset te match what is required by the API. @param rrset [Hash] RRset of which to format the records. @return [Hash] Formatted RRset.

# File lib/pdns_api/zone.rb, line 311
def format_records(rrset)
  # Ensure existence of required keys
  rrset[:records].map! do |record|
    # Format the record content
    record = format_single_record(record)

    # Add disabled from the rrset
    record[:disabled] ||= !!rrset[:disabled]

    # Return record
    next record unless @http.version.zero?

    # But add some more for APIv0
    record.merge(name: rrset[:name], type: rrset[:type], ttl: rrset[:ttl])
  end
  rrset
end
format_single_record(record) click to toggle source

Formats a single record to match what is required by the API.

@param record [String, Hash] Record to format. @return [Hash] Formatted record.

# File lib/pdns_api/zone.rb, line 293
def format_single_record(record)
  # Ensure content
  record = { content: record } if record.is_a? String

  # Add disabled and set_ptr
  record[:disabled] = !!record[:disabled]
  record[:set_ptr]  = !!record[:set_ptr]

  # Replace some symbols
  record[:'set-ptr'] = record.delete :set_ptr
  record
end