module GClouder::Resources::DNS

Public Class Methods

clean() click to toggle source
# File lib/gclouder/resources/dns.rb, line 11
def self.clean
  return if undefined.empty?
  header :clean

  undefined.each do |region, zones|
    info region, indent: 2, heading: true
    zones.each do |zone|
      next unless zone.key?("records")
      info zone["name"], indent: 3, heading: true
      zone["records"].each do |record|
        warning "#{record['name']} IN A #{record['type']} #{record['ttl']} #{record['rrdatas'].join(' ')}", indent: 4
      end
    end
  end
end
ensure() click to toggle source
# File lib/gclouder/resources/dns.rb, line 160
def self.ensure
  return if Local.list.empty?

  header

  Local.list.each do |region, zones|
    info region, heading: true, indent: 2

    zones.each do |zone|
      project_id = zone_project_id(zone)

      next if skip?(project_id, zone)

      info
      Zone.ensure(project_id, zone["name"], zone["zone"])
      Records.ensure(project_id, zone)
    end
  end
end
header(stage = :ensure) click to toggle source
# File lib/gclouder/resources/dns.rb, line 156
def self.header(stage = :ensure)
  info "[#{stage}] dns", indent: 1, title: true
end
record?(zones, zone, record) click to toggle source
# File lib/gclouder/resources/dns.rb, line 33
def self.record?(zones, zone, record)
  zones.fetch_with_default("name", zone, {}).fetch("records", []).fetch_with_default("name", record, {}).empty?
end
skip?(project_id, zone) click to toggle source
# File lib/gclouder/resources/dns.rb, line 180
def self.skip?(project_id, zone)
  return false if project_id == project["project_id"]
  return false if !cli_args[:skip_cross_project_resources]

  extra_info = " [#{project_id}]" if project_id != project["project_id"]
  warning "#{zone['name']}#{extra_info} [skipping] (cross project resource)", indent: 3, heading: true
  true
end
undefined() click to toggle source
# File lib/gclouder/resources/dns.rb, line 53
def self.undefined
  return {} if Remote.list.empty?

  Remote.list.each_with_object({ "global" => [] }) do |(_region, zones), collection|
    zones.each do |zone|
      # if zone isnt defined locally, then add it along with its associated records
      if !zone?(zones, zone["name"])
        collection["global"] << zone
        next
      end

      next unless zone.key?("records")

      # if record isnt defined locally, create a zone in global (if one doesn't exist), then append record to records field
      zone["records"].each do |record|
        if !zone?(collection["global"], zone["name"])
          zone_collection = zone.dup
          zone_collection["records"] = []
          collection["global"] << zone_collection
        end

        if !record?(zones, zone["name"], record["name"])
          zone_records_append(collection["global"], zone["name"], record)
        end
      end
    end
  end
end
update_zone_record(zones, zone, record, key, value) click to toggle source
# File lib/gclouder/resources/dns.rb, line 27
def self.update_zone_record(zones, zone, record, key, value)
  record = zones.fetch_with_default("name", zone, {}).fetch("records", []).fetch_with_default("name", record, {})
  fatal "couldn't update zone record" if record.empty?
  record[key] = value
end
validate() click to toggle source
# File lib/gclouder/resources/dns.rb, line 82
def self.validate
  return if Local.list.empty?
  header :validate

  failure = false

  Local.list.each do |region, zones|
    info region, indent: 2, heading: true

    unless zones.is_a?(Array)
      failure = true
      bad "zones value should be an array", indent: 3, heading: true
      next
    end

    zones.each do |zone|
      unless zone.is_a?(Hash)
        failure = true
        bad "zone value should be a hash", indent: 3, heading: true
        next
      end

      unless zone.key?("name")
        failure = true
        bad "zone with missing key: name", indent: 3, heading: true
        next
      end

      if zone["name"] !~ /^[a-z0-9\-]+$/
        failure = true
        bad "zone name must only contain lower-case letters, digits or dashes"
        next
      end

      info zone["name"], indent: 3, heading: true

      if zone.key?("zone")
        good "resource has zone specified (#{zone['zone']})", indent: 4
      else
        failure = true
        bad "missing key: zone", indent: 4
      end

      next unless zone.key?("records")

      zone["records"].each do |record|
        info record["name"], indent: 4, heading: true
        if ["A", "CNAME", "PTR", "NS", "TXT"].include?(record["type"])
          good "record has valid type (#{record['type']})", indent: 5
        else
          bad "unknown record type: #{record['type']}", indent: 5
          failure = true
        end

        if record["ttl"].is_a?(Integer)
          good "record has valid ttl (#{record['ttl']})", indent: 5
        else
          bad "record has invalid ttl: #{record['ttl']}", indent: 5
          failure = true
        end

        if record.key?("value") || record.key?("static_ips")
          good "record has a target", indent: 5
        else
          bad "record has no target", indent: 5
          failure = true
        end
      end
    end
  end

  fatal "failure due to invalid config" if failure
end
zone?(zones, zone) click to toggle source
# File lib/gclouder/resources/dns.rb, line 37
def self.zone?(zones, zone)
  zones.fetch_with_default("name", zone, {}).empty?
end
zone_project_id(zone_config) click to toggle source
# File lib/gclouder/resources/dns.rb, line 189
def self.zone_project_id(zone_config)
  return project["project_id"] unless zone_config
  zone_config.key?("project_id") ? zone_config["project_id"] : project["project_id"]
end
zone_record?(zones, zone_name, record_name) click to toggle source
# File lib/gclouder/resources/dns.rb, line 41
def self.zone_record?(zones, zone_name, record_name)
  found_zone = zones.find { |z| z["name"] == zone_name }
  return unless found_zone
  found["records"].find { |r| r["name"] == record_name }.nil?
end
zone_records_append(zones, zone, record) click to toggle source
# File lib/gclouder/resources/dns.rb, line 47
def self.zone_records_append(zones, zone, record)
  zone = zones.fetch_with_default("name", zone, {})
  fatal "couldn't update zone" if zone.empty?
  zone["records"] << record
end