70 lines
2.1 KiB
Ruby
70 lines
2.1 KiB
Ruby
require "erb"
|
|
ROOT_PATH = Pathname.new(File.expand_path("../../..", __FILE__))
|
|
|
|
class TemplateContext
|
|
def initialize(hash)
|
|
hash.each do |key, value|
|
|
singleton_class.send(:define_method, key) { value }
|
|
end
|
|
end
|
|
|
|
def get_binding
|
|
binding
|
|
end
|
|
end
|
|
|
|
class Container
|
|
def initialize(data, ip4:, ip6:, dn42_ipv4:, dn42_ipv6:, **options)
|
|
network = @data["network"] || {}
|
|
zone = data["zone"] || {}
|
|
|
|
ipv4_subnet = NetAddr::CIDR.create(zone["v4_subnet"] || "192.168.10.0/24")
|
|
ipv6_subnet = NetAddr::CIDR.create(zone["v6_subnet"] || "fd7d:aed0:18aa::/48")
|
|
|
|
if subnet = zone["dn42_ipv4_subnet"]
|
|
dn42_ipv4_netmask = NetAddr::CIDR.create(subnet).to_i(:netmask)
|
|
else
|
|
dn42_ipv4_netmask = 24
|
|
end
|
|
|
|
if subnet = zone["dn42_ipv6_subnet"]
|
|
dn42_ipv6_netmask = NetAddr::CIDR.create(subnet).to_i(:netmask)
|
|
else
|
|
dn42_ipv6_netmask = 48
|
|
end
|
|
|
|
ip4 ||= find_address(ipv4_subnet, collect_subnets(network, "ipv4"))
|
|
ip6 ||= find_address(ipv6_subnet, collect_subnets(network, "ipv6"))
|
|
@opts = options.merge(ipv4: format_address(ip4, ipv4_subnet.to_i(:netmask)),
|
|
ipv6: format_address(ip6, ipv6_subnet.to_i(:netmask)))
|
|
@opts[:dn42_ipv4] = format_address(dn42_ipv6, dn42_ipv4_netmask)
|
|
@opts[:dn42_ipv6] = format_address(dn42_ipv4, dn42_ipv6_netmask)
|
|
end
|
|
|
|
def write_config(config_path)
|
|
context = TemplateContext.new(@opts)
|
|
erb = ERB.new(File.read(ROOT_PATH.join("templates", "config.erb")))
|
|
open(config_path, "w+") do |f|
|
|
f.write(erb.result(context.get_binding))
|
|
end
|
|
end
|
|
|
|
private
|
|
def format_address(address, netmask)
|
|
NetAddr::CIDR.create(address, Mask: netmask).desc(IP: true, Short: true)
|
|
end
|
|
|
|
def collect_subnets(network, type)
|
|
network.map do |k,v|
|
|
NetAddr::CIDR.create(v[type]) if v[type]
|
|
end.compact!
|
|
end
|
|
|
|
def find_address(subnet, assigned_subnets)
|
|
subnet.enumerate(Limit: 1E4, Short: true)[1..1E4].each do |cidr|
|
|
assigned = assigned_subnets.find { |s| s.contains?(cidr) || s == cidr }
|
|
return cidr unless assigned
|
|
end
|
|
end
|
|
end
|