#!/usr/bin/env ruby require 'net/http' require 'netaddr' require 'json' require 'pathname' LXC_ROOT = Pathname.new("/etc/lxc") CONTAINER_DATA = LXC_ROOT.join("container.json") class Hetzner BASE_URI = URI("https://robot-ws.your-server.de") def initialize(user, password) @user = user @password = password end def get(path) resp = perform_request(Net::HTTP::Get.new(uri_for(path))) JSON.parse(resp.body) end def post(path, params={}) req = Net::HTTP::Post.new(uri_for(path)) req.set_form_data(params) resp = perform_request(req) JSON.parse(resp.body) end def put(path, params={}) req = Net::HTTP::Put.new(uri_for(path)) req.set_form_data(params) resp = perform_request(req) JSON.parse(resp.body) end def delete(path) perform_request(Net::HTTP::Delete.new(uri_for(path))) end private def uri_for(path) u = BASE_URI.clone u.path = path u end def perform_request(req) req.basic_auth(@user, @password) resp = Net::HTTP.start(BASE_URI.hostname, BASE_URI.port, use_ssl: true) do |http| http.request(req) end if resp.code.start_with? "2" return resp else raise StandardError.new("failed to perform request: #{resp.inspect}") end end end def update_hetzner_rdns6(user, password, json) api = Hetzner.new(user, password) rdns = api.get("/rdns") records = {} rdns.each do |val| rec = val["rdns"] cidr = NetAddr::CIDR.create(rec["ip"]) next if cidr.version == 4 records[cidr.ip] = rec["ptr"] end json["network"].each do |host, data| cidr = data["ipv6"] next if cidr.nil? ipv6 = NetAddr::CIDR.create(cidr).ip hostname = data["rdns6"] || "#{host}.higgsboson.tk" ptr = records.delete(ipv6) if ptr.nil? or ptr != hostname api.post("/rdns/#{ipv6}", ptr: hostname) end end records.each do |ip, ptr| api.delete("/rnds/#{ip}") end end credentials = File.read("/etc/lxc/hetzner.key") json = JSON.load(File.open(CONTAINER_DATA)) user, password = credentials.split(":") update_hetzner_rdns6(user, password, json) puts("ok")