From: Robert Klemme Date: 2010-10-26T16:48:12+09:00 Subject: Re: DSL and indirection question On Mon, Oct 25, 2010 at 10:30 PM, Matt Lawrence wrote: > On Tue, 26 Oct 2010, James Edward Gray II wrote: > >> On Oct 25, 2010, at 2:20 PM, Matt Lawrence wrote: >> >>> I'm trying to figure out the best way of writing a script that describes >>> various requirements in the form of "12.34.56" (from a requirement document) >>> that I can then create methods for reporting, verifying and remediating the >>> requirment on a system. >>> >>> This is script for checking and fixing systems based on a bunch of >>> security requirements.  There are a couple of hundred rules and a few >>> hundred systems.  I am thinking about building a hash of Procs, but I think >>> it is going to be too ugly.  Any suggestions on a clean and easy to read way >>> of doing this? >> >> This almost sounds like a job for Chef or Puppet, if I understood >> correctly. > > Chef or Puppet would not be practical in this environment for various > reasons.  This place is not in the Stone Age like my last job, they're more > like the Bronze Age.  I am campaigning to at least get Cfengine set up. > >> I'm not really getting what you are aiming for here.  Can you show a >> simple example or two? > > I have a directory full of results from a security scan, on file per system. >  In that file each line starts with a rule number, like "12.34" and has a > pass/fail/skipped result. > > What I probably want to do is to create a class for rules with each rule > having methods for testing and fixing each issue found.  I know I can brute > force the script and it will look ugly or I can ask for help on doing a > nifty DSL in the new favoured Ruby style. Rule = Struct.new :name do def test(&b) if b @test = b else @test end end # same for fix end AllRules = Hash.new {|h,k| h[k.freeze] = Rule[k]} AllRules["12.34"].test |system| puts "Testing rule on system #{system}"} AllRules["12.34"].fix {|system| puts "Fixing rule on system #{system}"} or AllRules["12.34"].tap do |rule| rule.test do |system| puts "Testing rule on system #{system}" end rule.fix do |system| puts "Fixing rule on system #{system}" end end RuleResult = Struct.new :rule, :result do def self.parse(str) raise ArgumentError, "Cannot parse %p" % str unless /^(\d+(?:\.\d+)*).*(pass|fail|skip)/ self[AllRules[$1], $2.to_sym] end alias __result= result= def result=(x) __result= x.to_sym end def ok? result == :pass end end Something like this? Cheers robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/