class Roadworker::Client

Public Class Methods

new(options = {}) click to toggle source
# File lib/roadworker/client.rb, line 6
def initialize(options = {})
  @options = OpenStruct.new(options)
  @options.logger ||= Logger.new($stdout)
  String.colorize = @options.color
  @options.route53 = Aws::Route53::Client.new
  @health_checks = HealthCheck.health_checks(@options.route53, :extended => true)
  @options.health_checks = @health_checks
  @route53 = Route53Wrapper.new(@options)
end

Public Instance Methods

apply(file) click to toggle source
# File lib/roadworker/client.rb, line 16
def apply(file)
  dsl = load_file(file)
  updated = false

  if dsl.hosted_zones.empty? and not @options.force
    log(:warn, "Nothing is defined (pass `--force` if you want to remove)", :yellow)
  else
    updated = walk_hosted_zones(dsl)
  end

  if updated and @options.health_check_gc
    HealthCheck.gc(@options.route53, :logger => @options.logger)
  end

  return updated
end
export() { |exported, method(:convert)| ... } click to toggle source
# File lib/roadworker/client.rb, line 33
def export
  exported = @route53.export

  if block_given?
    yield(exported, DSL.method(:convert))
  else
    DSL.convert(exported)
  end
end
test(file) click to toggle source
# File lib/roadworker/client.rb, line 43
def test(file)
  dsl = load_file(file)
  DSL.test(dsl, @options)
end

Private Instance Methods

collection_to_hash(collection, *keys) { |item| ... } click to toggle source
# File lib/roadworker/client.rb, line 177
def collection_to_hash(collection, *keys)
  hash = {}

  collection.each do |item|
    if block_given?
      key_list = yield(item)
    else
      key_list = keys.map do |k|
         item.send(k)
      end
    end

    hash[key_list] = item
  end

  return hash
end
load_file(file) click to toggle source
# File lib/roadworker/client.rb, line 50
def load_file(file)
  dsl = nil

  if file.kind_of?(String)
    open(file) do |f|
      dsl = DSL.define(f.read, file).result
    end
  else
    dsl = DSL.define(file.read, file.path).result
  end

  return dsl
end
normalize_id(id) click to toggle source
# File lib/roadworker/client.rb, line 195
def normalize_id(id)
  id.sub(%r!^/hostedzone/!, '') if id
end
walk_hosted_zones(dsl) click to toggle source
# File lib/roadworker/client.rb, line 64
def walk_hosted_zones(dsl)
  updated = false

  expected = collection_to_hash(dsl.hosted_zones) {|i| [i.name, i.vpcs.empty?, normalize_id(i.id)] }
  actual   = collection_to_hash(@route53.hosted_zones) {|i| [i.name, i.vpcs.empty?, normalize_id(i.id)] }

  expected.each do |keys, expected_zone|
    name, private_zone, id = keys
    next unless matched_zone?(name)
    if id
      actual_zone = actual.delete(keys)
      unless actual_zone
        log(:warn, "Hosted zone not found", :yellow, "#{name} (#{id})")
        next
      end
    else
      actual_keys, actual_zone = actual.find {|(n, p, _), _| n == name && p == private_zone }
      actual.delete(actual_keys) if actual_keys
    end

    unless actual_zone
      updated = true
      actual_zone = @route53.hosted_zones.create(name, :vpc => expected_zone.vpcs.first)
    end

    updated = true if walk_vpcs(expected_zone, actual_zone)
    updated = true if walk_rrsets(expected_zone, actual_zone)
  end

  actual.each do |keys, zone|
    name = keys[0]
    next unless matched_zone?(name)
    zone.delete
    updated = true
  end

  updated
end
walk_rrsets(expected_zone, actual_zone) click to toggle source

@param [OpenStruct] expected_zone Roadworker::DSL::Hostedzone#result @param [Roadworker::Route53Wrapper::HostedzoneWrapper] actual_zone

# File lib/roadworker/client.rb, line 134
def walk_rrsets(expected_zone, actual_zone)
  change_batch = Batch.new(actual_zone, health_checks: @options.health_checks, logger: @options.logger, dry_run: @options.dry_run)

  expected = collection_to_hash(expected_zone.rrsets, :name, :type, :set_identifier)
  actual   = actual_zone.rrsets.to_h.dup

  expected.each do |keys, expected_record|
    name, type, set_identifier = keys
    actual_record = actual.delete(keys)

    # XXX: normalization should be happen on DSL as much as possible, but ignore_patterns expect no trailing dot
    # and to keep backward compatibility, removing then dot when checking ignored_patterns.
    name_for_ignore_patterns = name.sub(/\.\z/, '')
    if expected_zone.ignore_patterns.any? { |pattern| pattern === name_for_ignore_patterns }
      log(:warn, "Ignoring defined record in DSL, because it is ignored record", :yellow) do
        "#{name} #{type}" + (set_identifier ? " (#{set_identifier})" : '')
      end
      next
    end

    if actual_record
      unless actual_record.eql?(expected_record)
        change_batch.update(expected_record)
      end
    else
      change_batch.create(expected_record)
    end
  end

  actual.each do |(name, _type, _set_identifier), record|
    # XXX: normalization should be happen on DSL as much as possible, but ignore_patterns expect no trailing dot
    # and to keep backward compatibility, removing then dot when checking ignored_patterns.
    name = name.sub(/\.\z/, '')
    if expected_zone.ignore_patterns.any? { |pattern| pattern === name }
      next
    end

    change_batch.delete(record)
  end

  change_batch.request!(@options.route53)
end
walk_vpcs(expected_zone, actual_zone) click to toggle source
# File lib/roadworker/client.rb, line 103
def walk_vpcs(expected_zone, actual_zone)
  updated = false

  expected_vpcs = expected_zone.vpcs || []
  actual_vpcs = actual_zone.vpcs || []

  if not expected_vpcs.empty? and actual_vpcs.empty?
    log(:warn, "Cannot associate VPC to public zone", :yellow, expected_zone.name)
  else
    (expected_vpcs - actual_vpcs).each do |vpc|
      actual_zone.associate_vpc(vpc)
      updated = true
    end

    unexpected_vpcs = actual_vpcs - expected_vpcs

    if unexpected_vpcs.length.nonzero? and expected_vpcs.length.zero?
      log(:warn, "Private zone requires one or more of VPCs", :yellow, expected_zone.name)
    else
      unexpected_vpcs.each do |vpc|
        actual_zone.disassociate_vpc(vpc)
        updated = true
      end
    end
  end

  updated
end