Saturday, April 28, 2007

Saturday Mornings with YAML

ubuntutrinux is progressing nicely to the point that I was able to replace my OpenBSD Internet-facing facing pf box. Sure iptables sucks for real firewalls, but I burned Trinux on a CD with a static set of rules on a Old Celeron-based Optiplex GX100 with no hard drive. Good enough. BTW, I added frobe to be able to export netflow data. With device file creation mostly complete, I'm moving to the initialization scripts and to a new YAML configuration scheme copy the spirit (if not the letter) of pfsense.

Right now I'm playing with something like:

network:
hostname: franzfw
interfaces:
eth0:
address: dhcp
eth2:
address: 192.168.100.1
netmask: 255.255.255.0
routes:
-'192.168.169.0/24': 192.168.100.2
forwarding: true
And when I run a little "check" script you see:

franz-g4:~/dev/playin/ruby mdfranz$ ruby ycheck.rb config.yaml
yf is a:Hash
{"network"=>
{"routes"=>{"-'192.168.169.0/24'"=>"192.168.100.2"},
"forwarding"=>true,
"interfaces"=>
{"eth0"=>{"address"=>"dhcp"},
"eth2"=>{"netmask"=>"255.255.255.0", "address"=>"192.168.100.1"}},
"hostname"=>"franzfw"}}
With the following keys:
-network
Hostname:franzfw
interfaces is a:Hash
Configuring:eth0
Configuring:eth2
With the script that created this...
require 'yaml'
require 'pp'
yf = YAML.load_file(ARGV[0])
print "yf is a:"
print yf.class
print "\n"
pp yf
print "With the following keys:\n"
yf.keys.each { |k| puts "-" + k }
puts "Hostname:" + yf['network']['hostname']
interfaces = yf['network']['interfaces']
print "interfaces is a:"
print interfaces.class
print "\n"
print interfaces.keys.each { |i| puts "Configuring:" + i }

Don't have time to get into the details (see the YAML Cookbook for more info) but there were a couple of areas I got hung up on:
  • Using tabs instead of whitespaces. Ruby YAML doesn't like tabs, but if your vimrc is setup for Python you should be good to go.
  • Getting hashes instead of arrays (and vice versa). Play around with ident's and -'s until you get what you need
XML parsing (or creating XML configuration files) isn't something I do on a daily basis (thank God!) but I've done enough to know that this is a lot easier to read and parse.

Since ruby is so small (less than 2MB compressed) it will be included as part of the core and probably everything outside /init may use it.

4 comments:

Anonymous said...

> Using tabs instead of whitespaces. Ruby YAML doesn't like tabs

Tabs for indentation? - I thought YAML specifically disallowed that...

KarlMW.

Matt Franz said...

You are correct. If you set your editor to replace tabs with spaces it is fine.

Thomas said...

puts "yf is a #{ yf.class }"

Matt Franz said...

Yeah but that is so ugly...