cf-cmd: A command-line tool for running CFEngine snippets
Dec 27, 2011 · 3 minute read · Commentscfenginetestingtools
While writing this book, I've had to run hundreds of little CFEngine snippets to run tests, develop examples, verify functionality, or get a solid idea of what some constructs did. After building the typical "test bundle" scaffolding in an editor for the hundredth time, I decided to do something about it. The result is the cf-cmd command. I will let it speak for itself:
$ cf-cmd helpcf-cmd v1.0 - Diego Zamboni diego@zzamboni.org>cf-cmd is a tool that allows you to run small CFEngine snippets quickly,by automatically wrapping them around a standard "test" bundle.The CFEngine Standard Library is automatically included.The following inputs are understood by this tool:help Print this messagelist Print current policyclear Clear current policygo|run Execute current policy using cf-agenttype: Switch to the given promise type(classes:, commands:, databases:, environments:, files:, interfaces:,methods:, outputs:, packages:, processes:, reports:, services:,storage:, vars:)The current promise type is shown in the prompt.All other lines are added literally to the current promise type.Commands can be abbreviated to any part of their name (for example,"r" or "ru" for "run").You can add lines to any of the standard promise types inside the testbundle by switching to the appropriate promise type first.The default promise type is "reports:", to make it easier to quickly printthe value of expressions.You can give the inputs also on the command line, they are interpretedin exactly the same way (make sure to quote things correctly).Examples:cf-cmd '"Flavor: $(sys.flavor)";' list runcf-cmd '"var1 = $(var1)";' vars: '"var1" string => "test";' l rcf-cmd h
You should try out those examples at the end to see what they do. An example interactive session looks like this (I have bolded the inputs to make them easier to see):
$ cf-cmdreports: > "this is a test";reports: > listbody common control {inputs => { "/var/cfengine/inputs/cfengine_stdlib.cf" };bundlesequence => { "test" };}bundle agent test{reports:cfengine::"this is a test";}reports: > run-> Running policy with 'cf-agent -KI -f ./test.cf'R: this is a testreports: > clearreports: > l (abbreviation of "list")body common control {inputs => { "/var/cfengine/inputs/cfengine_stdlib.cf" };bundlesequence => { "test" };}bundle agent test{}reports: > files:-> Switching to files: promise type.files: > "/tmp/test"files: > create => "true",files: > classes => if_repaired("done");files: > reports:-> Switching to reports: promise type.reports: > done::reports: > "Success";reports: > lbody common control {inputs => { "/var/cfengine/inputs/cfengine_stdlib.cf" };bundlesequence => { "test" };}bundle agent test{files:"/tmp/test"create => "true",classes => if_repaired("done");reports:done::"Success";}reports: > run-> Running policy with 'cf-agent -KI -f ./test.cf'-> Created file /tmp/test, mode = 600R: Successreports: >
The interactive prompt supports editing and completion of all commands and promise types - press Tab to view available completions.
You can download the script here:
.
Just put it somewhere in your path. If needed, modify the location of the cfengine_stdlib.cf file on your system (by default it looks for it under /var/cfengine/inputs/). You need Ruby installed (I tested with version 1.9.3).
If you find it useful, or if you find any problems or have any suggestions, please let me know. I'd be happy to hear from you.