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 Ptacek said...

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

Matt Franz said...

Yeah but that is so ugly...