<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Chapeau</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/" />
    <link rel="self" type="application/atom+xml" href="http://chapeau.freevariable.com/atom.xml" />
    <id>tag:chapeau.freevariable.com,2009-03-27://1</id>
    <updated>2011-11-02T22:25:30Z</updated>
    <subtitle>Short technical articles about computing.</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.25</generator>

<entry>
    <title>Exporting versioned Wallaby configurations</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2011/11/exporting-versioned-wallaby-configurations.html" />
    <id>tag:chapeau.freevariable.com,2011://1.31</id>

    <published>2011-11-02T22:25:27Z</published>
    <updated>2011-11-02T22:25:30Z</updated>

    <summary>Wallaby stores versioned configurations in a database. Wallaby API clients can access older versions of a node&#8217;s configuration by supplying the version option to the Node#getConfig method. Sometimes, though, we&#8217;d like to inspect individual configurations in greater detail than the...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="wallaby" label="wallaby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>Wallaby stores versioned configurations in a database.  <a href="http://getwallaby.com/the-wallaby-api/">Wallaby API</a> clients can access older versions of a node&#8217;s configuration by supplying the <code>version</code> option to the <code>Node#getConfig</code> method.  Sometimes, though, we&#8217;d like to inspect individual configurations in greater detail than the API currently allows.</p>

<p>The <a href="http://git.fedorahosted.org/git/?p=grid/wallaby.git">Wallaby git repository</a> now contains a <a href="http://git.fedorahosted.org/git/?p=grid/wallaby.git;a=blob;f=lib/mrg/grid/config/shell/cmd_versioned_config_export.rb;hb=HEAD">command</a> to export versioned configurations from a database to flat text files.  Clone the repository or just download the file and then place <code>cmd_versioned_config_export.rb</code> somewhere in your <code>WALLABY_SHELL_COMMAND_PATH</code>, and you&#8217;ll be able to invoke it like this:</p>

<pre><code>Usage:  wallaby vc-export DBFILE
exports versioned configurations from DBFILE to plain text files
    -h, --help                       displays this message
        --verbose                    outputs information about command progress
    -o, --output-dir DIR             set output directory to DIR
        --earliest NUM               output only the earliest NUM configurations
        --latest NUM                 output only the most recent NUM configurations
        --since DATE                 output only configurations since the given date
</code></pre>

<p>It will create a directory (called <code>snapshots</code> by default) with subdirectories for each versioned configuration; each of these will be timestamped with the time of the configuration.  Within each version directory, there will be directories for node configurations and stored group configurations.  (If you&#8217;re using an older version of Wallaby, the only stored group configuration will be for the default group.  Versioned configurations generated with a fairly recent version of Wallaby, on the other hand, will have stored configurations for more groups and should also have useful information about node memberships in the configuration file.)</p>

<p>(cross-posted from <a href="http://getwallaby.com">getwallaby.com</a>)</p>]]>
        
    </content>
</entry>

<entry>
    <title>Wallaby paper at SC11</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2011/09/wallaby-paper-at-sc11.html" />
    <id>tag:chapeau.freevariable.com,2011://1.30</id>

    <published>2011-09-08T18:20:53Z</published>
    <updated>2011-09-08T18:21:00Z</updated>

    <summary>I&apos;m pleased to announce that our paper &quot;Wallaby: A Scalable Semantic Configuration Service for Grids and Clouds&quot; will be presented at SC11 in the &quot;State of the Practice&quot; track on Clouds and Grids. If you&apos;re going to be at SC,...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="wallaby" label="wallaby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>I'm pleased to announce that our paper "<a href="http://web.willbenton.com/research/sc11">Wallaby: A Scalable Semantic Configuration Service for Grids and Clouds</a>" will be <a href="http://sc11.supercomputing.org/schedule/event_detail.php?evid=sprac111">presented at SC11 in the "State of the Practice" track on Clouds and Grids</a>.  If you're going to be at SC, I hope we'll be able to chat about Wallaby!</p>]]>
        
    </content>
</entry>

<entry>
    <title>Write-once, defaultable constants in Ruby</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2011/09/write-once-defaultable-constants-in-ruby.html" />
    <id>tag:chapeau.freevariable.com,2011://1.29</id>

    <published>2011-09-02T21:17:46Z</published>
    <updated>2011-09-02T21:18:30Z</updated>

    <summary>Ruby constants are a nice place to put application configuration information, but they can be inflexible if you want to defer initialization until later &#x2014; for example, if you want a constant to have a given value at application startup...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>Ruby constants are a nice place to put application configuration information, but they can be inflexible if you want to defer initialization until later &#x2014; for example, if you want a constant to have a given value at application startup only if a certain environment variable or command&#x2013;line parameter is set.  I like the idea of the single&#x2013;assignment variables that you get in many functional and logic languages, and I also like the idea that constants only really need to be constant <em>after</em> they've been read once.  (See <a href="http://web.willbenton.com/research/vmcai-2011">this paper</a> for some interesting implications of that idea in Java programs.)</p>

<p>The <a href="https://github.com/willb/quiescent"><em>quiescent</em> gem</a> is a little hack I put together to make it easy to have write-once, defaultable constants in your Ruby programs.  A <em>quiescing constant</em>, or <em>quiescent</em>, has an optional default value (either an explicit value or a block to calculate that value), and can be assigned to at most once in a program execution.  Once the quiescent is written to, its value quiesces and it becomes a normal constant.  If it is read without being explicitly quiesced, it assumes the default value (or the result of executing the default-value block) and becomes a normal constant.  Here's an example to make things clearer:</p>

<script src="https://gist.github.com/1189849.js"> </script><noscript>Visit <a href="http://chapeau.freevariable.com/2011/09/write-once-defaultable-constants-in-ruby.html">this post</a> in a browser with Javascript support to see the embedded code example.</noscript>

<p>Get quiescent from <a href="https://github.com/willb/quiescent">GitHub</a> or from <a href="http://rubygems.org/gems/quiescent">RubyGems</a>.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Gliss 0.2.0 release and a gliss example</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2011/07/gliss-020-release-and-a-gliss-example.html" />
    <id>tag:chapeau.freevariable.com,2011://1.28</id>

    <published>2011-07-22T01:49:13Z</published>
    <updated>2011-07-22T01:55:37Z</updated>

    <summary>Earlier today, I released version 0.2.0 of Gliss, a lightweight tool for inspecting and processing tagged annotations in git repositories. Since I last wrote about gliss, there have been a few improvements worth mentioning; I&#8217;ll briefly go over them here:...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="git" label="git" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="gliss" label="gliss" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="gloss" label="gloss" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>Earlier today, I released <a href="http://rubygems.org/gems/gliss/versions/0.2.0">version 0.2.0</a> of <a href="https://github.com/willb/gliss">Gliss</a>, a lightweight tool for inspecting and processing tagged annotations in git repositories.  Since I <a href="http://chapeau.freevariable.com/2011/01/grepping-for-git-glosses-with-gliss.html">last wrote about gliss</a>, there have been a few improvements worth mentioning; I&#8217;ll briefly go over them here:</p>

<ul>
<li><em>Support for malformed glosses</em>.  The gliss conventions specify that a gloss tag must start at the beginning of a new line.  If you have some commits that <em>don&#8217;t</em> follow the conventions, though, you might miss their glosses.  By using the <code>--permissive</code> option, you can find gloss candidates that are indented or that start in the middle of the line.</li>
<li><em>Support for multiple tag filters</em>.  In previous releases of gliss, you could use the <code>--filter</code> option to specify a regular expression that all printed tags must match.  Now, supplying multiple <code>--filter</code> options will return all glosses that match <code>any</code> of the provided expressions.</li>
<li><em>Support for printing the whole commit in which matching glosses appear</em>.  The <code>--whole-commit</code> option (`-w</code> for short) will cause gliss to print every commit containing a matching gloss.  You may need this option if you&#8217;re compiling release notes and the gloss text for a given gloss doesn&#8217;t contain enough context.</li>
<li><em>Support for Markdown-formatted glosses</em>.  If you have the <a href="http://rubygems.org/gems/maruku">Maruku</a> gem installed, gliss can treat glosses with certain tags as containing <a href="http://daringfireball.net/projects/markdown/">Markdown</a>-formatted text and render them in well-formed HTML or LaTeX.  Use the <code>--format-glosses-matching</code> option to specify regular expressions for gloss tags whose texts should be rendered via Markdown and <code>--markdown-output</code> to specify LaTeX or HTML output.  This is especially useful for streamlining automatic documentation generation from gloss texts.</li>
</ul>

<p>Install the latest version of gliss with <code>gem install gliss</code> (and, optionally, <code>gem install maruku</code>).</p>

<p>One aspect of gliss that some users who don&#8217;t have much exposure to <code>git</code> find confusing is how it selects a range of commits to process.  Ordinarily, you&#8217;ll invoke gliss with two arguments:  <code>FROM</code> and <code>TO</code>, both of which can be SHAs, branch names, or tag names.  The gliss on-line help tells you that this will process all of the commits reachable from <code>TO</code> but not from <code>FROM</code>.  If this doesn&#8217;t make a lot of sense, or if you aren&#8217;t sure what it means to be &#8220;reachable&#8221; from a branch or tag, read on.</p>

<p><img src="http://chapeau.freevariable.com//gliss-example.png" alt="Example git repository" title="gliss-example.png" border="0" width="505" height="369" /></p>

<p>The image above shows a simple git repository.  In this image, commits have a single-letter identifier and only contain a pointer to their immediate ancestor.  By transitively following the ancestry relationship, we can get from any commit to the root commit of the repository.  Note that git commits under the ancestry relation form a graph; more specifically, it is a directed graph (because ancestry is not a symmetric relation) and an acyclic graph (because a node may not transitively have itself as an ancestor).</p>

<p>In this diagram, we have two branches:  <em>master</em> and <em>topic</em>, and two tags:  <em>1.1</em> and <em>1.0</em>.  Tags are essentially immutable pointers to particular commits; branches are pointers that can track a stream of development.  <em>A</em> is the root commit, <em>B</em> is the commit pointed to by <em>1.0</em>, <em>E</em> is the commit pointed to by <em>1.1</em>, and so on.  Let&#8217;s look at some example gliss use cases to see how we can use this information.</p>

<p>Say we wanted to see what had changed between tags <em>1.0</em> and <em>1.1</em>.  We&#8217;d give <em>1.0</em> as the <code>FROM</code> argument and <em>1.1</em> as the <code>TO</code> argument.  This would examine all of the commits reachable from 1.1, but not from 1.0.  The commits reachable from <em>1.1</em> are <em>A</em>, <em>B</em>, <em>C</em>, <em>D</em>, and <em>E</em> (<em>E</em> is a merge commit, which is why it has multiple parents); of these, <em>B</em> and <em>A</em> are also reachable from <em>1.0</em>.  Therefore, in this case, gliss would only search for glosses in <em>C</em>, <em>D</em>, and <em>E</em>.</p>

<p>Alternatively, we might want to see which commits were reachable from <em>topic</em> but not from <em>master</em>.  In this case, gliss would process only <em>F</em>.  Note, however, that the <code>TO</code> and <code>FROM</code> arguments are not interchangeable:  using gliss on the commits reachable from <em>master</em> but not from <em>topic</em> would give us the glosses <em>C</em>, <em>E</em>, and <em>G</em>.</p>

<p>Please contact me or file a <a href="https://github.com/willb/gliss/issues">issue report</a> if you have problems with or suggestions for gliss.  I hope you find it useful!</p>
]]>
        

    </content>
</entry>

<entry>
    <title>When software-dependency philosophies collide</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2011/07/when-software-dependency-philosophies-collide.html" />
    <id>tag:chapeau.freevariable.com,2011://1.27</id>

    <published>2011-07-07T03:38:01Z</published>
    <updated>2011-07-07T16:29:58Z</updated>

    <summary>Earlier today, I released version 0.4.0 of Rhubarb, a little object-graph persistence library for Ruby built on top of SQLite. Rhubarb 0.4.0 adds no new features, unless you consider &#8220;working with recent releases of the sqlite3 gem&#8221; to be a...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="fedora" label="fedora" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="gems" label="gems" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rhubarb" label="rhubarb" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rpm" label="rpm" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="sqlite3" label="sqlite3" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>Earlier today, I released <a href="http://rubygems.org/gems/rhubarb/versions/0.4.0">version 0.4.0</a> of <a href="http://git.fedorahosted.org/git/?p=grid/rhubarb.git">Rhubarb</a>, a little object-graph persistence library for Ruby built on top of SQLite.  Rhubarb 0.4.0 adds no new features, unless you consider &#8220;working with recent releases of the <tt>sqlite3</tt> gem&#8221; to be a feature.  The case of Rhubarb 0.4.0 is interesting, though, because it exposes a fundamental incompatibility between the package-dependency model of RubyGems and that of operating-system distributions.</p>

<p>The <tt>sqlite3</tt> gem (formerly known as <tt>ruby-sqlite3</tt>) introduced some nontrivial semantic and interface incompatibilities between versions 1.2 and 1.3; as far as I can tell, 1.3 is a near-total rewrite.  The main problems I ran into with Rhubarb were related to prepared statements and to the (now deprecated and subtly broken) <a href="http://rdoc.info/github/luislavena/sqlite3-ruby/master/SQLite3/Translator">&#8220;type translation&#8221;</a> functionality that is meant to take untyped SQLite values and convert them to Ruby objects of an appropriate type.<small><sup>1</sup></small></p>

<p>In some circles, backwards incompatibility is anathema, especially if (as in this case) it entails deprecating useful functionality and providing no replacements or workarounds.  However, in the Ruby world, it essentially doesn&#8217;t matter:  the RubyGems package manager is designed to let you install multiple versions of a gem package simultaneously; gems can specify that they will only work with a particular minor-version series of a dependency; and there are a <a href="http://gembundler.com/">whole</a> <a href="https://rvm.beginrescueend.com/">host</a> of external tools to make it easier to install an application in a private, application-specific local environment with the correct versions of its dependencies.<small><sup>2</sup></small></p>

<p>Since production Ruby applications can run indefinitely against an older version of a dependency without affecting the rest of the system, there is really little disincentive to breaking backwards compatibility.  Unless, that is, someone wants to package production Ruby applications as part of Fedora or another Linux distribution.  In that case, the packager is likely stuck with just the most recent stable version of the dependency &#8212; and this version must work for every application packaged with the distribution.  Since it is typically <a href="http://fedoraproject.org/wiki/Packaging:No_Bundled_Libraries">not an option</a> for downstream packagers to install &#8220;local&#8221; versions of packages, this means that they are faced with an unappealing choice:  break (and thus don&#8217;t ship) some software or package unnecessarily conservative versions of dependencies.</p>

<p>This problem is especially interesting since, due to the impedance mismatch between these packaging cultures, there is no obviously correct solution.</p>

<p><br/><br/></p>

<p><small><sup>1</sup></small> I observed several related problems that led to <em>a lot</em> of test suite and application failures:</p>

<ol>
<li>In the 1.2 series, automatic type translation caused field values to be converted based on the given type of the column; in newer versions (in which automatic type translation is officially deprecated), conversion proceeds based on properties of the string representation of the value.  So, for example, a <tt>varchar</tt> field containing the value <tt>&#8220;fooblitz&#8221;</tt> would become a Ruby <tt>String</tt>, but a <tt>varchar</tt> field containing the value <tt>&#8220;1234&#8221;</tt> would become a Ruby <tt>Fixnum</tt>.</li>
<li>Enabling (deprecated) automated type-translation support in the version of <tt>sqlite3-ruby</tt> in Fedora 15 breaks the <a href="http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html#section"><tt>results_as_hash</tt></a> facility that allows addressing rows by column name and not merely column index.  (I understand this is fixed in <a href="http://groups.google.com/group/sqlite3-ruby/browse_thread/thread/72186e494d6c10dc?pli=1">a more recent release</a>.)</li>
<li>Attempting to install explicit type translations results in a deprecation warning, leaving no reasonable way to work around the deprecation of automatic type translation.</li>
<li>Foreign-key triggers are apparently now incompatible with prepared statements, resulting in confusing failures upon database close if both are enabled.</li>
</ol>

<p><small><sup>2</sup></small> While the local-environment idea is well-known, notably in the Java world and anywhere that people ship software that uses Boost, some environments take the basic philosophy further still.  Consider the build process for applications using the <a href="https://github.com/basho/webmachine/">webmachine REST framework</a>, which <em>clones and checks out particular versions of webmachine&#8217;s dependencies</em>!</p>
]]>
        
    </content>
</entry>

<entry>
    <title>Node tagging in a Wallaby client library</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2011/06/node-tagging-in-a-wallaby-client-library.html" />
    <id>tag:chapeau.freevariable.com,2011://1.26</id>

    <published>2011-06-20T14:28:37Z</published>
    <updated>2011-06-20T14:28:39Z</updated>

    <summary>In an earlier post, I presented a technique for adding node tagging to Wallaby without adding explicit tagging support to the Wallaby API. Node tags are useful for a variety of reasons: they can correspond to informal user-supplied classifications of...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>In an <a href="http://chapeau.freevariable.com/2011/05/using-wallaby-groups-to-implement-node-tagging.html">earlier post</a>, I presented a technique for adding <em>node tagging</em> to Wallaby without adding explicit tagging support to the Wallaby API.  Node tags are useful for a variety of reasons:  they can correspond to informal user-supplied classifications of nodes or machine-generated system attributes (e.g. "64-bit", "high-memory", "infiniband").  Since we implemented tags as special Wallaby groups, they may contain configuration information (although they don't need to) and will be advertised as one of the machine's Condor attributes.</p>

<p>The Wallaby source repository now includes a <a href="http://git.fedorahosted.org/git/?p=grid/wallaby.git;a=blob;f=extensions/tagging.py;hb=HEAD">small Python module</a> that patches the <a href="http://chapeau.freevariable.com/2010/12/extending-wallaby-with-a-python-client-library.html">Wallaby python client library</a> with idiomatic tagging support:  namely, you can ask the store for the name of the group that represents the partition between tags and groups, and you can call <tt>getTags()</tt> and <tt>modifyTags()</tt> methods on <tt>Node</tt> objects, as well as inspect the tags property of a <tt>Node</tt>.  This will appear in Wallaby packages in the future, but you don't have to be that adventurous to try it out now!  To use it, clone the repository and put <tt>extensions/tagging.py</tt> and <tt>schema/wallaby.py</tt> somewhere in your <tt>PYTHONPATH</tt>.  Then follow along with this transcript:</p>

<p><script src="https://gist.github.com/1035680.js?file=gistfile1.py"></script><noscript>Visit this post in a browser with JavaScript support (not a feed reader) to see the embedded transcript.</noscript></p>

<p>I appreciate any feedback or comments on this library.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>RESTful manipulation of versioned data</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2011/06/restful-manipulation-of-versioned-data.html" />
    <id>tag:chapeau.freevariable.com,2011://1.25</id>

    <published>2011-06-08T04:43:56Z</published>
    <updated>2011-06-08T18:58:52Z</updated>

    <summary>In this post, I&#8217;ll sketch a half-baked plan for making an idiomatic RESTful service that handles versioned data in a sensible way. I&#8217;m not claiming that the pattern I&#8217;m proposing is novel or non-obvious (it is, in fact, rather obviously...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="http" label="http" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rest" label="rest" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="versioning" label="versioning" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="webservices" label="web services" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>In this post, I&#8217;ll sketch a half-baked plan for making an idiomatic RESTful service that handles versioned data in a sensible way.  I&#8217;m not claiming that the pattern I&#8217;m proposing is novel or non-obvious (it is, in fact, rather obviously inspired by <a href="http://git-scm.com/"><tt>git</tt></a> and <a href="http://www.eecs.usma.edu/webs/people/okasaki/pubs.html#jfp99">functional dictionaries</a>); but I haven&#8217;t seen it elsewhere, and I believe it might be a good pattern for other folks with similar applications to mine.  I&#8217;ll briefly introduce my problem domain (specifically, a web-service interface for <a href="http://getwallaby.org/">Wallaby</a>) before detailing my solution.  (Feel free to skip the first section if you aren&#8217;t interested in the Wallaby application, and skip the second if you have a pretty good idea of how <tt>git</tt> works.)</p>

<h2>Background</h2>

<p>Wallaby&#8217;s current API maps quite naturally to remote invocations over XML-RPC or SOAP, but a REST interface is more palatable to many client programmers.  (And, perhaps more importantly, to this service developer:  as a recovering functional programmer, I really appreciate the explicit state transfers inherent in RESTful interaction.)  A more dramatic interface change affords the opportunity to think about improving some limitations of the old interface, particularly in terms of the versioning model.</p>

<p>Wallaby&#8217;s current versioning support is designed to support two major kinds of operations: saving and reloading the state of the entire system, and comparing the (activated) configuration of an individual node to any previously-activated configuration.  These two classes of operations support a lot of interesting use cases really well, including most of the ones Wallaby users care about:  providing named snapshots of system state, providing &#8220;undo&#8221; functionality, and differencing configurations to identify which Condor subsystems need to be restarted.</p>

<p>However, this model has some shortcomings:  it treats service state as essentially linear (not as a tree or DAG), it is thus unable to support branches (or to safely handle concurrent modification), and it is unable to optimize cases involving identical snapshots or partial snapshots with distinct identities.  In practice, these are not a major obstacle to using Wallaby, but it would be nice to eliminate these problems and, more generally, to support branching and tree-structured state histories.</p>

<h2>A quick overview of the git model</h2>

<p>The model of versioned data that <tt>git</tt> presents seems like a pretty sensible starting point:  put simply, this model is a content-addressable memory, where <em>objects</em> are stored by hashes of their contents.  Objects can be untyped data blobs (think of the contents of files); <em>trees</em>, which contain mappings from names to trees or blobs; or <em>commits</em>, which bundle metadata including a timestamp, an author, and the identity of the parent commit with a tree.  The ancestor-of relation implies a DAG of commits.  (<tt>git</tt> supports more features, and its data model is more complex than the brief explanation above, but this non-exhaustive summary should suffice for the purposes of this post.)  Objects are write-once and can thus be shared:  files and subtrees among multiple trees, commits as parents of multiple commits, etc.</p>

<p><tt>git</tt> also supports naming particular commits:  <em>tags</em> are names that are fixed to particular commits, and <em>branches</em> are names that can be updated to refer to a commit transitively descended from the commit that they currently point to.  (Of course, it is possible in practice to &#8220;update&#8221; a branch to an unrelated commit, or to &#8220;update&#8221; a tag, by deleting and recreating it, but these operations are not directly provided by the interface.)  All branches and tags, taken collectively, are known as the <em>heads</em> of a repository; typically (but not always), you can follow the ancestry relation back to a single primeval commit from any head.</p>

<p>One common pattern for multiple users collaboratively editing a <tt>git</tt> repository involves creating <em>clones</em> of that repository, one for each user.  Each user then works in his or her clone repository, editing and making commits.  When the time comes to  share these changes, the user can then <em>push</em> changed branches and new tags from the clone to the original repository.  Other users can then <em>pull</em> these changes from the original repository and merge these in to their private clones.</p>

<p>Clearly, the <tt>git</tt> model has some similarities to REST:  client expectations and full object state are transferred explicitly between repositories (so that, e.g., you can&#8217;t push an updated branch that isn&#8217;t an ancestor of the remote branch you&#8217;re pushing to).  However, the assumption that each client can make changes to a private, persistent working area and transmit them en masse does not generally hold in the web services domain, especially if we want clients to be essentially stateless.</p>

<h2>RESTful versioned data</h2>

<p>The basic idea behind this proposal is that &#8220;changing&#8221; an object simply creates a new object, as with <tt>git</tt> and functional data structures.  The identities of data objects are taken from their content; tree objects contain mappings from names to particular tree or data objects.  (These names provide ways to model change, since object identities are dependent on object contents.)  Clients who access the state of the system are really accessing a particular named state — that is, the state of a tree with a given (mutable) tag.  Clients can construct substantial changes to the state of the system  in parallel to the version that other clients are accessing, and then change the whole &#8220;state of the system&#8221; atomically by changing the identity of the current-state tag.  We&#8217;ll now spend some time unpacking this fairly dense overview.</p>

<p>The figure below presents an example <tt>git</tt>-like representation of an employee database; it will be our running example.  Note that, as with a <tt>git</tt> repository, there is a commit object pointing to a tree object; trees contain references either to other tree objects or to data objects.  (In the figure, commit objects are orange, tree objects are blue, and data objects are red.)</p>

<p><img src="http://chapeau.freevariable.com//employees.png" alt="Employees" title="employees.png" border="0" width="381" height="600" /></p>

<p>For clarity, this figure omits some data objects and does not provide explicit IDs for trees.  Note that data objects are represented as strings containing structured data.  (It would also be possible to represent data as trees mapping from attribute names to structured-data representations of values.)  Note also that inter-object references, as in the object representing the Engineering department, are handled by name (i.e. the path through the tree to the referenced object) and not by hashes or other unique identifiers; this makes it possible to change a single object without affecting other objects.</p>

<p>We&#8217;ll now cover what happens when we access and modify data.  We&#8217;ll present one way to access data and two ways to update it, using two different API approaches:  a high-level approach and a low-level approach.</p>

<h3>Accessing data</h3>

<p>We will use HTTP GET requests to access objects or collections of objects.  Consider the following examples:</p>

<dl>
<dt><tt>GET /tag/master/employees/wilma</tt></dt><dd>Redirects to a URL explicitly identifying the current state of the system on tag <tt>master</tt>, something like <tt>/commits/89d71040/employees/wilma</tt>.  This URL points to a representation of the state of <tt>/employees/wilma</tt> as of commit <tt>89d71040</tt>; that is, the object with identity <tt>2c8ec116</tt>.</dd> 
<dt><tt>GET /objects/2c8ec116</tt></dt><dd>Returns the representation of the object with identity <tt>2c8ec116</tt>.</dd> 
<dt><tt>GET /commits/89d71040/employees/</tt></dt><dd>Returns the name and object ID of every employee as of commit <tt>89d71040</tt>, like <tt>{&#8220;wilma&#8221;:2c8ec116, &#8220;betty&#8221;:3fd513f6, &#8230;}</tt></dd>
<dt><tt>GET /commits/89d71040/employees/?displayname=Flintstone</tt></dt><dd>Returns the name and object ID of every employee as of commit <tt>89d71040</tt> whose <tt>displayname</tt> attribute contains the string &#8220;Flintstone.&#8221;</dd>
</dl>

<h3>Updating data: the high-level approach</h3>

<p>The high-level approach corresponds fairly closely to the managed-object model:  one object can be changed at a time, and the changes to that object are immediately committed to service state.  However, because we don&#8217;t want to force users to update the externally-visible service state (that is, the state of the <tt>master</tt> tag) with each object update, we will not change the referent of the <tt>master</tt> tag.  Instead, updating an object will create a &#8220;detached commit,&#8221; as in the following example, in which we want to move Wilma to the corner office next door:</p>

<p><img src="http://chapeau.freevariable.com//updated-wilma.png" alt="Updated wilma" title="updated-wilma.png" border="0" width="169" height="151" /></p>

<p>Here&#8217;s how we&#8217;d update the system to reflect this new state for the <tt>wilma</tt> object:</p>

<ol>
<li>A client issues a HTTP PUT request to <tt>/tag/master/employees/wilma</tt>; at the point of the request, the <tt>master</tt> tag points to commit <tt>89d71040</tt> and <tt>/employees/wilma</tt> points to object <tt>2c8ec116</tt>.  Included in the PUT request body is a representation of the updated state for <tt>wilma</tt>.</li>
<li>The service creates a new object with the supplied updated state (<tt>a30db7ac</tt>) for wilma.</li>
<li>The service then creates a new tree object for <tt>/employees</tt> with the <tt>wilma</tt> reference updated to point to <tt>a30db7ac</tt>.</li>
<li>The service then iteratively updates every tree containing an updated tree until it gets to the root.</li>
<li>The service creates a new commit object referencing the newly-created root tree with <tt>89d71040</tt> as a parent commit; say that this new commit has the ID <tt>597028a0</tt>.</li>
<li>The PUT request returns, redirecting the client to <tt>/commits/597028a0/employees/wilma</tt>.  Until this commit object becomes transitively reachable from a named tag, it will have a <tt>Content-Expires</tt> header indicating a point after which it may be garbage collected.  The client may inspect the commit object or use it as a point of reference for further updates.
</ol>

<p>After making several changes, the client may wish to update the <tt>master</tt> tag, thus affecting the default externally-visible state of the system.  In this approach, as in the low-level approach below, updating tags is done with a PUT request.  To eliminate the possibility of inconsistent updates across clients, the PUT request body should include both the expected old hash of the tag and the new tag hash; this allows rejecting updates that would shadow other updates.  Once a commit is tagged, all of its ancestors are marked as reachable so that they will not expire.</p>

<h3>Updating data: the low-level approach</h3>

<p>This model makes explicit what happens when changing the state of the system.  Say we want to move Wilma to the corner office next door, as above.  First, we&#8217;ll create a new object corresponding to Wilma&#8217;s new state, using HTTP POST to store the new payload, with a request like <tt>POST /objects</tt> and a payload of the representation of the new object.  After this request succeeds, we have the following state:</p>

<p><img src="http://chapeau.freevariable.com//updated-object.png" alt="Updated object" title="updated-object.png" border="0" width="361" height="307" /></p>

<p>Note that the <tt>/employees</tt> tree still points to the old <tt>wilma</tt> object.  The client is responsible for creating a new tree object that points to the new <tt>wilma</tt> object, which it does by HTTP POST request to the <tt>/trees</tt> resource.  The client must then create a new tree object for the tree containing the modified <tt>employees</tt> tree; this is the root tree in this case, but in general the process recursively creates parent trees until it creates a new root.  Given the identity of the new root tree object, the client can then create a new (detached) commit object, proceeding as in the high-level model.</p>

<p>This low-level approach trades flexibility (specifically, the ability to make commits with multiple changes) for complexity, either in the client or (more likely) in a client library.  For applications that must support atomic operations on multiple objects, it might be more suitable than the high-level model; as stated above, though, the high-level model is well-suited for migrating applications from a managed-objects model.</p>

<h2>Improvements</h2>

<p>There are a lot of features that <tt>git</tt> has that we&#8217;ve omitted or hinted at in the above discussion.  Here, we&#8217;ll briefly examine a few that it makes sense to support:</p>

<ol>
<li><em>Differencing and patching</em>.  It should be possible to construct the difference of two trees.  (This may be impractical in general, but it should be sensible for trees of data objects that can be distinguished and differenced.)  Furthermore, it should be possible to construct a patch object that encapsulates the difference between two trees (i.e. how to transform tree <em>A</em> into tree <em>B</em>) and can be applied to other trees to incorporate these changes.</li>
<li><em>Merging</em>.  Given differencing and patching, it makes sense to have first class support for constructing new commits that are the merge of two or more other commits.</li>
<li><em>Hooks</em>.  It should be possible to specify tests which must succeed before, e.g., a commit succeeds, or before a commit may receive a particular tag.  This allows the system to enforce validity properties.</li>
<li><em>Garbage collection</em>.  The system should be space-efficient, automatically eliminating unreachable commits that have expired.</li>
</ol>

<h2>Going forward from here</h2>

<p>It seems like this pattern makes sense for my application, but it also seems sufficiently general to be more broadly useful.  I&#8217;d be inclined to implement this pattern as a framework that handles most of the &#8220;<tt>git</tt> plumbing&#8221;-type operations for developer-provided model or resource objects or structures.  In fact, it might also make sense to support automatic generation of client libraries for certain classes of application!  Dealing with versioned data is a tedious hassle.  Anything we can do to make it more straightforward is a huge win.</p>

<p>I welcome constructive feedback on this proposal.</p>

<p><strong>UPDATE</strong>:  clarified a couple of confusing sentences; thanks to Erik Erlandson for bringing them to my attention.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Using Wallaby groups to implement node tagging</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2011/05/using-wallaby-groups-to-implement-node-tagging.html" />
    <id>tag:chapeau.freevariable.com,2011://1.24</id>

    <published>2011-05-25T15:03:20Z</published>
    <updated>2011-05-25T16:19:32Z</updated>

    <summary>One of the great things about Wallaby is that it&apos;s a platform, not merely a tool. Put another way, if it doesn&apos;t do exactly what you want, you can use its API to build tools that benefit from configuration validation...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="api" label="api" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="condor" label="condor" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="extension" label="extension" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="wallaby" label="wallaby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>One of the great things about <a href="http://getwallaby.com/">Wallaby</a> is that it's a platform, not merely a tool.  Put another way, if it doesn't do exactly what you want, you can use its <a href="http://getwallaby.com/the-wallaby-api/">API</a> to build tools that benefit from configuration validation and deployment.  We've talked in the past about a <a href="http://chapeau.freevariable.com/2010/09/migrating-legacy-condor-configurations-to-wallaby.html">number</a> of <a href="http://chapeau.freevariable.com/2010/10/wallaby-node-inventory-with-constraints.html">useful</a> <a href="http://chapeau.freevariable.com/2010/10/retrieving-wallaby-node-configurations-over-http.html">tools</a> built on the Wallaby API.  (Another cool Wallaby API client that I hope to talk about more in the future is <a href="https://github.com/erikerlandson/">Erik Erlandson</a>'s <a href="http://git.fedorahosted.org/git/?p=grid/albatross.git">Albatross</a> project, which programmatically generates and changes pool configurations in order to test Condor scale and functionality.)</p>

<p>The Wallaby API is designed to be sufficiently general to allow developers to do just about anything with configuration data, not to unnecessarily restrict users to a few use cases that we thought of.  Because of this generality, some tasks might require adopting application-level conventions.  In this article, we'll cover one such convention and see how the Wallaby API is flexible enough to handle an interesting use case &mdash; namely, tagging nodes with various keywords, perhaps as supplied by a user or generated by an agent like <a href="http://qpidcomponents.org/download.html">sesame</a> or <a href="https://github.com/matahari/matahari/wiki">matahari</a>.</p>

<p>First, though, we'll review how configurations are generated and applied to nodes.  Recall that a <em>node</em> is a member of several <em>groups</em>.  These memberships are ordered:  a node's lowest-priority membership is always in the special <em>default group</em> (which includes every node), and its highest-priority membership is always in a special, node-specific <em>identity group</em> (which only includes a single node).  Zero or more memberships in <em>explicit groups</em> may occupy the priority space between the default group and a node's identity group.  In the illustration below, <code>node.local</code> is a member of two explicit groups, which have blue backgrounds:  "EC2 submit nodes," and "Execute nodes."</p>

<p><img src="http://chapeau.freevariable.com//wallaby-groups-simple.png" alt="Wallaby groups simple" title="wallaby-groups-simple.png" border="0" width="487" height="175" /></p>

<p>When Wallaby calculates the configuration for <code>node.local.</code>, it will begin with a copy of the default group's configuration.  It will then repeatedly apply the configurations for the explicit groups and identity group in order of increasing priority, so that parameter-value mappings from higher-priority groups take precedence over lower-priority ones (and thus either replace these or are appended to them, depending on the mapping kind).  The <code>condor_configd</code>, which takes a node's configuration from Wallaby and installs it on a node, will also cause the Wallaby groups a node is a member of (as well as the Wallaby features it has installed) to be advertised for use in Condor matchmaking.  So a Condor job could specify that it wanted to match against a node that was a member of the "EC2 submit nodes" group; this would translate into a preference for <code>node.local</code>.</p>

<p>Because group names appear in machine ClassAd attributes, the list of explicit node memberships is a natural place to put tag information.  Nodes would simply be members of "dummy" groups like "Desktop workstations" or "Machines with more than 8GB RAM," and these keywords could be used in matchmaking or in searching for particular nodes.  However, the list of explicit groups is not necessarily suitable for automatic manipulation:  users will not necessarily expect their changes to be overridden, other API clients won't necessarily expect users to rearrange or remove groups corresponding to tags, and in general it is impossible to determine whether a group membership should be interpreted as a tag or as an explicit membership.</p>

<p>We can adopt a convention to partition the space of group memberships.  Say we create a special <em>sentinel group</em> to partition the membership space:  every node will be a member of the sentinel group.  All memberships that are of a lower priority than the sentinel group will be managed by tagging agents, and all memberships that are of a higher priority will be explicitly managed by the user.  In the example below, "&mdash;EXPLICIT GROUPS" is the sentinel group, and groups in yellow correspond to tags.</p>

<p><img src="http://chapeau.freevariable.com//wallaby-sentinel-groups.png" alt="Wallaby memberships, with a sentinel group and tag groups" title="wallaby-sentinel-groups.png" border="0" width="487" height="294" /></p>

<p>This approach demonstrates the generality of the Wallaby API, and allows users to supply tag-specific configurations by installing parameters or features on tag groups, for example, ensuring that every desktop workstation has a policy that favors its owner, or overprovisioning high-memory nodes.  However, it is not free of shortcomings.  Firstly, Wallaby will present all of these groups &mdash; sentinel, tag, and explicit groups &mdash; so a user-facing tool that puts a friendly interface on node memberships and tagging will need to use the sentinel group to partition which groups it displays to the user.  Secondly, the sentinel groups must be added to all nodes (in practice, we can assume that the absence of a sentinel group implies the absence of tags); in general, we are relying on clients to enforce invariants in this case.  Finally, altering a node's membership list to insert a tag will cause that node's configuration to be validated at the next activation.  If the node has a complex configuration, this could be expensive.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Wallaby user tutorial and live VM</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2011/05/wallaby-user-tutorial-and-live-vm.html" />
    <id>tag:chapeau.freevariable.com,2011://1.23</id>

    <published>2011-05-04T19:35:55Z</published>
    <updated>2011-05-04T19:36:43Z</updated>

    <summary>Rob Rati and I presented a Wallaby user tutorial at Condor Week yesterday. Today, we have a tutorial you can follow along with at home, including a link to an EC2 AMI that boots up with Wallaby and Condor installed...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[Rob Rati and I presented a <a target="_blank" href="http://getwallaby.com">Wallaby</a> user tutorial at <a target="_blank" href="http://www.cs.wisc.edu/condor/CondorWeek2011/">Condor Week</a> yesterday.  Today, we have a <a target="_blank" href="http://getwallaby.com/tutorial-2011/">tutorial you can follow along with at home</a>, including a link to an EC2 AMI that boots up with Wallaby and Condor installed and running so you can experiment without installing anything. Enjoy!<br /><br />]]>
        
    </content>
</entry>

<entry>
    <title>Grepping for git glosses with gliss</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2011/01/grepping-for-git-glosses-with-gliss.html" />
    <id>tag:chapeau.freevariable.com,2011://1.22</id>

    <published>2011-01-13T05:25:20Z</published>
    <updated>2011-01-13T14:44:15Z</updated>

    <summary>I&apos;m pleased to announce the first release of gliss, a tool to make it easier to track lightweight inline annotations in your git repositories. gliss is available as source code or as a Ruby gem. Consider the following things you...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="annotations" label="annotations" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="git" label="git" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="gliss" label="gliss" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="gloss" label="gloss" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>I'm pleased to announce the first release of <a href="https://github.com/willb/gliss"><code>gliss</code></a>, a tool to make it easier to track lightweight inline annotations in your git repositories.  <code>gliss</code> is available as <a href="https://github.com/willb/gliss">source code</a> or as a <a href="http://rubygems.org/gems/gliss">Ruby gem</a>.</p>

<p>Consider the following things you might want to do if you could put metadata in your commit messages:</p>

<ul>
<li>You'd like to link commits to the bug-tracking tickets that they addressed.</li>
<li>You'd like to identify commits that other developers have signaled might require a release note (or, worse yet, introduce a backwards-compatibility problem).</li>
<li>You're working on a private branch and you'd like to mark some commits for later redaction or revision.</li>
</ul>

<p>If you're willing to adopt a simple, flexible microformat for metadata annotations in commit messages, you can write annotations expressing all of these and more, and then use the <code>gliss</code> tool to identify all of the annotations (optionally of a certain kind) in a range of commits (or in the difference between two trees).  We'll begin by introducing the format for these annotations.</p>

<p>A gliss annotation is called a <em>gloss</em> and has two parts:  a tag, and (optionally) some text.  To put a gloss in your commit message, simply begin a line with three identical characters, which we'll call the <em>tag delimiter</em>, followed by a tag name, which can be any string of characters that doesn't start with a dash or contain the tag delimiter, and then the tag delimiter again.  Examples include <code>---FRED---</code>, <code>===BARNEY===</code>, and <code>***WILMA***</code>.  <code>gliss</code> will recognize lines that contain gloss tags and process them.  Any additional text on the same line as the gloss tag will be treated as the beginning of the gloss text.</p>

<p>A gloss can contain more than one line; simply indent the first line after the line containing the gloss tag, and this line becomes a continuation line:  any text after the indent will be appended to the gloss text.  Similarly, any line after a continuation line will be a continuation line if it is at least as indented as the first continuation line of its gloss.  (Currently, the <code>gliss</code> tool strips extra whitespace from continuation lines before outputting them; in a future release of <code>gliss</code>, glosses whose tag begins with a dash will be outputted with whitespace and formatting preserved.)</p>

<p>As an example, <a href="https://github.com/willb/gliss/commit/172863f7c955310cae23e3fe2b206ec2d9729e51">consider this commit message</a> from the gliss repository, which contains two glosses, both tagged <code>@EXAMPLE</code>.  The first is contained on a single line.  The second contains multiple continuation lines; its ends with the first non-indented line.</p>

<p>To inspect these messages with the <code>gliss</code> tool, make sure you have <code>gliss</code> installed and the <a href="https://github.com/willb/gliss"><code>gliss</code> repository</a> checked out locally.  You can then run <code>gliss 2ce2b3c2 master</code> from within the <code>gliss</code> repository directory, and it will show you all of the glosses in commits that are ancestors of <code>master</code> but are not ancestors of <code>2ce2b3c2</code>.  (You can omit <code>master</code> from the command-line; it's the default.)  The output will look something like this:</p>

<pre><code>172863f7 (@EXAMPLE)

    This is an example gliss message, tagged @EXAMPLE.

172863f7 (@EXAMPLE)

    This is another example gliss message, that spans multiple lines. 
    As long as each line has at least the same amount of indentation 
    as the first line after the tag, messages can span one or many lines.
</code></pre>

<p>That's it.</p>

<p>The <code>gliss</code> tool also supports some options, notably to display only glosses with certain tags.  Try <code>gliss -h</code> for some brief documentation overview.</p>

<p>I wrote gliss because I intend to use it, but I hope you find it useful, too.  Please don't hesitate to send in feedback or bug reports.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Extending wallaby with a python client library</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2010/12/extending-wallaby-with-a-python-client-library.html" />
    <id>tag:chapeau.freevariable.com,2010://1.21</id>

    <published>2010-12-16T15:57:34Z</published>
    <updated>2010-12-16T15:57:36Z</updated>

    <summary>In my previous post, we saw how to extend wallaby by writing Ruby classes that use a client library to extend the wallaby shell. If you&apos;re comfortable with Ruby, this is a great way to build functionality on top of...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="condor" label="condor" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="python" label="python" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="wallaby" label="wallaby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>In <a href="http://chapeau.freevariable.com/2010/10/extending-the-wallaby-shell.html">my previous post</a>, we saw how to extend wallaby by writing Ruby classes that use a client library to extend the wallaby shell.  If you're comfortable with Ruby, this is a great way to build functionality on top of the wallaby API in an idiomatic way.  However, Python programmers shouldn't have to learn Ruby just to interact with wallaby.</p>

<p>The wallaby source repository now includes <a href="http://git.fedorahosted.org/git/?p=grid/wallaby.git;a=blob;f=schema/wallaby.py">a Python client library</a> to interact with a wallaby service.  This library does a few things to make your life easier:</p>

<ol>
<li>Raw QMF object proxies are wrapped in Python client objects.</li>
<li>Object references returned by QMF methods are automatically wrapped by client objects.</li>
<li>QMF methods that return error statuses will raise exceptions in the client library.</li>
<li>Client classes include docstrings for QMF methods.</li>
</ol>

<p>See below for a transcript illustrating these features.  Note that you'll need to have the following packages installed to use the Python wallaby client library:  Red Hat Enterprise MRG 1.3 (or the <code>python-qmf</code> package from a recent Fedora release) and Wallaby 0.9.18 or later (0.10.0 to access all of the features exposed through the client library).</p>

<script src="https://gist.github.com/743525.js?file=gistfile1.txt"></script><noscript>Please visit this post in a browser with JavaScript support to view the embedded transcript.</noscript>]]>
        
    </content>
</entry>

<entry>
    <title>Extending the wallaby shell</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2010/10/extending-the-wallaby-shell.html" />
    <id>tag:chapeau.freevariable.com,2010://1.20</id>

    <published>2010-10-21T16:43:51Z</published>
    <updated>2010-10-21T16:48:59Z</updated>

    <summary>The most recent few releases of the Wallaby configuration management service have included some great new features: wallaby console can now be used as an interpreter for shebang scripts, wallaby inventory now supports limiting the nodes it lists with expressive...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="condor" label="condor" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="wallaby" label="wallaby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>The most recent few releases of the Wallaby configuration management service have included some great new features:  <code>wallaby console</code> can now be used as an interpreter for <a href="http://en.wikipedia.org/wiki/Shebang_(Unix)">shebang scripts</a>, <code>wallaby inventory</code> now supports limiting the nodes it lists with <a href="http://chapeau.freevariable.com/2010/10/wallaby-node-inventory-with-constraints.html">expressive constraints</a>, the <code>wallaby http-server</code> command <a href="http://chapeau.freevariable.com/2010/10/retrieving-wallaby-node-configurations-over-http.html">provides access to node configurations over HTTP</a>, and the <code>wallaby</code> command and its subcommands feature many minor functional and aesthetic improvements.  One feature that I'm particularly excited about is under the hood:  there is now an API for extending the wallaby shell with your own subcommands.  In this post, we'll look at how to make a new <code>wallaby</code> subcommand.  <noscript>You'll need to view this post outside of a feed reader, in a browser with JavaScript support, in order to see the embedded code snippets.</noscript></p>

<p>First, make sure you're running <a href="http://git.fedorahosted.org/git/?p=grid/wallaby.git;a=shortlog;h=refs/tags/v0.9.23">wallaby 0.9.23</a> or later.  If you're running Fedora, you can simply <code>git clone</code> the repository, check out the <code>v0.9.23</code> tag, and run <code>rake rpms</code> to generate installable packages.</p>

<p>Next, you'll want to have a directory in which to put your custom wallaby shell commands.  I recommend putting them somewhere in your home directory.  (For the purposes of this discussion, we'll assume that you're using <code>~/.wallaby</code>.)  The <code>wallaby</code> command will find and attempt to load every ruby file in this directory that begins with <code>cmd_</code>, so you probably don't want it to be writable by anyone other than you.  Once you have this directory set up, set <code>WALLABY_COMMAND_DIR</code> in your environment to this directory:</p>

<p><code>export WALLABY_COMMAND_DIR=${HOME}/.wallaby</code></p>

<p>We'll start by making a fairly straightforward command that simply prints out the API version supported by the wallaby service.  To create a new wallaby command, use <code>wallaby new-command</code>:</p>

<script src="http://gist.github.com/638780.js?file=gistfile3.txt"></script>

<p>The <code>-d</code> option allows us to provide a description for the new command (viz., what would show up if we typed <code>wallaby help commands</code>).  The <code>-D</code> option allows us to specify a directory in which to create the new command file.  (<code>wallaby new-command</code> supports several other options; you can use <code>wallaby help new-command</code> for additional documentation.)  After executing this command, we'll have a documented template file for a new wallaby command, called <code>cmd_api_version.rb</code>, installed in our <code>WALLABY_COMMAND_DIR</code>.  It will look something like this:</p>

<script src="http://gist.github.com/638780.js?file=generated_cmd_api_version.rb"></script>

<p>We can now run <code>wallaby help commands</code> and verify that our command shows up.  Sure enough, it does:</p>

<script src="http://gist.github.com/638780.js?file=gistfile4.txt"></script>

<p>We can even run <code>wallaby api-version</code>, although it won't do anything yet.  To make it do something useful, we're going to edit the <code>act</code> method defined for us in the <code>ApiVersion</code> class.  We could do something very simple, like insert <code>puts store.apiVersionNumber</code> before <code>return 0</code>, but it would be nice to allow a user to format the API version number as he or she sees fit, in order to use the result of our command in other scripts.</p>

<p>To let the user supply a format string, we'll need to add a command-line option, which requires us to edit the <code>init_option_parser</code> method.  This method must return an <code>OptionParser</code> object; if you haven't used Ruby's option parser class, read up on <a href="http://ruby-doc.org/stdlib/libdoc/optparse/rdoc/classes/OptionParser.html">its documentation</a>.  For this example, though, the changes we have to make are pretty minor.  </p>

<p>After we've added a command-line option and a body for the <code>act</code> method, our <code>cmd_api_version.rb</code> file will look more like this:</p>

<script src="http://gist.github.com/638780.js?file=cmd_api_version.rb"></script>

<p>Running this command without arguments will return a string like <code>The wallaby service is running version 20100915 of the Wallaby API.</code>  If you supply a format string, you can get simply the raw number (with <code>--format '%s'</code>) or something more suited to your taste.  (Note that this example script doesn't do any sanity- or error-checking of the format string, which you'd certainly want to do if you were going to put your command into production.)</p>

<p>We'll look at a more interesting example wallaby shell command and some of the issues that more interesting commands raise in a future post.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Wallaby node inventory with constraints</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2010/10/wallaby-node-inventory-with-constraints.html" />
    <id>tag:chapeau.freevariable.com,2010://1.19</id>

    <published>2010-10-18T17:03:04Z</published>
    <updated>2010-10-18T17:03:06Z</updated>

    <summary>wallaby inventory is a useful command for quickly checking up on the health of your pool and answering certain kinds of questions: Which nodes have checked in recently? Which nodes have checked in without being explicitly configured? Which nodes have...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="wallaby" label="wallaby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p><tt>wallaby inventory</tt> is a useful command for quickly checking up on the health of your pool and answering certain kinds of questions:  Which nodes have checked in recently?  Which nodes have checked in without being explicitly configured?  Which nodes have never checked in?</p>

<p>Recently, I added <em>constraint</em> support to <tt>wallaby inventory</tt>.  That is, instead of listing all nodes, you can choose to list only nodes for which a given Ruby expression is true.  These constraints can be simple, like <tt>last_checkin &lt; 1.hour_ago</tt> (which will find all nodes that have checked in more than one hour ago), or more complex.  They are only limited by Ruby's <a href="http://ruby-doc.org/docs/ProgrammingRuby/html/taint.html"><tt>$SAFE</tt> execution</a>:  among other things, they cannot modify running classes, perform file I/O, fork new processes, or, because of how QMF is implemented, invoke QMF <em>methods</em> on the node object.  However, every QMF <em>property</em> of the node object is available to <tt>wallaby inventory</tt> constraints.  The transcript below provides some examples running against a wallaby agent loaded up with test data.</p>

<script src="http://gist.github.com/632556.js"> </script><noscript>Visit this post in a browser with JavaScript support (not a feed reader) to see the embedded transcript.</noscript>]]>
        
    </content>
</entry>

<entry>
    <title>Retrieving Wallaby node configurations over HTTP</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2010/10/retrieving-wallaby-node-configurations-over-http.html" />
    <id>tag:chapeau.freevariable.com,2010://1.18</id>

    <published>2010-10-15T18:00:57Z</published>
    <updated>2010-10-15T18:00:59Z</updated>

    <summary>In some environments, users may wish to use Wallaby to serve configurations to nodes that can&apos;t reach the Qpid broker that the Wallaby agent is running against. Some users may also want to write simple scripts that access current or...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="condor" label="condor" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="http" label="http" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="wallaby" label="wallaby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>In some environments, users may wish to use Wallaby to serve configurations to nodes that can't reach the Qpid broker that the Wallaby agent is running against.  Some users may also want to write simple scripts that access current or historical configuration data without writing a QMF console.  The <tt>wallaby http-server</tt> command, which is available beginning with <tt>wallaby-0.9.19</tt>, offers a solution for such users.  It provides a read-only web service gateway to a node's configuration:  the last activated configuration, a particular version, and the node's current configuration in the store (which may not yet have been activated).</p>

<p><tt>wallaby http-server</tt> requires that the Sinatra framework is installed.  If you are building RPMs for wallaby, <tt>wallaby-http-server</tt> will be built as a separate package, and only if you're building from Fedora 12 or later.  If you're installing from source, simply <tt>gem install sinatra</tt> before running the HTTP server; if you've already installed a wallaby package on a non-Fedora system, you can simply install <tt>cmd_http_server.rb</tt> <a href="http://git.fedorahosted.org/git/?p=grid/wallaby.git;a=blob;f=lib/mrg/grid/config/shell/cmd_http_server.rb;hb=HEAD">from the source repository</a> into your wallaby shell commands directory.  (In the future, we expect to package <tt>wallaby-http-server</tt> for Red Hat Enterprise Linux as well, thus simplifying this process.)</p>

<p>The transcript below shows the HTTP server's built-in help, listing all of the methods it supports (as of <tt>wallaby-0.9.20</tt>, which will be released later today).  Please let us know if you can think of other API methods that would be useful to expose over the Wallaby HTTP server.</p>

<p><script src="http://gist.github.com/628571.js"> </script><noscript>Please visit this post in a browser with JavaScript support to see the embedded code snippet.</noscript></p>]]>
        
    </content>
</entry>

<entry>
    <title>Flexible interaction with the Wallaby console</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2010/09/flexible-interaction-with-the-wallaby-console.html" />
    <id>tag:chapeau.freevariable.com,2010://1.17</id>

    <published>2010-09-28T17:05:11Z</published>
    <updated>2010-09-28T17:05:13Z</updated>

    <summary>One of the main benefits of using Wallaby for configuration is the remote-access API. Because the API is comprehensive and usable from any language with a QMF binding (including C++, Java, Python, and Ruby), it provides developers and users with...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="wallaby" label="wallaby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>One of the main benefits of using Wallaby for configuration is the remote-access <a href="http://wallaby.freevariable.com/the-wallaby-api/">API</a>.  Because the API is comprehensive and usable from any language with a QMF binding (including C++, Java, Python, and Ruby), it provides developers and users with the means to build tools, policies, templating systems, and one-off scripts on top of Wallaby.</p>

<p>If you're writing a Wallaby API client in Ruby, you can use a couple of nice features to ease development:  the <a href="http://git.fedorahosted.org/git/?p=grid/wallaby.git;a=blob;f=lib/mrg/grid/config-client.rb;hb=HEAD">Wallaby client library</a>, which presents a more polished interface than dealing with raw QMF queries and calls, and the <code>wallaby console</code> utility, which connects to a specified broker and gives you a Ruby <a href="http://en.wikipedia.org/wiki/Read-eval-print_loop">REPL</a> that has a global variable pointing to a store client --- perfect for casual, interactive experimentation.</p>

<p>Use the same global command line options for <code>wallaby console</code> as you'd use for any other <code>wallaby</code> subcommand:  specifying host, port, and authentication information for the broker.  Once you've started it up, you'll be dropped into a Ruby prompt where <code>Wallaby::store</code> is a reference to a client proxy object for your Wallaby store.  You can then inspect or modify any entity that the store knows about; the store object has accessors called <code>nodes</code>, <code>features</code>, <code>parameters</code>, etc., that return arrays of each kind of object.  Then you can invoke methods on each object.  The transcript below shows a session in which the user inspects some details of a node in a trivial pool:</p>

<p><code>&gt;&gt; Wallaby::store.nodes.map {|n| n.name}</code> <br />
<code>=&gt; ["frotz"]</code> <br />
<code>&gt;&gt; frotz = Wallaby::store.nodes[0] ; nil</code> <br />
<code>=&gt; nil</code> <br />
<code>&gt;&gt; Wallaby::store.groups.map {|g| g.name}</code> <br />
<code>=&gt; ["+++DEFAULT", "+++af413ebf1de0f9d4253eb89717a4e13b"]</code> <br />
<code>&gt;&gt; Wallaby::store.groups[1].features</code> <br />
<code>=&gt; ["DisablePreemption"]</code> <br />
<code>&gt;&gt; frotz.getConfig</code> <br />
<code>=&gt; {"PREEMPT"=&gt;"FALSE", "WALLABY_CONFIG_VERSION"=&gt;"1284180448517726"}</code></p>

<p>In the future, it will be easier to extend the <code>wallaby</code> command with your own subcommands.  For now, however, <code>wallaby console</code> provides a great way to interact with the Wallaby API.</p>
]]>
        

    </content>
</entry>

</feed>

