network/nix/pkgs/subnetplan/render.rb

140 lines
2.7 KiB
Ruby

#!/usr/bin/env ruby
require 'ipaddress_2'
require 'erb'
TABLE_WIDTH = 8
class Subnet
attr_reader :addr, :desc
attr_accessor :addr_visible
def initialize addr, desc
@addr = addr
@desc = desc
@addr_visible = false
end
end
class Group
attr_accessor :net, :blocks
def initialize net, blocks
@net = net
@blocks = blocks
end
end
class Block
attr_accessor :label, :name
def initialize label, name
@label = label
@name = name
end
end
nets = []
while line = gets
a, desc = line.split(/ /, 2)
addr = IPAddress.parse a
desc.chomp!
nets << Subnet.new(addr, desc)
end
nets.sort_by! { |net| net.addr }
collisions = 0
prev = nil
nets.each do |net|
if prev and (net.addr.include?(prev.addr) or prev.addr.include?(net.addr))
STDERR.puts "#{prev.addr} and #{net.addr} overlap"
collisions += 1
end
prev = net
end
exit 1 if collisions > 0
GROUP_PREFIX = 16
groups = {}
nets.each do |net|
group = net.addr.supernet(GROUP_PREFIX).to_s
(groups[group] ||= []) << net
end
max_prefix = [groups.collect { nets.collect { |net| net.addr.prefix }.max }.max, 64].min
groups = groups.collect do |group, nets|
allnet = nets[0].addr.clone
while allnet.prefix > 0 and not allnet.include?(nets[nets.size - 1].addr)
allnet = allnet.supernet(allnet.prefix - 1)
end
blocks = []
row = []
allnet.subnet(max_prefix).each do |addr|
net = nets.select { |net| net.addr.include? addr }[0]
label = net ? "#{addr}/#{net.addr.prefix}" : addr.to_s
row << Block.new(label, net ? net.desc : "")
if row.size >= TABLE_WIDTH
blocks << row
row = []
end
end
blocks << row if row.size > 0
blocks.each do |row|
prev_name = nil
row.each_with_index do |block|
block.label = "" if prev_name == block.name
prev_name = block.name
end
end
Group.new(allnet, blocks)
end
def background_color desc
case desc
when "core"
"#9F9F9F"
when "mgmt"
"#FF3F3F"
when "c3d2"
"yellow"
when "serv", "cluster"
"orange"
when "pub"
"#7FFF7F"
when /priv(\d+)/
"hsl(240, 80%, #{60 + 5 * ($1.to_i % 8)}%)"
else
"white"
end
end
html = ERB::new <<~EOF
<html>
<head>
<title>Subnetwork Plan</title>
</head>
<body>
<table border="1">
<% groups.each do |group| %>
<tr>
<th colspan="<%= TABLE_WIDTH %>"><%= group.net.to_string %></th>
</tr>
<% group.blocks.each do |row| %>
<tr>
<% row.each do |block| %>
<td style="background-color: <%= background_color(block.name) %>"><%= block.label %> <%= block.name %></td>
<% end %>
</tr>
<% end %>
<% end %>
</table>
</body>
</html>
EOF
puts html.result