#!/usr/bin/env ruby require 'json' require 'erb' require 'netaddr' require 'fileutils' require 'pathname' require 'ostruct' LXC_ROOT = Pathname.new("/etc/lxc") ZONE_PATH = LXC_ROOT.join("zones") TEMPLATE_PATH = LXC_ROOT.join("templates") CONTAINER_DATA = LXC_ROOT.join("container.json") LXC_ZONE = ZONE_PATH.join("eve.higgsboson.tk.zone") DNS_CONTAINER = "dns" def atomic_write(path, content) temp_path = path.to_s + ".tmp" File.open(temp_path, 'w+') do |f| f.write(content) end FileUtils.mv(temp_path, path) end class ZoneData < OpenStruct def get_binding binding end def ip(subnet) NetAddr::CIDR.create(subnet).ip(Short: true) end def pointers(&block) subnet_arpa = subnet.arpa version = subnet.version data["network"].each do |name, data| next unless data["ipv#{version}"] arpa = NetAddr::CIDR.create(data["ipv#{version}"]).arpa addr = arpa[0, arpa.size - subnet_arpa.size - 1] yield addr, name end end end def reverse_zone(data, subnet) subnet = NetAddr::CIDR.create(subnet) zone_data = ZoneData.new(data: data, subnet: subnet).get_binding rdns_zone_template = File.read(TEMPLATE_PATH.join("rdns-zone.erb")) rdns_path = ZONE_PATH.join(subnet.arpa.gsub(/\.$/, "")) template = ERB.new(rdns_zone_template, nil, '-').result(zone_data) [rdns_path, template] end def main json = JSON.load(File.open(CONTAINER_DATA)) json["zone"]["serial"] += 1 zone_data = ZoneData.new(data: json) lxc_zone_template = File.read(TEMPLATE_PATH.join("lxc-zone.erb")) zone = ERB.new(lxc_zone_template, nil, '-').result(zone_data.get_binding) atomic_write(LXC_ZONE, zone) atomic_write(*reverse_zone(json, json["zone"]["v4_subnet"])) atomic_write(*reverse_zone(json, json["zone"]["v6_subnet"])) atomic_write(CONTAINER_DATA, JSON.pretty_generate(json)) system("lxc-attach", "-n", DNS_CONTAINER, "--", "rndc", "reload") end main