<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Whopper Tacos]]></title>
  <link href="http://blog.thesilentpenguin.com/atom.xml" rel="self"/>
  <link href="http://blog.thesilentpenguin.com/"/>
  <updated>2012-04-16T15:41:10-04:00</updated>
  <id>http://blog.thesilentpenguin.com/</id>
  <author>
    <name><![CDATA[The Silent Penguin LLC]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Logstash Debuntu Packaging and Deployment]]></title>
    <link href="http://blog.thesilentpenguin.com/blog/2012/04/16/logstash-debuntu-packaging-and-deployment/"/>
    <updated>2012-04-16T14:51:00-04:00</updated>
    <id>http://blog.thesilentpenguin.com/blog/2012/04/16/logstash-debuntu-packaging-and-deployment</id>
    <content type="html"><![CDATA[<p>Logstash is a really nifty log shipping, indexing, and searching suite. The
typical centralized setup involves running a shipper agent on all your nodes,
which are configured to ship certain log messages to a message broker. An
indexing agent consumes the log messages from the broker, and writes them to
elasticsearch. Logstash comes with a light web interface for searching this
data.</p>

<!-- more -->


<p>Unfortunately, I couldn&#8217;t find any current packaging for logstash. However,
the writer of Logstash (Jordan Sissel, aka whack) writes another utility
called FPM (F&#8217;n Package Management) which allows you to easily create OS
packages from a directory structure. So I forked the elasticsearch init
script which is included with elasticsearch&#8217;s deb package, making one init
script for each of the three moving parts in Logstash.</p>

<p>I put the default configs and /etc/default/logstash-{web,shipper,indexer} in
a directory, and a couple of pre and post install scripts. Then, I downloaded
the latest stable logstash all in one jar. I named this jar logstash.jar and
put it in logstash_packaging/usr/share/logstash/.</p>

<p>I then used fpm to build a package like so:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>fpm -n logstash -v 1.1.0.1yoursite1 -d grok -d default-jre -a all -C logstash_packaging/ -m "The Systems Group systems@yoursite.com" -t deb -s dir --pre-install ./logstash.preinstall --post-install ./logstash.postinstall --description "Logstash Open Source Log Management" --url 'http://www.logstash.net/'</span></code></pre></td></tr></table></div></figure>


<p>Remember if you need to re-package, only bump the number after your sitename.</p>

<p>You can find the packaging files here: <a href="https://github.com/thesilentpenguin/logstash-packaging">GitHub</a>.</p>

<p>Now onto the actual deployment. As usual, I use Puppet for this. Basically I
have a parameterized class that you feed a &#8216;role&#8217; to. This is an array of
which logstash agents you&#8217;ll be running. Depending on this role, certain
services are enabled and started up, and their configs served out.</p>

<p>That code can be found here: <a href="https://github.com/thesilentpenguin/puppet-logstash">GitHub</a>.</p>

<p>A couple of small caveats. I put in an elasticsearch parameter, which should
work. Just be wary that if you use an external elasticsearch server, you must
use the version your logstash jar is compiled against. This is because the
REST API was not fast enough, so Jordan had to use the Java messaging.</p>

<p>Also, be wary that elasticsearch <em>discovery</em> is done using multicast. So if
you are firewalling, you may notice that changing your default policy to
ACCEPT during startup of logstash alleviates the issue, which will probably
manifest in you seeing the indexer see messages, but nothing appearing in
elastisearch.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Puppet vs Chef: The Unequivocal Winner]]></title>
    <link href="http://blog.thesilentpenguin.com/blog/2012/03/08/puppet-vs-chef-the-unequivocal-winner/"/>
    <updated>2012-03-08T12:14:00-05:00</updated>
    <id>http://blog.thesilentpenguin.com/blog/2012/03/08/puppet-vs-chef-the-unequivocal-winner</id>
    <content type="html"><![CDATA[<p>Me, representing Puppet, versus Reza, good friend and lowly Chef user, at the
moment of Puppet&#8217;s glorious victory:</p>

<!-- more -->


<p><img src="http://a6.sphotos.ak.fbcdn.net/hphotos-ak-ash2/71678_1194667483012_5305622_n.jpg"></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[OpenBSD - Using Hierarchical Protection Domains for Network Security]]></title>
    <link href="http://blog.thesilentpenguin.com/blog/2012/03/01/openbsd-using-hierarchical-protection-domains-for-network-security/"/>
    <updated>2012-03-01T01:07:00-05:00</updated>
    <id>http://blog.thesilentpenguin.com/blog/2012/03/01/openbsd-using-hierarchical-protection-domains-for-network-security</id>
    <content type="html"><![CDATA[<p>Some time ago I worked with Reyk Floeter on the ininitial implementation of a
new datacenter network during my time at one of the more well-known Information
Security vendors. Reyk had this phenomenal idea for the network structure that
seemed to simple it was one of those &#8220;why didn&#8217;t I think of that&#8221; ideas. So
after we deployed, I looked over the net and couldn&#8217;t really find docs of people
doing this, so I wrote a really short paper and some basic slides on it and
presented at LOPSA PICC &#8216;11. I kind of suck at presenting, but this topic is
actually super easy to understand, so I was able to get my ideas out fast and
then answer a lot of questions. Anyways, this paper came up in an IRC chat
tonight and I figured I should post a link to it, <a href="http://devio.us/~jmcdonagh/openbsd_rings.tar.gz">here ya go.</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Simple puppet function for writing out to Confluence]]></title>
    <link href="http://blog.thesilentpenguin.com/blog/2012/02/29/simple-puppet-function-for-writing-out-to-confluence/"/>
    <updated>2012-02-29T20:54:00-05:00</updated>
    <id>http://blog.thesilentpenguin.com/blog/2012/02/29/simple-puppet-function-for-writing-out-to-confluence</id>
    <content type="html"><![CDATA[<p>A couple gigs ago we were an Atlassian shop and I am actually a big fan of
Atlassian software, though it takes a lot of work up front to get it deployed
in the way you like, but I&#8217;m not going to cover all that here. What I did
though was I enabled the SOAP api for a user named Puppet, opened up the IT
or Systems area so I could write something here:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='text'><span class='line'>http://confluence.yourorg.com/Systems/${fqdn}
</span></code></pre></td></tr></table></div></figure>




<!-- more -->


<p>Now that the thing that is phenomenal about this is that each page in
Confluence has a comments section that you don&#8217;t deal with when comparing
the data, to determine if an update is needed. Now what this means is that
you can use the comments area as a server log. Everytime you do some work
on a given server, you can log it right on the server&#8217;s page. So here is the
function, which I will talk about a little bit more after the paste:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1"># This file is managed by puppet. It&#39;s used to write node information to</span>
</span><span class='line'><span class="c1"># Atlassian Confluence wiki pages.</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;erb&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="k">module</span> <span class="nn">Puppet::Parser::Functions</span>
</span><span class='line'>   <span class="n">newfunction</span><span class="p">(</span><span class="ss">:write_confluence_wiki</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">args</span><span class="o">|</span>
</span><span class='line'>      <span class="n">page_template</span> <span class="o">=</span> <span class="sx">%{</span>
</span><span class='line'><span class="sx">{panel}</span>
</span><span class='line'><span class="sx">{color:#102051}This page is automagically generated and updated by a Puppet function.{color}</span>
</span><span class='line'><span class="sx">{panel}</span>
</span><span class='line'>
</span><span class='line'><span class="sx">h1. &lt;%= lookupvar(&quot;::fqdn&quot;) %&gt;</span>
</span><span class='line'><span class="sx">----</span>
</span><span class='line'>
</span><span class='line'><span class="sx">h2. Node Information</span>
</span><span class='line'><span class="sx">|| *Fact or Variable* \ || *Value* ||</span>
</span><span class='line'><span class="sx">| Architecture \ | &lt;%= lookupvar(&quot;::hardwaremodel&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Core Count \ | &lt;%= lookupvar(&quot;::processorcount&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| CPU \ | &lt;% if lookupvar(&quot;::kernel&quot;) == &quot;OpenBSD&quot; %&gt;&lt;%= lookupvar(&quot;::hardwareisa&quot;) %&gt;&lt;% else %&gt;&lt;%= lookupvar(&quot;processor0&quot;) %&gt;&lt;% end %&gt; \ |</span>
</span><span class='line'><span class="sx">| Facter Version \ | &lt;%= lookupvar(&quot;::facterversion&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Kernel \ | &lt;%= lookupvar(&quot;::kernelrelease&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Location \ | &lt;%= extlookup(&quot;address&quot;) %&gt;, &lt;%= extlookup(&quot;citystate&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| OS \ | &lt;% if lookupvar(&quot;::operatingsystem&quot;) == &quot;OpenBSD&quot; %&gt;OpenBSD &lt;%= lookupvar(&quot;::operatingsystemrelease&quot;) %&gt;&lt;% else %&gt;&lt;%= lookupvar(&quot;::lsbdistdescription&quot;) %&gt;&lt;% end %&gt; \ |</span>
</span><span class='line'><span class="sx">| Physical Processor Count \ | &lt;%= lookupvar(&quot;::physicalprocessorcount&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Puppet Master \ | &lt;%= extlookup(&quot;puppetserver&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| RAID Type \ | &lt;%= lookupvar(&quot;::raidtype&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Ruby Version \ | &lt;%= lookupvar(&quot;::rubyversion&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Time Zone \ | &lt;%= lookupvar(&quot;::timezone&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Virtual? \ | &lt;% if lookupvar(&quot;::virtual&quot;) != &quot;physical&quot; %&gt;Yes&lt;% else %&gt;No&lt;% end %&gt; \ |</span>
</span><span class='line'>
</span><span class='line'><span class="sx">h2. Firewall Information</span>
</span><span class='line'>
</span><span class='line'><span class="sx">*Note that this information is not accurate on OpenBSD routers and firewalls*</span>
</span><span class='line'>
</span><span class='line'><span class="sx">|| *Network Type* \ || *Networks* ||</span>
</span><span class='line'><span class="sx">| Node Networks \ | &lt;%= extlookup(&quot;nodenets&quot;).to_a.join(&#39;,&#39;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Trusted Networks \ | &lt;%= extlookup(&quot;trustednets&quot;).to_a.join(&#39;,&#39;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Blocked Machines/Networks \ | &lt;%= extlookup(&quot;badactors&quot;).to_a.join(&#39;,&#39;) %&gt; \ |</span>
</span><span class='line'>
</span><span class='line'><span class="sx">|| *Port Set* \ || *Ports* ||</span>
</span><span class='line'><span class="sx">| Restricted to Node Networks (TCP) \ | &lt;%= lookupvar(&quot;restricted_to_node_nets_tcp_ports&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Restricted to Node Networks (UDP) \ | &lt;%= lookupvar(&quot;restricted_to_node_nets_udp_ports&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Restricted to Trusted Networks (TCP) \ | &lt;%= lookupvar(&quot;restricted_tcp_ports&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Restricted to Trusted Networks (UDP) \ | &lt;%= lookupvar(&quot;restricted_udp_ports&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Fully Open to the World Ports (TCP) \ | &lt;%= lookupvar(&quot;open_tcp_ports&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Fully Open to the World Ports (UDP) \ | &lt;%= lookupvar(&quot;open_udp_ports&quot;) %&gt; \ |</span>
</span><span class='line'>
</span><span class='line'><span class="sx">h2. NIC Information</span>
</span><span class='line'><span class="sx">|| *Interface* \ || *MAC Address* \ || *IP* \ || *Netmask* ||</span>
</span><span class='line'><span class="sx">&lt;% lookupvar(&quot;::interfaces&quot;).split(&#39;,&#39;).each do |iface|</span>
</span><span class='line'><span class="sx">   ip   = &quot;ipaddress_&quot; + iface </span>
</span><span class='line'><span class="sx">   mac  = &quot;macaddress_&quot; + iface</span>
</span><span class='line'><span class="sx">   mask = &quot;netmask_&quot; + iface</span>
</span><span class='line'><span class="sx">%&gt;| &lt;%= iface %&gt; \ | &lt;%= lookupvar(mac) %&gt; \ | &lt;%= lookupvar(ip) %&gt; \ | &lt;%= lookupvar(mask) %&gt; \ |</span>
</span><span class='line'><span class="sx">&lt;% end %&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="sx">h2. Contact Points</span>
</span><span class='line'><span class="sx">| Primary Admin | &lt;%= extlookup(&quot;primary_nagios_contact&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Secondary Admin | &lt;%= extlookup(&quot;secondary_nagios_contact&quot;) %&gt; \ |</span>
</span><span class='line'><span class="sx">| Tertiary Admin | &lt;%= extlookup(&quot;tertiary_nagios_contact&quot;) %&gt; \ |</span>
</span><span class='line'>
</span><span class='line'><span class="sx">During non-emergency, please contact &lt;%= lookupvar(&quot;admin_group_email&quot;) %&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="sx">More information such as what resources are managed on this node can be viewed [here|http://puppetdocs.&lt;%= lookupvar(&quot;::domain&quot;) -%&gt;/&lt;%= lookupvar(&quot;::environment&quot;) -%&gt;]</span>
</span><span class='line'><span class="sx">----</span>
</span><span class='line'>
</span><span class='line'><span class="sx">*Please use the comments for a server log.* </span>
</span><span class='line'>
</span><span class='line'><span class="sx">{column}</span>
</span><span class='line'><span class="sx">{section}{section}</span>
</span><span class='line'><span class="sx">      }</span>
</span><span class='line'>
</span><span class='line'>      <span class="c1"># Get current page to determine if there are no changed to be made</span>
</span><span class='line'>      <span class="n">current_confluence_page</span> <span class="o">=</span> <span class="sb">`/usr/local/bin/confluence.sh --action getPageSource --title </span><span class="si">#{</span><span class="n">lookupvar</span><span class="p">(</span><span class="s2">&quot;::fqdn&quot;</span><span class="p">)</span><span class="si">}</span><span class="sb"> --space IT`</span>
</span><span class='line'>      <span class="c1"># Compile Confluence page with dynamic data populated</span>
</span><span class='line'>      <span class="n">new_confluence_page</span> <span class="o">=</span> <span class="no">ERB</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">page_template</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>      <span class="c1"># Now we will exit if there are no changes</span>
</span><span class='line'>      <span class="k">if</span> <span class="n">current_confluence_page</span> <span class="o">==</span> <span class="n">new_confluence_page</span>
</span><span class='line'>         <span class="k">return</span> <span class="mi">0</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>      <span class="c1"># Stuff changes into confluence</span>
</span><span class='line'>      <span class="n">output</span> <span class="o">=</span> <span class="sb">`/usr/local/bin/confluence.sh --action storePage --title &quot;</span><span class="si">#{</span><span class="n">lookupvar</span><span class="p">(</span><span class="s2">&quot;::fqdn&quot;</span><span class="p">)</span><span class="si">}</span><span class="sb">&quot; --space IT --content &#39;</span><span class="si">#{</span><span class="n">new_confluence_page</span><span class="o">.</span><span class="n">result</span><span class="p">(</span><span class="nb">binding</span><span class="p">)</span><span class="si">}</span><span class="sb">&#39; 2&gt;&amp;1`</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">if</span> <span class="vg">$?</span> <span class="o">!=</span> <span class="mi">0</span>
</span><span class='line'>         <span class="k">raise</span> <span class="no">Puppet</span><span class="o">::</span><span class="no">ParseError</span><span class="p">,</span> <span class="n">output</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">return</span> <span class="mi">0</span>
</span><span class='line'>   <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Please note this requires the shitty Java Confluence client, never had the
chance to rewrite using native SOAP, but if you would, feel free to send me
a patch!</p>

<p>This is also in production at one of my gigs on a 2.6.7 master, have yet to
try on 2.7.9 which I am using at all my other gigs.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using git cherry to get a list of unmerged and un-cherry-picked commits]]></title>
    <link href="http://blog.thesilentpenguin.com/blog/2012/02/27/using-git-cherry-to-get-a-list-of-unmerged-and-un-cherry-picked-commits/"/>
    <updated>2012-02-27T22:18:00-05:00</updated>
    <id>http://blog.thesilentpenguin.com/blog/2012/02/27/using-git-cherry-to-get-a-list-of-unmerged-and-un-cherry-picked-commits</id>
    <content type="html"><![CDATA[<p>Recently I made a post about using Git submodules for Puppet and I pasted some
code I use to interact with the repo and ensure I get the workflow right. One
of these scripts, promote.sh, had a feature that listed commits not yet in
the master branch of each submodule. This was done with git log master..develop.
Unfortunately, this command will show commits that have been cherry-picked as
not yet merged, since cherry-picks get a new SHA on the branch you bring them
into. After doing some digging, I found a new command: git cherry.</p>

<!-- more -->


<p>Git cherry is made for this exact purpose almost. The man page says it is for
determining which commits have not yet made it to upstream, and it does this
by comparing the changeset, not the SHA commit id. It will output lines of
each commit ID that has not yet been merged to upstream. Then, each
line will begin with a - or +. The lines with -&#8217;s are already in the branch
passed, while the lines beginning with + are the ones that only exist in your
current branch. I then took this knowledge, and modified the list function
for promote.sh to look like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c"># This will go through all submodules and run the appropriate git command to</span>
</span><span class='line'><span class="c"># show what commits master needs to be on track with develop. This uses the</span>
</span><span class='line'><span class="c"># git cherry command, which is basically built for this exact purpose. Note</span>
</span><span class='line'><span class="c"># that this had to be used due to our use case of sometimes promoting single</span>
</span><span class='line'><span class="c"># changes through cherry-pick. Therefore git log master..develop would some-</span>
</span><span class='line'><span class="c"># times show inaccurate information.</span>
</span><span class='line'><span class="k">function </span>list_pending_promotions<span class="o">()</span> <span class="o">{</span>
</span><span class='line'>   <span class="nb">pushd</span> <span class="nv">$puppetroot</span> &gt;/dev/null 2&gt;&amp;1
</span><span class='line'>
</span><span class='line'>   <span class="nb">read</span> -p <span class="s2">&quot;Update checkout? (y/N) &quot;</span> answer
</span><span class='line'>
</span><span class='line'>   <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$answer&quot;</span> !<span class="o">=</span> <span class="s2">&quot;y&quot;</span> -a <span class="s2">&quot;$answer&quot;</span> !<span class="o">=</span> <span class="s2">&quot;Y&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">      </span><span class="nb">printf</span> <span class="s2">&quot;Be warned, data might be innaccurate if you are not up to date.\n&quot;</span>
</span><span class='line'>   <span class="k">else</span>
</span><span class='line'><span class="k">      </span><span class="nb">printf</span> <span class="s2">&quot;Ensure checkout is updated...\n&quot;</span>
</span><span class='line'>      scripts/updatecheckout.sh
</span><span class='line'>   <span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">   </span><span class="nb">printf</span> <span class="s2">&quot;Show pending changes...\n\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;========================================\n&quot;</span>
</span><span class='line'>   git submodule --quiet foreach <span class="s1">&#39;if [[ $path =~ ^production.* ]]; then printf &quot;%s:\n\n&quot; &quot;$(basename $name)&quot;; changes=$(git checkout develop 2&gt;/dev/null; git cherry -v master | egrep &quot;^\+&quot; | sed &quot;s/^+ //&quot;; git checkout master 2&gt;/dev/null); if [ -z &quot;$changes&quot; ]; then printf &quot;No pending commits.\n&quot;; else printf &quot;%s\n&quot; &quot;$changes&quot;; fi; printf &quot;========================================\n&quot;; fi&#39;</span>
</span><span class='line'>   <span class="nb">popd</span> <span class="nv">$puppetroot</span> &gt;/dev/null 2&gt;&amp;1
</span><span class='line'><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The long line for git submodule is kind of suboptimal, but I didn&#8217;t really
want to play with escaping at this point. This feature is nice though and
after asking around not many people seemed to know about it.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Hackery to script creation of new Puppet CA]]></title>
    <link href="http://blog.thesilentpenguin.com/blog/2012/02/27/hackery-to-script-creation-of-new-puppet-ca/"/>
    <updated>2012-02-27T19:33:00-05:00</updated>
    <id>http://blog.thesilentpenguin.com/blog/2012/02/27/hackery-to-script-creation-of-new-puppet-ca</id>
    <content type="html"><![CDATA[<p>One of the tasks when setting up a new master is to set up a new CA. This is
not something most people think about because Puppet does it automatically
for you. However, unless your puppet.conf is in place already, it may not
create 4096 bit keys. Also, if you&#8217;re doing a completely automated setup of
a new organization, you might want to just run a script to generate the CA
in a version controlled directory.</p>

<!-- more -->


<p>So, here is my quick and dirty hack for generating a new Puppet CA:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1">#!/usr/bin/env ruby</span>
</span><span class='line'><span class="c1"># QnD for generating Puppet CA. Doing a certification chain is a royal PITA</span>
</span><span class='line'><span class="c1"># with Puppet, so I typically have the Puppet CA as a separate entity from</span>
</span><span class='line'><span class="c1"># the company SSL setup. This is obviously suboptimal for enterprise-scale</span>
</span><span class='line'><span class="c1"># Puppet setups. You&#39;ve been warned!</span>
</span><span class='line'>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;rubygems&#39;</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;puppet&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="k">begin</span>
</span><span class='line'>   <span class="no">Puppet</span><span class="o">::</span><span class="no">SSL</span><span class="o">::</span><span class="no">Host</span><span class="o">.</span><span class="n">ca_location</span> <span class="o">=</span> <span class="ss">:local</span>
</span><span class='line'>   <span class="no">Puppet</span><span class="o">.</span><span class="n">settings</span><span class="o">.</span><span class="n">use</span> <span class="ss">:ca</span>
</span><span class='line'>   <span class="no">Puppet</span><span class="o">[</span><span class="ss">:certname</span><span class="o">]</span> <span class="o">=</span> <span class="s2">&quot;puppet&quot;</span>
</span><span class='line'>   <span class="no">Puppet</span><span class="o">[</span><span class="ss">:keylength</span><span class="o">]</span> <span class="o">=</span> <span class="s2">&quot;4096&quot;</span>
</span><span class='line'>   <span class="no">Puppet</span><span class="o">[</span><span class="ss">:ssldir</span><span class="o">]</span> <span class="o">=</span> <span class="s2">&quot;./&quot;</span>
</span><span class='line'>   <span class="n">newca</span> <span class="o">=</span> <span class="no">Puppet</span><span class="o">::</span><span class="no">SSL</span><span class="o">::</span><span class="no">CertificateAuthority</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'>   <span class="n">newca</span><span class="o">.</span><span class="n">generate_ca_certificate</span>
</span><span class='line'>   <span class="no">Puppet</span><span class="o">::</span><span class="no">SSL</span><span class="o">::</span><span class="no">CertificateAuthority</span><span class="o">.</span><span class="n">instance</span>
</span><span class='line'><span class="k">rescue</span>
</span><span class='line'>   <span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="s2">&quot;Error creating Puppet CA!!!&quot;</span>
</span><span class='line'>   <span class="nb">exit</span> <span class="o">-</span><span class="mi">2</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[My technique for reconciling generic canned Puppet modules and organization-specific configurations]]></title>
    <link href="http://blog.thesilentpenguin.com/blog/2012/02/26/my-technique-for-reconciling-generic-canned-puppet-modules-and-organization-specific-configurations/"/>
    <updated>2012-02-26T14:30:00-05:00</updated>
    <id>http://blog.thesilentpenguin.com/blog/2012/02/26/my-technique-for-reconciling-generic-canned-puppet-modules-and-organization-specific-configurations</id>
    <content type="html"><![CDATA[<p>As I&#8217;ve mentioned before I use a large set of cross-platform, relatively
generic modules that I wrote for a system I call GRUMPS. The problem with
this method is that you&#8217;re going to need to have some ERBs and files that
are custom to your organization.</p>

<!-- more -->


<p>In my previous post about using Puppet submodules, you may have noticed
that in addition to my grumps-modules, I use an organization-modules as
the second module in my modulepath. So, to remediate the need for site-
specific stuff while maintaining the generic moduleset is to create
modules under the organization-modules directory named modulename_priv.</p>

<p>Then I do something like this to tell my defined resources to look there
(the &#8230;&#8217;s cut out code not necessary for this demonstration):</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">define</span> <span class="n">httpd</span><span class="o">::</span><span class="n">site</span> <span class="p">(</span>
</span><span class='line'>   <span class="vg">$ensure</span>  <span class="o">=</span> <span class="s2">&quot;present&quot;</span><span class="p">,</span>
</span><span class='line'>   <span class="vg">$group</span>   <span class="o">=</span> <span class="s2">&quot;${httpd::apache_group}&quot;</span><span class="p">,</span>
</span><span class='line'>   <span class="vg">$mode</span>    <span class="o">=</span> <span class="s2">&quot;640&quot;</span><span class="p">,</span>
</span><span class='line'>   <span class="vg">$owner</span>   <span class="o">=</span> <span class="s2">&quot;root&quot;</span><span class="p">,</span>
</span><span class='line'>   <span class="vg">$private</span> <span class="o">=</span> <span class="s2">&quot;false&quot;</span>
</span><span class='line'><span class="p">)</span> <span class="p">{</span>
</span><span class='line'><span class="o">.</span><span class="n">.</span><span class="o">.</span>
</span><span class='line'>
</span><span class='line'>   <span class="k">if</span> <span class="p">(</span><span class="vg">$private</span> <span class="o">==</span> <span class="s2">&quot;true&quot;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="vg">$template_path</span> <span class="o">=</span> <span class="s2">&quot;httpd_priv/sites/${name}.erb&quot;</span>
</span><span class='line'>   <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>      <span class="vg">$template_path</span> <span class="o">=</span> <span class="s2">&quot;httpd/sites/${name}.erb&quot;</span>
</span><span class='line'>   <span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="o">.</span><span class="n">.</span><span class="o">.</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">file</span> <span class="p">{</span>
</span><span class='line'>      <span class="s2">&quot;${httpd::confdir}/${name}&quot;</span><span class="p">:</span>
</span><span class='line'>         <span class="n">content</span>  <span class="o">=&gt;</span> <span class="vg">$ensure</span> <span class="p">?</span> <span class="p">{</span> <span class="n">present</span> <span class="o">=&gt;</span> <span class="n">template</span><span class="p">(</span><span class="vg">$template_path</span><span class="p">),</span> <span class="n">absent</span> <span class="o">=&gt;</span> <span class="k">undef</span> <span class="p">},</span>
</span><span class='line'>         <span class="k">ensure</span>   <span class="o">=&gt;</span> <span class="vg">$ensure</span><span class="p">,</span>
</span><span class='line'>         <span class="n">group</span>    <span class="o">=&gt;</span> <span class="vg">$group</span><span class="p">,</span>
</span><span class='line'>         <span class="n">mode</span>     <span class="o">=&gt;</span> <span class="vg">$mode</span><span class="p">,</span>
</span><span class='line'>         <span class="n">owner</span>    <span class="o">=&gt;</span> <span class="vg">$owner</span><span class="p">,</span>
</span><span class='line'>         <span class="n">tag</span>      <span class="o">=&gt;</span> <span class="s2">&quot;httpd_config&quot;</span><span class="p">;</span>
</span><span class='line'>   <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Testing Puppet]]></title>
    <link href="http://blog.thesilentpenguin.com/blog/2012/02/22/testing-puppet/"/>
    <updated>2012-02-22T19:07:00-05:00</updated>
    <id>http://blog.thesilentpenguin.com/blog/2012/02/22/testing-puppet</id>
    <content type="html"><![CDATA[<p>An often over-looked part of Puppet is the fact that you can programmatically
test changes. The Puppet master has a &#8211;compile feature, which will work if
you sync the fact YAMLs from your master to the machine you run the &#8211;compile
from.</p>

<!-- more -->


<p>Puppet-cucumber looks to solve this, so I tried to start using it today. I
found that the features I need already work in my massive monolith test
script, and that puppet-cucumber was just not a good fit. Particularly because
it seemed a little obtuse in general, especially if I only wanted to test things
that changes in either one revision or range of revisions. Anyways, this is my
script for testing puppet changes. You will need GNU Parallel, Puppet, and
MySQL, maybe a couple other smaller deps to run it.</p>

<p>My typical usage is:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>scripts/puppet-test -d -e staging</span></code></pre></td></tr></table></div></figure>


<p>Before I have deployed. If you look at the script through, it supports revision
ranges and whatnot. -d is just a shortcut to run the tests against the changes
local to you that are not yet deployed.</p>

<p>As always, use at your own risk:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
<span class='line-number'>106</span>
<span class='line-number'>107</span>
<span class='line-number'>108</span>
<span class='line-number'>109</span>
<span class='line-number'>110</span>
<span class='line-number'>111</span>
<span class='line-number'>112</span>
<span class='line-number'>113</span>
<span class='line-number'>114</span>
<span class='line-number'>115</span>
<span class='line-number'>116</span>
<span class='line-number'>117</span>
<span class='line-number'>118</span>
<span class='line-number'>119</span>
<span class='line-number'>120</span>
<span class='line-number'>121</span>
<span class='line-number'>122</span>
<span class='line-number'>123</span>
<span class='line-number'>124</span>
<span class='line-number'>125</span>
<span class='line-number'>126</span>
<span class='line-number'>127</span>
<span class='line-number'>128</span>
<span class='line-number'>129</span>
<span class='line-number'>130</span>
<span class='line-number'>131</span>
<span class='line-number'>132</span>
<span class='line-number'>133</span>
<span class='line-number'>134</span>
<span class='line-number'>135</span>
<span class='line-number'>136</span>
<span class='line-number'>137</span>
<span class='line-number'>138</span>
<span class='line-number'>139</span>
<span class='line-number'>140</span>
<span class='line-number'>141</span>
<span class='line-number'>142</span>
<span class='line-number'>143</span>
<span class='line-number'>144</span>
<span class='line-number'>145</span>
<span class='line-number'>146</span>
<span class='line-number'>147</span>
<span class='line-number'>148</span>
<span class='line-number'>149</span>
<span class='line-number'>150</span>
<span class='line-number'>151</span>
<span class='line-number'>152</span>
<span class='line-number'>153</span>
<span class='line-number'>154</span>
<span class='line-number'>155</span>
<span class='line-number'>156</span>
<span class='line-number'>157</span>
<span class='line-number'>158</span>
<span class='line-number'>159</span>
<span class='line-number'>160</span>
<span class='line-number'>161</span>
<span class='line-number'>162</span>
<span class='line-number'>163</span>
<span class='line-number'>164</span>
<span class='line-number'>165</span>
<span class='line-number'>166</span>
<span class='line-number'>167</span>
<span class='line-number'>168</span>
<span class='line-number'>169</span>
<span class='line-number'>170</span>
<span class='line-number'>171</span>
<span class='line-number'>172</span>
<span class='line-number'>173</span>
<span class='line-number'>174</span>
<span class='line-number'>175</span>
<span class='line-number'>176</span>
<span class='line-number'>177</span>
<span class='line-number'>178</span>
<span class='line-number'>179</span>
<span class='line-number'>180</span>
<span class='line-number'>181</span>
<span class='line-number'>182</span>
<span class='line-number'>183</span>
<span class='line-number'>184</span>
<span class='line-number'>185</span>
<span class='line-number'>186</span>
<span class='line-number'>187</span>
<span class='line-number'>188</span>
<span class='line-number'>189</span>
<span class='line-number'>190</span>
<span class='line-number'>191</span>
<span class='line-number'>192</span>
<span class='line-number'>193</span>
<span class='line-number'>194</span>
<span class='line-number'>195</span>
<span class='line-number'>196</span>
<span class='line-number'>197</span>
<span class='line-number'>198</span>
<span class='line-number'>199</span>
<span class='line-number'>200</span>
<span class='line-number'>201</span>
<span class='line-number'>202</span>
<span class='line-number'>203</span>
<span class='line-number'>204</span>
<span class='line-number'>205</span>
<span class='line-number'>206</span>
<span class='line-number'>207</span>
<span class='line-number'>208</span>
<span class='line-number'>209</span>
<span class='line-number'>210</span>
<span class='line-number'>211</span>
<span class='line-number'>212</span>
<span class='line-number'>213</span>
<span class='line-number'>214</span>
<span class='line-number'>215</span>
<span class='line-number'>216</span>
<span class='line-number'>217</span>
<span class='line-number'>218</span>
<span class='line-number'>219</span>
<span class='line-number'>220</span>
<span class='line-number'>221</span>
<span class='line-number'>222</span>
<span class='line-number'>223</span>
<span class='line-number'>224</span>
<span class='line-number'>225</span>
<span class='line-number'>226</span>
<span class='line-number'>227</span>
<span class='line-number'>228</span>
<span class='line-number'>229</span>
<span class='line-number'>230</span>
<span class='line-number'>231</span>
<span class='line-number'>232</span>
<span class='line-number'>233</span>
<span class='line-number'>234</span>
<span class='line-number'>235</span>
<span class='line-number'>236</span>
<span class='line-number'>237</span>
<span class='line-number'>238</span>
<span class='line-number'>239</span>
<span class='line-number'>240</span>
<span class='line-number'>241</span>
<span class='line-number'>242</span>
<span class='line-number'>243</span>
<span class='line-number'>244</span>
<span class='line-number'>245</span>
<span class='line-number'>246</span>
<span class='line-number'>247</span>
<span class='line-number'>248</span>
<span class='line-number'>249</span>
<span class='line-number'>250</span>
<span class='line-number'>251</span>
<span class='line-number'>252</span>
<span class='line-number'>253</span>
<span class='line-number'>254</span>
<span class='line-number'>255</span>
<span class='line-number'>256</span>
<span class='line-number'>257</span>
<span class='line-number'>258</span>
<span class='line-number'>259</span>
<span class='line-number'>260</span>
<span class='line-number'>261</span>
<span class='line-number'>262</span>
<span class='line-number'>263</span>
<span class='line-number'>264</span>
<span class='line-number'>265</span>
<span class='line-number'>266</span>
<span class='line-number'>267</span>
<span class='line-number'>268</span>
<span class='line-number'>269</span>
<span class='line-number'>270</span>
<span class='line-number'>271</span>
<span class='line-number'>272</span>
<span class='line-number'>273</span>
<span class='line-number'>274</span>
<span class='line-number'>275</span>
<span class='line-number'>276</span>
<span class='line-number'>277</span>
<span class='line-number'>278</span>
<span class='line-number'>279</span>
<span class='line-number'>280</span>
<span class='line-number'>281</span>
<span class='line-number'>282</span>
<span class='line-number'>283</span>
<span class='line-number'>284</span>
<span class='line-number'>285</span>
<span class='line-number'>286</span>
<span class='line-number'>287</span>
<span class='line-number'>288</span>
<span class='line-number'>289</span>
<span class='line-number'>290</span>
<span class='line-number'>291</span>
<span class='line-number'>292</span>
<span class='line-number'>293</span>
<span class='line-number'>294</span>
<span class='line-number'>295</span>
<span class='line-number'>296</span>
<span class='line-number'>297</span>
<span class='line-number'>298</span>
<span class='line-number'>299</span>
<span class='line-number'>300</span>
<span class='line-number'>301</span>
<span class='line-number'>302</span>
<span class='line-number'>303</span>
<span class='line-number'>304</span>
<span class='line-number'>305</span>
<span class='line-number'>306</span>
<span class='line-number'>307</span>
<span class='line-number'>308</span>
<span class='line-number'>309</span>
<span class='line-number'>310</span>
<span class='line-number'>311</span>
<span class='line-number'>312</span>
<span class='line-number'>313</span>
<span class='line-number'>314</span>
<span class='line-number'>315</span>
<span class='line-number'>316</span>
<span class='line-number'>317</span>
<span class='line-number'>318</span>
<span class='line-number'>319</span>
<span class='line-number'>320</span>
<span class='line-number'>321</span>
<span class='line-number'>322</span>
<span class='line-number'>323</span>
<span class='line-number'>324</span>
<span class='line-number'>325</span>
<span class='line-number'>326</span>
<span class='line-number'>327</span>
<span class='line-number'>328</span>
<span class='line-number'>329</span>
<span class='line-number'>330</span>
<span class='line-number'>331</span>
<span class='line-number'>332</span>
<span class='line-number'>333</span>
<span class='line-number'>334</span>
<span class='line-number'>335</span>
<span class='line-number'>336</span>
<span class='line-number'>337</span>
<span class='line-number'>338</span>
<span class='line-number'>339</span>
<span class='line-number'>340</span>
<span class='line-number'>341</span>
<span class='line-number'>342</span>
<span class='line-number'>343</span>
<span class='line-number'>344</span>
<span class='line-number'>345</span>
<span class='line-number'>346</span>
<span class='line-number'>347</span>
<span class='line-number'>348</span>
<span class='line-number'>349</span>
<span class='line-number'>350</span>
<span class='line-number'>351</span>
<span class='line-number'>352</span>
<span class='line-number'>353</span>
<span class='line-number'>354</span>
<span class='line-number'>355</span>
<span class='line-number'>356</span>
<span class='line-number'>357</span>
<span class='line-number'>358</span>
<span class='line-number'>359</span>
<span class='line-number'>360</span>
<span class='line-number'>361</span>
<span class='line-number'>362</span>
<span class='line-number'>363</span>
<span class='line-number'>364</span>
<span class='line-number'>365</span>
<span class='line-number'>366</span>
<span class='line-number'>367</span>
<span class='line-number'>368</span>
<span class='line-number'>369</span>
<span class='line-number'>370</span>
<span class='line-number'>371</span>
<span class='line-number'>372</span>
<span class='line-number'>373</span>
<span class='line-number'>374</span>
<span class='line-number'>375</span>
<span class='line-number'>376</span>
<span class='line-number'>377</span>
<span class='line-number'>378</span>
<span class='line-number'>379</span>
<span class='line-number'>380</span>
<span class='line-number'>381</span>
<span class='line-number'>382</span>
<span class='line-number'>383</span>
<span class='line-number'>384</span>
<span class='line-number'>385</span>
<span class='line-number'>386</span>
<span class='line-number'>387</span>
<span class='line-number'>388</span>
<span class='line-number'>389</span>
<span class='line-number'>390</span>
<span class='line-number'>391</span>
<span class='line-number'>392</span>
<span class='line-number'>393</span>
<span class='line-number'>394</span>
<span class='line-number'>395</span>
<span class='line-number'>396</span>
<span class='line-number'>397</span>
<span class='line-number'>398</span>
<span class='line-number'>399</span>
<span class='line-number'>400</span>
<span class='line-number'>401</span>
<span class='line-number'>402</span>
<span class='line-number'>403</span>
<span class='line-number'>404</span>
<span class='line-number'>405</span>
<span class='line-number'>406</span>
<span class='line-number'>407</span>
<span class='line-number'>408</span>
<span class='line-number'>409</span>
<span class='line-number'>410</span>
<span class='line-number'>411</span>
<span class='line-number'>412</span>
<span class='line-number'>413</span>
<span class='line-number'>414</span>
<span class='line-number'>415</span>
<span class='line-number'>416</span>
<span class='line-number'>417</span>
<span class='line-number'>418</span>
<span class='line-number'>419</span>
<span class='line-number'>420</span>
<span class='line-number'>421</span>
<span class='line-number'>422</span>
<span class='line-number'>423</span>
<span class='line-number'>424</span>
<span class='line-number'>425</span>
<span class='line-number'>426</span>
<span class='line-number'>427</span>
<span class='line-number'>428</span>
<span class='line-number'>429</span>
<span class='line-number'>430</span>
<span class='line-number'>431</span>
<span class='line-number'>432</span>
<span class='line-number'>433</span>
<span class='line-number'>434</span>
<span class='line-number'>435</span>
<span class='line-number'>436</span>
<span class='line-number'>437</span>
<span class='line-number'>438</span>
<span class='line-number'>439</span>
<span class='line-number'>440</span>
<span class='line-number'>441</span>
<span class='line-number'>442</span>
<span class='line-number'>443</span>
<span class='line-number'>444</span>
<span class='line-number'>445</span>
<span class='line-number'>446</span>
<span class='line-number'>447</span>
<span class='line-number'>448</span>
<span class='line-number'>449</span>
<span class='line-number'>450</span>
<span class='line-number'>451</span>
<span class='line-number'>452</span>
<span class='line-number'>453</span>
<span class='line-number'>454</span>
<span class='line-number'>455</span>
<span class='line-number'>456</span>
<span class='line-number'>457</span>
<span class='line-number'>458</span>
<span class='line-number'>459</span>
<span class='line-number'>460</span>
<span class='line-number'>461</span>
<span class='line-number'>462</span>
<span class='line-number'>463</span>
<span class='line-number'>464</span>
<span class='line-number'>465</span>
<span class='line-number'>466</span>
<span class='line-number'>467</span>
<span class='line-number'>468</span>
<span class='line-number'>469</span>
<span class='line-number'>470</span>
<span class='line-number'>471</span>
<span class='line-number'>472</span>
<span class='line-number'>473</span>
<span class='line-number'>474</span>
<span class='line-number'>475</span>
<span class='line-number'>476</span>
<span class='line-number'>477</span>
<span class='line-number'>478</span>
<span class='line-number'>479</span>
<span class='line-number'>480</span>
<span class='line-number'>481</span>
<span class='line-number'>482</span>
<span class='line-number'>483</span>
<span class='line-number'>484</span>
<span class='line-number'>485</span>
<span class='line-number'>486</span>
<span class='line-number'>487</span>
<span class='line-number'>488</span>
<span class='line-number'>489</span>
<span class='line-number'>490</span>
<span class='line-number'>491</span>
<span class='line-number'>492</span>
<span class='line-number'>493</span>
<span class='line-number'>494</span>
<span class='line-number'>495</span>
<span class='line-number'>496</span>
<span class='line-number'>497</span>
<span class='line-number'>498</span>
<span class='line-number'>499</span>
<span class='line-number'>500</span>
<span class='line-number'>501</span>
<span class='line-number'>502</span>
<span class='line-number'>503</span>
<span class='line-number'>504</span>
<span class='line-number'>505</span>
<span class='line-number'>506</span>
<span class='line-number'>507</span>
<span class='line-number'>508</span>
<span class='line-number'>509</span>
<span class='line-number'>510</span>
<span class='line-number'>511</span>
<span class='line-number'>512</span>
<span class='line-number'>513</span>
<span class='line-number'>514</span>
<span class='line-number'>515</span>
<span class='line-number'>516</span>
<span class='line-number'>517</span>
<span class='line-number'>518</span>
<span class='line-number'>519</span>
<span class='line-number'>520</span>
<span class='line-number'>521</span>
<span class='line-number'>522</span>
<span class='line-number'>523</span>
<span class='line-number'>524</span>
<span class='line-number'>525</span>
<span class='line-number'>526</span>
<span class='line-number'>527</span>
<span class='line-number'>528</span>
<span class='line-number'>529</span>
<span class='line-number'>530</span>
<span class='line-number'>531</span>
<span class='line-number'>532</span>
<span class='line-number'>533</span>
<span class='line-number'>534</span>
<span class='line-number'>535</span>
<span class='line-number'>536</span>
<span class='line-number'>537</span>
<span class='line-number'>538</span>
<span class='line-number'>539</span>
<span class='line-number'>540</span>
<span class='line-number'>541</span>
<span class='line-number'>542</span>
<span class='line-number'>543</span>
<span class='line-number'>544</span>
<span class='line-number'>545</span>
<span class='line-number'>546</span>
<span class='line-number'>547</span>
<span class='line-number'>548</span>
<span class='line-number'>549</span>
<span class='line-number'>550</span>
<span class='line-number'>551</span>
<span class='line-number'>552</span>
<span class='line-number'>553</span>
<span class='line-number'>554</span>
<span class='line-number'>555</span>
<span class='line-number'>556</span>
<span class='line-number'>557</span>
<span class='line-number'>558</span>
<span class='line-number'>559</span>
<span class='line-number'>560</span>
<span class='line-number'>561</span>
<span class='line-number'>562</span>
<span class='line-number'>563</span>
<span class='line-number'>564</span>
<span class='line-number'>565</span>
<span class='line-number'>566</span>
<span class='line-number'>567</span>
<span class='line-number'>568</span>
<span class='line-number'>569</span>
<span class='line-number'>570</span>
<span class='line-number'>571</span>
<span class='line-number'>572</span>
<span class='line-number'>573</span>
<span class='line-number'>574</span>
<span class='line-number'>575</span>
<span class='line-number'>576</span>
<span class='line-number'>577</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c">#!/bin/bash</span>
</span><span class='line'><span class="c"># This script does syntax checks on a working tree of a puppet git repo,</span>
</span><span class='line'><span class="c"># and then utilizes the stored config DB to find a host that belongs to</span>
</span><span class='line'><span class="c"># a changed class, then compile the catalog for that host. Note that</span>
</span><span class='line'><span class="c"># this script is designed to be run in the scripts directory of the puppet</span>
</span><span class='line'><span class="c"># checkout.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># In regular mode, your diff is between the current origin. This can be mod-</span>
</span><span class='line'><span class="c"># ified by using the -d argument, which diffs against the deployed revision.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># This script can also be used as a git pre-commit hook, by placing it in</span>
</span><span class='line'><span class="c"># your git checkout under .git/hooks/pre-commit, or linking the git pre-</span>
</span><span class='line'><span class="c"># commit file to the script itself.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># Note that this script auto-detects whether you are in an svn or git</span>
</span><span class='line'><span class="c"># checkout, and alters its mode of operation depending on the VCS used.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># Also note that -r does not currently work right when git sub-modules</span>
</span><span class='line'><span class="c"># are involved. Will eventually be fixed.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># Finally, you should make sure you are in the root of the checkout when this</span>
</span><span class='line'><span class="c"># is run otherwise it likely won&#39;t work right, esp wrt submodules.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'>
</span><span class='line'><span class="k">function </span>caterror<span class="o">()</span> <span class="o">{</span>
</span><span class='line'>   cat <span class="s2">&quot;$1&quot;</span> &gt;&amp;2
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">function </span>die<span class="o">()</span> <span class="o">{</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;%s\n&quot;</span> <span class="s2">&quot;$1&quot;</span>
</span><span class='line'>   <span class="nb">exit</span> <span class="nv">$2</span>
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">function </span>usage<span class="o">()</span> <span class="o">{</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;                              _        _            _   \n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot; _ __  _   _ _ __  _ __   ___| |_     | |_ ___  ___| |_ \n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;| &#39;_ \| | | | &#39;_ \| &#39;_ \ / _ \ __|____| __/ _ \/ __| __|\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;| |_) | |_| | |_) | |_) |  __/ ||_____| ||  __/\__ \ |_ \n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;| .__/ \__,_| .__/| .__/ \___|\__|     \__\___||___/\__|\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;|_|         |_|   |_| \n\n&quot;</span>
</span><span class='line'>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;This script can be used to perform a thorough test of\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;your puppet checkout, including syntax, duplication,\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;and compile-time errors.\n\n&quot;</span>
</span><span class='line'>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;Note that specifying revisions here only applies to the diff.\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;This means that you should not expect this script to check\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;out the given revision to test the actual code from that\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;revision. This type of functionality will be added later.\n\n&quot;</span>
</span><span class='line'>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;Usage:\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   $(basename $0) [-c] [-e environment] [-f] [-F]\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   -d  Performs test of deployed rev v. your checkout\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   -e  Puppet environment to test against, default production\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   -f  Force tests even if there are no changes\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   -F  Really force, even for regex node checks\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   -m  Sets VCS mode. Can be &#39;git&#39;, &#39;svn&#39;, or &#39;git-svn&#39;\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   -P  Specify the root of your Puppet checkout. Default to ~/working/git/puppet\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   -r  Specify revision to diff against, or range of revisions to \n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;       diff between. Range must be in the form of rev1:rev2. Does not yet\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;       work with submodules.\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;\n&quot;</span>
</span><span class='line'>
</span><span class='line'>   <span class="nb">exit </span>0
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="nv">check_node_regex</span><span class="o">=</span><span class="nb">false</span>
</span><span class='line'><span class="nv">compile_failure_log</span><span class="o">=</span><span class="s2">&quot;$(mktemp /tmp/compile_failure_log.XXXXXX)&quot;</span>
</span><span class='line'><span class="nv">deployed</span><span class="o">=</span><span class="s2">&quot;false&quot;</span>
</span><span class='line'><span class="nv">environment</span><span class="o">=</span><span class="s2">&quot;production&quot;</span>
</span><span class='line'><span class="nv">error_msg</span><span class="o">=</span><span class="k">$(</span>mktemp /tmp/error_msg.XXXXXX<span class="k">)</span>
</span><span class='line'><span class="nv">force</span><span class="o">=</span><span class="s2">&quot;false&quot;</span>
</span><span class='line'><span class="nv">fullforce</span><span class="o">=</span><span class="s2">&quot;false&quot;</span>
</span><span class='line'><span class="nv">puppet_masters</span><span class="o">=</span><span class="s2">&quot;puppet.yoursite.com&quot;</span>
</span><span class='line'><span class="nv">puppetroot</span><span class="o">=</span><span class="s2">&quot;$HOME/working/git/puppet&quot;</span>
</span><span class='line'><span class="nv">storedconfig_password</span><span class="o">=</span><span class="s1">&#39;3287432424jkdhsfkh&#39;</span>
</span><span class='line'><span class="nv">syntax_errors</span><span class="o">=</span>0
</span><span class='line'><span class="nv">vcs</span><span class="o">=</span><span class="s2">&quot;&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="k">while </span><span class="nb">getopts </span>de:fFhm:P:r: option; <span class="k">do</span>
</span><span class='line'><span class="k">   case</span> <span class="s2">&quot;$option&quot;</span> in
</span><span class='line'>      d<span class="o">)</span>
</span><span class='line'>         <span class="nv">deployed</span><span class="o">=</span><span class="s2">&quot;true&quot;</span>
</span><span class='line'>      ;;
</span><span class='line'>      e<span class="o">)</span>
</span><span class='line'>         <span class="nv">environment</span><span class="o">=</span><span class="s2">&quot;$OPTARG&quot;</span>
</span><span class='line'>
</span><span class='line'>         <span class="k">if</span> <span class="o">[</span> <span class="s1">&#39;!&#39;</span> -d <span class="s2">&quot;${puppetroot}/${environment}&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nb">printf</span> <span class="s2">&quot;Environment %s does not exist\n.&quot;</span> <span class="s2">&quot;$environment&quot;</span>
</span><span class='line'>            <span class="nb">exit</span> -1
</span><span class='line'>         <span class="k">fi</span>
</span><span class='line'>      ;;
</span><span class='line'>      f<span class="o">)</span>
</span><span class='line'>         <span class="nv">force</span><span class="o">=</span><span class="s2">&quot;true&quot;</span>
</span><span class='line'>      ;;
</span><span class='line'>      F<span class="o">)</span>
</span><span class='line'>         <span class="nv">force</span><span class="o">=</span><span class="s2">&quot;true&quot;</span>
</span><span class='line'>         <span class="nv">fullforce</span><span class="o">=</span><span class="s2">&quot;true&quot;</span>
</span><span class='line'>      ;;
</span><span class='line'>      m<span class="o">)</span>
</span><span class='line'>         <span class="nv">vcs</span><span class="o">=</span><span class="s2">&quot;$OPTARG&quot;</span>
</span><span class='line'>
</span><span class='line'>         <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$vcs&quot;</span> !<span class="o">=</span> <span class="s2">&quot;git&quot;</span> -a <span class="s2">&quot;$vcs&quot;</span> !<span class="o">=</span> <span class="s2">&quot;svn&quot;</span> -a <span class="s2">&quot;$vcs&quot;</span> !<span class="o">=</span> <span class="s2">&quot;git-svn&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nb">printf</span> <span class="s2">&quot;FATAL: %s is not a supported VCS!\n&quot;</span> &gt;&amp;2
</span><span class='line'>            <span class="nb">exit</span> -15
</span><span class='line'>         <span class="k">fi</span>
</span><span class='line'>      ;;
</span><span class='line'>      P<span class="o">)</span>
</span><span class='line'>         <span class="nv">puppetroot</span><span class="o">=</span><span class="s2">&quot;$OPTARG&quot;</span>
</span><span class='line'>      ;;
</span><span class='line'>      r<span class="o">)</span>
</span><span class='line'>         <span class="nv">rev</span><span class="o">=</span><span class="s2">&quot;$OPTARG&quot;</span>
</span><span class='line'>      ;;
</span><span class='line'>      <span class="o">[</span>?h<span class="o">])</span>
</span><span class='line'>         usage
</span><span class='line'>      ;;
</span><span class='line'>   <span class="k">esac</span>
</span><span class='line'><span class="k">done</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Fail if puppetroot is not there</span>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> ! -d <span class="s2">&quot;$puppetroot&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span>die <span class="s2">&quot;FATAL: Puppet checkout not found at ${puppetroot}&quot;</span> -2
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Die if attempt to diff against prod and specify revision</span>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$deployed&quot;</span> <span class="o">==</span> <span class="s2">&quot;true&quot;</span> -a -n <span class="s2">&quot;$rev&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span>die <span class="s2">&quot;-d and -r are mutually exclusive options!&quot;</span> <span class="s2">&quot;107&quot;</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Attempt to auto-identify VCS if nothing is passed to -m</span>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -z <span class="s2">&quot;$vcs&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   if</span> <span class="o">[</span> -e <span class="s2">&quot;${puppetroot}/.git&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">      </span><span class="nv">vcs</span><span class="o">=</span><span class="s2">&quot;git&quot;</span>
</span><span class='line'>   <span class="k">elif</span> <span class="o">[</span> -e <span class="s2">&quot;${puppetroot}/.svn&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">      </span><span class="nv">vcs</span><span class="o">=</span><span class="s2">&quot;svn&quot;</span>
</span><span class='line'>   <span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">   if</span> <span class="o">[</span> -z <span class="s2">&quot;$vcs&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">      </span><span class="nb">printf</span> <span class="s2">&quot;FATAL: Could not determine VCS!\n&quot;</span> &gt;&amp;2
</span><span class='line'>      <span class="nb">exit</span> -1
</span><span class='line'>   <span class="k">else</span>
</span><span class='line'><span class="k">      </span><span class="nb">printf</span> <span class="s2">&quot;Selecting %s as vcs...\n&quot;</span> <span class="s2">&quot;$vcs&quot;</span>
</span><span class='line'>   <span class="k">fi</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Move to puppet root and let the games begin</span>
</span><span class='line'><span class="nb">cd</span> <span class="nv">$puppetroot</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Determine if given revision or revision range is valid. Die if not.</span>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -n <span class="s2">&quot;$rev&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span><span class="nb">export </span><span class="nv">IFS</span><span class="o">=</span>:
</span><span class='line'>   <span class="k">case</span> <span class="s2">&quot;$vcs&quot;</span> in
</span><span class='line'>      git<span class="o">)</span>
</span><span class='line'>         <span class="k">for </span>r in <span class="nv">$rev</span>; <span class="k">do</span>
</span><span class='line'><span class="k">            if</span> <span class="s1">&#39;!&#39;</span> git show --summary <span class="k">${</span><span class="nv">r</span><span class="k">}</span> &gt;/dev/null 2&gt;&amp;1; <span class="k">then</span>
</span><span class='line'><span class="k">               </span>die <span class="s2">&quot;Git revision ${r} is not valid&quot;</span> <span class="s2">&quot;69&quot;</span>
</span><span class='line'>            <span class="k">fi</span>
</span><span class='line'><span class="k">         done</span>
</span><span class='line'>      ;;
</span><span class='line'>      git-svn<span class="o">)</span>
</span><span class='line'>         <span class="k">for </span>r in <span class="nv">$rev</span>; <span class="k">do</span>
</span><span class='line'><span class="k">            if</span> <span class="s1">&#39;!&#39;</span> git svn find-rev r<span class="k">${</span><span class="nv">r</span><span class="k">}</span> &gt;/dev/null 2&gt;&amp;1; <span class="k">then</span>
</span><span class='line'><span class="k">               </span>die <span class="s2">&quot;SVN Revision ${r} does not exit&quot;</span> <span class="s2">&quot;70&quot;</span>
</span><span class='line'>            <span class="k">fi</span>
</span><span class='line'><span class="k">         done</span>
</span><span class='line'>      ;;
</span><span class='line'>      svn<span class="o">)</span>
</span><span class='line'>         <span class="k">for </span>r in <span class="nv">$rev</span>; <span class="k">do</span>
</span><span class='line'><span class="k">            if</span> <span class="s1">&#39;!&#39;</span> svn info -r<span class="k">${</span><span class="nv">r</span><span class="k">}</span> &gt;/dev/null 2&gt;&amp;1; <span class="k">then</span>
</span><span class='line'><span class="k">               </span>die <span class="s2">&quot;SVN Revision ${r} is not valid&quot;</span> <span class="s2">&quot;71&quot;</span>
</span><span class='line'>            <span class="k">fi</span>
</span><span class='line'><span class="k">         done</span>
</span><span class='line'>      ;;
</span><span class='line'>      *<span class="o">)</span>
</span><span class='line'>         die <span class="s2">&quot;Sense is not being made&quot;</span> <span class="s2">&quot;42&quot;</span>
</span><span class='line'>      ;;
</span><span class='line'>   <span class="k">esac</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="c"># It would be a little weird to try and add conditionals to save some lines</span>
</span><span class='line'><span class="c"># here, so we just do separate behavior for each VCS.</span>
</span><span class='line'><span class="k">case</span> <span class="nv">$vcs</span> in
</span><span class='line'>   git<span class="o">)</span>
</span><span class='line'>      <span class="nv">current_branch</span><span class="o">=</span><span class="k">$(</span>git branch | egrep <span class="s1">&#39;^\*&#39;</span> | cut -d<span class="s1">&#39; &#39;</span> -f2<span class="k">)</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$current_branch&quot;</span> <span class="o">==</span> <span class="s2">&quot;master&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">         </span>git pull --all &gt;/dev/null 2&gt;&amp;1
</span><span class='line'>         git submodule update --merge &gt;/dev/null 2&gt;&amp;1
</span><span class='line'>
</span><span class='line'>         <span class="k">if</span> <span class="o">[</span> <span class="nv">$?</span> -ne 0 <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nb">printf</span> <span class="s2">&quot;Unspecified error when running git pull and/or submodule update on your checkout!\n&quot;</span> &gt;&amp;2
</span><span class='line'>            <span class="nb">exit</span> -1
</span><span class='line'>         <span class="k">fi</span>
</span><span class='line'><span class="k">      fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">      if</span> <span class="o">[</span> <span class="s2">&quot;$deployed&quot;</span> <span class="o">=</span> <span class="s2">&quot;true&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">         </span><span class="nv">oldrev</span><span class="o">=</span><span class="k">$(</span>ssh <span class="k">$(</span><span class="nb">echo</span> <span class="nv">$puppet_masters</span> | cut -d<span class="s1">&#39; &#39;</span> -f1<span class="k">)</span> <span class="s2">&quot;sudo cat /etc/puppet/REVISION&quot;</span><span class="k">)</span>
</span><span class='line'>         <span class="nv">diffcmd</span><span class="o">=</span><span class="s2">&quot;git diff ${oldrev}&quot;</span>
</span><span class='line'>      <span class="k">elif</span> <span class="o">[</span> -n <span class="s2">&quot;$rev&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">         </span><span class="nv">diffcmd</span><span class="o">=</span><span class="s2">&quot;git diff $(echo $rev | tr &#39;:&#39; &#39; &#39;)&quot;</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'><span class="k">         </span><span class="nv">diffcmd</span><span class="o">=</span><span class="s2">&quot;git diff origin&quot;</span>
</span><span class='line'>      <span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">      </span><span class="nb">unset </span>IFS
</span><span class='line'>
</span><span class='line'>      <span class="c"># Get list of submodules</span>
</span><span class='line'>      <span class="nv">submodules</span><span class="o">=</span><span class="k">$(</span>git submodule | cut -c2-<span class="k">)</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$submodules&quot;</span> <span class="o">==</span> <span class="s2">&quot;&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">         </span><span class="nv">changes</span><span class="o">=</span><span class="k">$(</span><span class="se">\</span>
</span><span class='line'>                  <span class="nb">eval</span> <span class="k">${</span><span class="nv">diffcmd</span><span class="k">}</span> <span class="se">\</span>
</span><span class='line'>                  | grep <span class="s1">&#39;^+++&#39;</span> <span class="se">\</span>
</span><span class='line'>                  | grep -v <span class="s1">&#39;/dev/null$&#39;</span> <span class="se">\</span>
</span><span class='line'>                  | cut -d<span class="s1">&#39;/&#39;</span> -f2- <span class="se">\</span>
</span><span class='line'>                  | sort -u <span class="se">\</span>
</span><span class='line'>                  <span class="k">)</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'><span class="k">         if</span> <span class="o">[</span> <span class="s2">&quot;$deployed&quot;</span> <span class="o">==</span> <span class="s2">&quot;true&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nv">changes</span><span class="o">=</span><span class="s2">&quot;$($puppetroot/scripts/uberdiff.rb &quot;</span><span class="k">${</span><span class="nv">oldrev</span><span class="k">}</span><span class="s2">&quot;)&quot;</span>
</span><span class='line'>         <span class="k">elif</span> <span class="o">[</span> -n <span class="s2">&quot;$rev&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nv">changes</span><span class="o">=</span><span class="s2">&quot;$($puppetroot/scripts/uberdiff.rb \&quot;$(echo $rev | tr &#39;:&#39; &#39; &#39;)\&quot;)&quot;</span>
</span><span class='line'>         <span class="k">else</span>
</span><span class='line'><span class="k">            </span><span class="nv">changes</span><span class="o">=</span><span class="s2">&quot;$($puppetroot/scripts/uberdiff.rb HEAD)&quot;</span>
</span><span class='line'>         <span class="k">fi</span>
</span><span class='line'><span class="k">      fi</span>
</span><span class='line'>   ;;
</span><span class='line'>   git-svn<span class="o">)</span>
</span><span class='line'>      <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$deployed&quot;</span> <span class="o">=</span> <span class="s2">&quot;true&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">         </span><span class="nv">oldsvnrev</span><span class="o">=</span><span class="k">$(</span>ssh <span class="k">$(</span><span class="nb">echo</span> <span class="nv">$puppet_masters</span> | cut -d<span class="s1">&#39; &#39;</span> -f1<span class="k">)</span> <span class="s2">&quot;sudo cat /etc/puppet/REVISION&quot;</span><span class="k">)</span>
</span><span class='line'>         <span class="nv">oldrev</span><span class="o">=</span><span class="k">$(</span>git svn find-rev r<span class="k">${</span><span class="nv">oldsvnrev</span><span class="k">})</span>
</span><span class='line'>         <span class="nv">diffcmd</span><span class="o">=</span><span class="s2">&quot;git diff ${oldrev}&quot;</span>
</span><span class='line'>      <span class="k">elif</span> <span class="o">[</span> -n <span class="s2">&quot;$rev&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">         for </span>r in <span class="nv">$rev</span>; <span class="k">do</span>
</span><span class='line'><span class="k">            </span><span class="nv">gitrev</span><span class="o">=</span><span class="s2">&quot;$gitrev $(git svn find-rev r${r})&quot;</span>
</span><span class='line'>         <span class="k">done</span>
</span><span class='line'>
</span><span class='line'><span class="k">         </span><span class="nv">diffcmd</span><span class="o">=</span><span class="s2">&quot;git diff $gitrev&quot;</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'><span class="k">         </span><span class="nv">diffcmd</span><span class="o">=</span><span class="s2">&quot;git diff git-svn&quot;</span>
</span><span class='line'>      <span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">      </span><span class="nb">unset </span>IFS
</span><span class='line'>      <span class="nv">changes</span><span class="o">=</span><span class="k">$(</span><span class="se">\</span>
</span><span class='line'>               <span class="nb">eval</span> <span class="k">${</span><span class="nv">diffcmd</span><span class="k">}</span> <span class="se">\</span>
</span><span class='line'>               | grep <span class="s1">&#39;^+++&#39;</span> <span class="se">\</span>
</span><span class='line'>               | grep -v <span class="s1">&#39;/dev/null$&#39;</span> <span class="se">\</span>
</span><span class='line'>               | cut -d<span class="s1">&#39;/&#39;</span> -f2- <span class="se">\</span>
</span><span class='line'>               | sort -u <span class="se">\</span>
</span><span class='line'>               <span class="k">)</span>
</span><span class='line'>   ;;
</span><span class='line'>   svn<span class="o">)</span>
</span><span class='line'>      svn up &gt;/dev/null 2&gt;&amp;1
</span><span class='line'>
</span><span class='line'>      <span class="k">if</span> <span class="o">[</span> <span class="nv">$?</span> -ne 0 <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">         </span><span class="nb">printf</span> <span class="s2">&quot;Unspecified error when running svn up on your checkout!\n&quot;</span> &gt;&amp;2
</span><span class='line'>         <span class="nb">exit</span> -1
</span><span class='line'>      <span class="k">fi</span>
</span><span class='line'><span class="k">      </span>
</span><span class='line'><span class="k">      if</span> <span class="o">[</span> <span class="s2">&quot;$deployed&quot;</span> <span class="o">==</span> <span class="s1">&#39;true&#39;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">         </span><span class="nv">oldrev</span><span class="o">=</span><span class="k">$(</span>ssh <span class="k">$(</span><span class="nb">echo</span> <span class="nv">$puppet_masters</span> | cut -d<span class="s1">&#39; &#39;</span> -f1<span class="k">)</span> <span class="s2">&quot;sudo cat /etc/puppet/REVISION&quot;</span><span class="k">)</span>
</span><span class='line'>         <span class="nv">diffcmd</span><span class="o">=</span><span class="s2">&quot;svn diff -r${oldrev}&quot;</span>
</span><span class='line'>      <span class="k">elif</span> <span class="o">[</span> -n <span class="s2">&quot;$rev&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">         </span><span class="nv">diffcmd</span><span class="o">=</span><span class="s2">&quot;svn diff -r${rev}&quot;</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'><span class="k">         </span><span class="nv">diffcmd</span><span class="o">=</span><span class="s2">&quot;svn diff&quot;</span>
</span><span class='line'>      <span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">      </span><span class="nb">unset </span>IFS
</span><span class='line'>      <span class="nv">changes</span><span class="o">=</span><span class="k">$(</span><span class="se">\</span>
</span><span class='line'>               <span class="nb">eval</span> <span class="k">${</span><span class="nv">diffcmd</span><span class="k">}</span> <span class="se">\</span>
</span><span class='line'>               | grep <span class="s1">&#39;^+++&#39;</span> <span class="se">\</span>
</span><span class='line'>               | cut -d<span class="s1">&#39; &#39;</span> -f2- <span class="se">\</span>
</span><span class='line'>               | sed <span class="s1">&#39;s/[[:space:]]\+(working copy)//g&#39;</span> <span class="se">\</span>
</span><span class='line'>               | sort -u <span class="se">\</span>
</span><span class='line'>               <span class="k">)</span>
</span><span class='line'>   ;;
</span><span class='line'>   *<span class="o">)</span>
</span><span class='line'>      <span class="nb">printf</span> <span class="s2">&quot;FATAL: Pigs have flown\n&quot;</span> &gt;&amp;2
</span><span class='line'>      <span class="nb">exit</span> -42
</span><span class='line'>   ;;
</span><span class='line'><span class="k">esac</span>
</span><span class='line'>
</span><span class='line'><span class="c"># If no changes and not in force mode, end.</span>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -z <span class="s2">&quot;$changes&quot;</span> -a <span class="s2">&quot;$force&quot;</span> <span class="o">==</span> <span class="s2">&quot;false&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">    </span><span class="nb">printf</span> <span class="s2">&quot;No changes made.\n&quot;</span>
</span><span class='line'>    rm -f <span class="nv">$error_msg</span>
</span><span class='line'>    <span class="nb">exit </span>0
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="c"># If full force mode is on, set check_node_regex to true</span>
</span><span class='line'><span class="nv">check_node_regex</span><span class="o">=</span><span class="s2">&quot;$fullforce&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># If full force is off, but there are node changes, set check_node_regex true</span>
</span><span class='line'><span class="k">if </span><span class="nb">echo</span> <span class="nv">$changes</span> | grep -q <span class="s1">&#39;manifests/nodes&#39;</span>; <span class="k">then</span>
</span><span class='line'><span class="k">    </span><span class="nv">check_node_regex</span><span class="o">=</span><span class="nb">true</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="c"># The syntax checks also check for hard tabs in Ruby, ERB, shell, and puppet</span>
</span><span class='line'><span class="c"># code. It is fairly stupid and only uses file extensions to do this.</span>
</span><span class='line'><span class="nb">printf</span> <span class="s2">&quot;Checking syntax on changes in working tree... &quot;</span>
</span><span class='line'><span class="k">for </span>change in <span class="nv">$changes</span>; <span class="k">do</span>
</span><span class='line'><span class="k">   case</span> <span class="nv">$change</span> in
</span><span class='line'>      *.erb<span class="o">)</span>
</span><span class='line'>         <span class="c"># Check ERB template syntax</span>
</span><span class='line'>         cat <span class="nv">$change</span> <span class="se">\</span>
</span><span class='line'>         | erb -P -x -T - <span class="se">\</span>
</span><span class='line'>         | ruby -cw 2&gt; <span class="nv">$error_msg</span> &gt; /dev/null
</span><span class='line'>
</span><span class='line'>         <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$?&quot;</span> -ne 0 <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nb">printf</span> <span class="s1">&#39;FAIL!\nERB Parse Failure:\n&#39;</span> &gt;&amp;2
</span><span class='line'>            <span class="nb">printf</span> <span class="s2">&quot;$change: &quot;</span> &gt;&amp;2
</span><span class='line'>            caterror <span class="nv">$error_msg</span>
</span><span class='line'>            <span class="nv">syntax_errors</span><span class="o">=</span><span class="k">$((</span>syntax_errors <span class="o">+</span> <span class="m">1</span><span class="k">))</span>
</span><span class='line'>         <span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">         if </span>cat <span class="nv">$change</span> | grep -q <span class="s1">&#39; &#39;</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nb">printf</span> <span class="s1">&#39;FAIL!\nHard tabs found in %s!\n&#39;</span> <span class="s2">&quot;$change&quot;</span> &gt;&amp;2
</span><span class='line'>            <span class="nv">syntax_errors</span><span class="o">=</span><span class="k">$((</span>syntax_errors <span class="o">+</span> <span class="m">1</span><span class="k">))</span>
</span><span class='line'>         <span class="k">fi</span>
</span><span class='line'>      ;;
</span><span class='line'>      *.pp<span class="o">)</span>
</span><span class='line'>         <span class="c"># Check puppet manifest syntax</span>
</span><span class='line'>          puppet parser validate --color<span class="o">=</span><span class="nb">false</span> --ignoreimport <span class="nv">$change</span> &gt; <span class="nv">$error_msg</span> 2&gt;&amp;1
</span><span class='line'>
</span><span class='line'>         <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$?&quot;</span> -ne 0 <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nb">printf</span> <span class="s1">&#39;FAIL!\nPuppet Parse Failure:\n&#39;</span> &gt;&amp;2
</span><span class='line'>            <span class="nb">printf</span> <span class="s2">&quot;$change: &quot;</span> &gt;&amp;2
</span><span class='line'>            caterror <span class="nv">$error_msg</span>
</span><span class='line'>            <span class="nv">syntax_errors</span><span class="o">=</span><span class="k">$((</span>syntax_errors <span class="o">+</span> <span class="m">1</span><span class="k">))</span>
</span><span class='line'>         <span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">         if </span>cat <span class="nv">$change</span> | grep -q <span class="s1">&#39; &#39;</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nb">printf</span> <span class="s1">&#39;FAIL!\nHard tabs found in %s!\n&#39;</span> <span class="s2">&quot;$change&quot;</span> &gt;&amp;2
</span><span class='line'>            <span class="nv">syntax_errors</span><span class="o">=</span><span class="k">$((</span>syntax_errors <span class="o">+</span> <span class="m">1</span><span class="k">))</span>
</span><span class='line'>         <span class="k">fi</span>
</span><span class='line'>      ;;
</span><span class='line'>      *.rb<span class="o">)</span>
</span><span class='line'>         <span class="c"># Check Ruby template syntax</span>
</span><span class='line'>         cat <span class="nv">$change</span> <span class="se">\</span>
</span><span class='line'>         | ruby -cw &gt; /dev/null
</span><span class='line'>
</span><span class='line'>         <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$?&quot;</span> -ne 0 <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nb">printf</span> <span class="s1">&#39;FAIL!\nRuby Parse Failure:\n&#39;</span> &gt;&amp;2
</span><span class='line'>            <span class="nb">printf</span> <span class="s2">&quot;$change: &quot;</span> &gt;&amp;2
</span><span class='line'>            caterror <span class="nv">$error_msg</span>
</span><span class='line'>            <span class="nv">syntax_errors</span><span class="o">=</span><span class="k">$((</span>syntax_errors <span class="o">+</span> <span class="m">1</span><span class="k">))</span>
</span><span class='line'>         <span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">         if </span>cat <span class="nv">$change</span> | grep -q <span class="s1">&#39; &#39;</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nb">printf</span> <span class="s1">&#39;FAIL!\nHard tabs found in %s!\n&#39;</span> <span class="s2">&quot;$change&quot;</span> &gt;&amp;2
</span><span class='line'>            <span class="nv">syntax_errors</span><span class="o">=</span><span class="k">$((</span>syntax_errors <span class="o">+</span> <span class="m">1</span><span class="k">))</span>
</span><span class='line'>         <span class="k">fi</span>
</span><span class='line'>      ;;
</span><span class='line'>      *.sh<span class="o">)</span>
</span><span class='line'>         <span class="c"># Shell scripts</span>
</span><span class='line'>         cat <span class="nv">$change</span> <span class="se">\</span>
</span><span class='line'>         | bash -n
</span><span class='line'>
</span><span class='line'>         <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$?&quot;</span> -ne 0 <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nb">printf</span> <span class="s1">&#39;FAIL!\nParse Failure:\n&#39;</span> &gt;&amp;2
</span><span class='line'>            <span class="nb">printf</span> <span class="s2">&quot;$change: &quot;</span> &gt;&amp;2
</span><span class='line'>            caterror <span class="nv">$error_msg</span>
</span><span class='line'>            <span class="nv">syntax_errors</span><span class="o">=</span><span class="k">$((</span>syntax_errors <span class="o">+</span> <span class="m">1</span><span class="k">))</span>
</span><span class='line'>         <span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">         if </span>cat <span class="nv">$change</span> | grep -q <span class="s1">&#39; &#39;</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nb">printf</span> <span class="s1">&#39;FAIL!\nHard tabs found in %s!\n&#39;</span> <span class="s2">&quot;$change&quot;</span> &gt;&amp;2
</span><span class='line'>            <span class="nv">syntax_errors</span><span class="o">=</span><span class="k">$((</span>syntax_errors <span class="o">+</span> <span class="m">1</span><span class="k">))</span>
</span><span class='line'>         <span class="k">fi</span>
</span><span class='line'>      ;;
</span><span class='line'>   <span class="k">esac</span>
</span><span class='line'>
</span><span class='line'><span class="k">   </span>rm -f <span class="nv">$error_msg</span>
</span><span class='line'>
</span><span class='line'>   <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$syntax_errors&quot;</span> -ne 0 <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">      </span><span class="nb">printf</span> <span class="se">\</span>
</span><span class='line'>         <span class="s1">&#39;%s syntax or style errors found!\n&#39;</span> <span class="se">\</span>
</span><span class='line'>         <span class="s2">&quot;$syntax_errors&quot;</span> &gt;&amp;2
</span><span class='line'>      <span class="nb">exit </span>1
</span><span class='line'>   <span class="k">fi</span>
</span><span class='line'><span class="k">done</span>
</span><span class='line'><span class="nb">printf</span> <span class="s2">&quot;SUCCESS!\n&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Now let&#39;s check for duplicate defined classes</span>
</span><span class='line'><span class="nb">printf</span> <span class="s2">&quot;Checking for duplicate class definitions... &quot;</span>
</span><span class='line'><span class="nv">IFS</span><span class="o">=</span><span class="s1">$&#39;\n&#39;</span>
</span><span class='line'><span class="nv">sorted_classlist</span><span class="o">=(</span> <span class="k">$(</span>find <span class="nv">$puppetroot</span>/<span class="nv">$environment</span> -type f -name <span class="s1">&#39;*.pp&#39;</span> -a ! -path <span class="nv">$puppetroot</span>/dist<span class="se">\*</span> -exec egrep -h <span class="s1">&#39;class[[:space:]]+([[:alnum:]]|[-_:])+[[:space:]]+(inherits[[:space:]]+([[:alnum:]]|[-_:])+|.*)*{&#39;</span> <span class="o">{}</span> <span class="se">\;</span> | sort<span class="k">)</span> <span class="o">)</span>
</span><span class='line'><span class="nb">unset </span>IFS
</span><span class='line'>
</span><span class='line'><span class="nv">duplicate_classlist</span><span class="o">=</span><span class="k">$(</span><span class="se">\</span>
</span><span class='line'>   <span class="k">for</span> <span class="o">((</span><span class="nv">i</span> <span class="o">=</span> 0; i &lt; <span class="k">${#</span><span class="nv">sorted_classlist</span><span class="p">[*]</span><span class="k">}</span>; i++<span class="k">)</span><span class="o">)</span>; <span class="k">do</span>
</span><span class='line'><span class="k">      </span><span class="nb">echo</span> <span class="k">${</span><span class="nv">sorted_classlist</span><span class="p">[</span><span class="nv">$i</span><span class="p">]</span><span class="k">}</span>
</span><span class='line'>   <span class="k">done</span> | uniq -d | awk <span class="s1">&#39;{ print $2 }&#39;</span> <span class="se">\</span>
</span><span class='line'><span class="o">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -n <span class="s2">&quot;$duplicate_classlist&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span><span class="nb">printf</span> <span class="s2">&quot;FAIL!\n\nIt appears that the following classes have duplicates:\n&quot;</span> &gt;&amp;2
</span><span class='line'>
</span><span class='line'>   <span class="k">for</span> <span class="o">((</span><span class="nv">i</span> <span class="o">=</span> 0; i &lt; <span class="k">${#</span><span class="nv">duplicate_classlist</span><span class="p">[*]</span><span class="k">}</span>; i++<span class="o">))</span>; <span class="k">do</span>
</span><span class='line'><span class="k">      </span><span class="nb">printf</span> <span class="s2">&quot;%s\n&quot;</span> <span class="s2">&quot;${duplicate_classlist[$i]}&quot;</span> &gt;&amp;2
</span><span class='line'>   <span class="k">done</span>
</span><span class='line'>
</span><span class='line'><span class="k">   </span><span class="nb">printf</span> <span class="se">\</span>
</span><span class='line'><span class="s2">&quot;Please locate these files using &quot;</span>egrep -R <span class="s1">&#39;class classname {&#39;</span> *<span class="s2">&quot; from the</span>
</span><span class='line'><span class="s2">root of the puppet checkout.\n&quot;</span>
</span><span class='line'>
</span><span class='line'>   <span class="nb">exit</span> -1
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="nb">printf</span> <span class="s1">&#39;SUCCESS!\n&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Check for duplicate node regexes if nodes files have changed, or full force</span>
</span><span class='line'><span class="c"># mode is on.</span>
</span><span class='line'><span class="k">if</span> <span class="nv">$check_node_regex</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span><span class="nb">printf</span> <span class="s2">&quot;Checking for duplicate node regexes... &quot;</span>
</span><span class='line'>   <span class="k">for </span>master in <span class="nv">$puppet_masters</span>; <span class="k">do</span>
</span><span class='line'><span class="k">      </span><span class="nv">nodelist</span><span class="o">=</span><span class="s2">&quot;$nodelist $(\</span>
</span><span class='line'><span class="s2">               ssh $master \&quot;\</span>
</span><span class='line'><span class="s2">               sudo mysql -s \</span>
</span><span class='line'><span class="s2">                    -D puppet \</span>
</span><span class='line'><span class="s2">                    -h $master \</span>
</span><span class='line'><span class="s2">                    -e \&quot;select name from hosts;\&quot; \</span>
</span><span class='line'><span class="s2">               | cat \</span>
</span><span class='line'><span class="s2">               \&quot;)&quot;</span>
</span><span class='line'>   <span class="k">done</span>
</span><span class='line'>
</span><span class='line'><span class="k">   if</span> <span class="o">[</span> -z <span class="s2">&quot;$nodelist&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">      </span><span class="nb">printf</span> <span class="s1">&#39;FAIL! Unspecified Error retrieving nodes from database!\n&#39;</span> &gt;&amp;2
</span><span class='line'>      <span class="nb">exit</span> -1
</span><span class='line'>   <span class="k">fi</span>
</span><span class='line'>
</span><span class='line'>   <span class="c"># Sort nodes to remove duplicates, which can happen if the databases are</span>
</span><span class='line'>   <span class="c"># not maintained.</span>
</span><span class='line'>   <span class="nv">sorted_nodelist</span><span class="o">=</span><span class="k">$(</span><span class="nb">echo</span> <span class="nv">$nodelist</span> | sort -u<span class="k">)</span>
</span><span class='line'>
</span><span class='line'>   <span class="k">for </span>node_manifest in <span class="nv">$puppetroot</span>/<span class="nv">$environment</span>/manifests/nodes*; <span class="k">do</span>
</span><span class='line'><span class="k">      </span><span class="nv">node_regex_list</span><span class="o">=</span><span class="s2">&quot;$node_regex_list $(egrep -h &#39;^node /&#39; $node_manifest | cut -d&#39;/&#39; -f2)&quot;</span>
</span><span class='line'>   <span class="k">done</span>
</span><span class='line'>
</span><span class='line'>   <span class="c"># This variable is so we can check how many total dupes there were</span>
</span><span class='line'>   <span class="nv">global_duplicates</span><span class="o">=</span>0
</span><span class='line'>   <span class="k">for </span>node in <span class="nv">$sorted_nodelist</span>; <span class="k">do</span>
</span><span class='line'><span class="k">      </span><span class="nv">matches</span><span class="o">=</span><span class="s2">&quot;&quot;</span>
</span><span class='line'>      <span class="nv">matchcount</span><span class="o">=</span>0
</span><span class='line'>      <span class="k">for </span>node_regex in <span class="nv">$node_regex_list</span>; <span class="k">do</span>
</span><span class='line'><span class="k">         if</span> <span class="o">[[</span> <span class="s2">&quot;$node&quot;</span> <span class="o">=</span>~ <span class="nv">$node_regex</span> <span class="o">]]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">            </span><span class="nv">matches</span><span class="o">=</span><span class="s2">&quot;$matches $node_regex&quot;</span>
</span><span class='line'>            <span class="nv">matchcount</span><span class="o">=</span><span class="k">$((</span>matchcount+1<span class="k">))</span>
</span><span class='line'>         <span class="k">fi</span>
</span><span class='line'><span class="k">      done</span>
</span><span class='line'>
</span><span class='line'><span class="k">      if</span> <span class="o">[</span> <span class="nv">$matchcount</span> -gt 1 <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">         </span><span class="nv">global_duplicates</span><span class="o">=</span><span class="k">$((</span>global_duplicates+1<span class="k">))</span>
</span><span class='line'>         <span class="nb">printf</span> <span class="s2">&quot;WARNING: %s matches multiple regexes:\n&quot;</span> <span class="s2">&quot;$node&quot;</span> &gt;&amp;2
</span><span class='line'>         <span class="k">for </span>regex in <span class="nv">$matches</span>; <span class="k">do</span>
</span><span class='line'><span class="k">            </span><span class="nb">printf</span> <span class="s2">&quot;%s\n&quot;</span> <span class="s2">&quot;$regex&quot;</span>
</span><span class='line'>         <span class="k">done</span>
</span><span class='line'><span class="k">      fi</span>
</span><span class='line'><span class="k">   done</span>
</span><span class='line'>
</span><span class='line'><span class="k">   if</span> <span class="o">[</span> <span class="nv">$global_duplicates</span> -gt 0 <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">      </span><span class="nb">printf</span> <span class="s2">&quot;FAIL!\n%d duplicate node regexes found.\n&quot;</span> <span class="nv">$global_duplicates</span> &gt;&amp;2
</span><span class='line'>      <span class="nb">exit</span> -2
</span><span class='line'>   <span class="k">else</span>
</span><span class='line'><span class="k">      </span><span class="nb">printf</span> <span class="s2">&quot;SUCCESS!\n&quot;</span>
</span><span class='line'>   <span class="k">fi</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Now we compile for compile-time errors</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Cat changes files and look for classes</span>
</span><span class='line'><span class="nb">printf</span> <span class="s1">&#39;Checking for compilation errors...\n&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Get changes that are applicable (puppet manifest changes only)</span>
</span><span class='line'><span class="nv">pp_changes</span><span class="o">=</span><span class="k">$(</span><span class="se">\</span>
</span><span class='line'>            <span class="k">for </span>change in <span class="nv">$changes</span>; <span class="k">do</span>
</span><span class='line'><span class="k">               if</span> <span class="o">[[</span> <span class="nv">$change</span> <span class="o">=</span>~ .pp<span class="nv">$ </span><span class="o">]]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">                  </span><span class="nb">printf</span> <span class="s2">&quot;%s &quot;</span> <span class="s2">&quot;$change&quot;</span>
</span><span class='line'>               <span class="k">fi</span>
</span><span class='line'><span class="k">            done</span>
</span><span class='line'>            <span class="k">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -z <span class="s2">&quot;${pp_changes}&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span><span class="nb">printf</span> <span class="s2">&quot;No puppet manifest changes to test for compilation errors, exiting!\n&quot;</span>
</span><span class='line'>   <span class="nb">exit </span>0
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="nv">classes</span><span class="o">=</span><span class="k">$(</span><span class="se">\</span>
</span><span class='line'>         cat <span class="nv">$pp_changes</span> <span class="se">\</span>
</span><span class='line'>         | egrep -v <span class="s1">&#39;^[[:space:]]+?#&#39;</span> <span class="se">\</span>
</span><span class='line'>         | egrep <span class="s1">&#39;^[[:space:]]+?class[[:space:]]+([[:alnum:]]|[-_:])+[[:space:]]+(inherits[[:space:]]+([[:alnum:]]|[-_:])+|.*)*({|\()&#39;</span> <span class="se">\</span>
</span><span class='line'>         | awk -F<span class="s1">&#39; &#39;</span> <span class="s1">&#39;{ print $2 }&#39;</span> <span class="se">\</span>
</span><span class='line'>         <span class="k">)</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Should have at least one server for a non-specific compile test</span>
</span><span class='line'><span class="nv">servers</span><span class="o">=</span><span class="s2">&quot;puppet.yoursite.com&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Ensure fake ssldir is set up</span>
</span><span class='line'>sudo mkdir -p /var/lib/puppet-test-<span class="nv">$USER</span>
</span><span class='line'>sudo rsync -r --delete <span class="nv">$puppetroot</span>/ssl/ /var/lib/puppet-test-<span class="nv">$USER</span>/ssl/
</span><span class='line'>sudo chown -R <span class="nv">$USER</span> /var/lib/puppet-test-<span class="nv">$USER</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Now we will find one host for each changed class to add to the list of</span>
</span><span class='line'><span class="c"># servers for testing compiled catalogs.</span>
</span><span class='line'><span class="k">for </span>master in <span class="nv">$puppet_masters</span>; <span class="k">do</span>
</span><span class='line'>   <span class="c"># First we sync facts as they are needed for catalog compilation testing</span>
</span><span class='line'>   ssh <span class="k">${</span><span class="nv">master</span><span class="k">}</span> <span class="s2">&quot;sudo mkdir /tmp/puppetyaml-$USER 2&gt;/dev/null; sudo rsync -r /var/lib/puppet/yaml/ /tmp/puppetyaml-$USER/; sudo chmod -R 755 /tmp/puppetyaml-$USER&quot;</span>
</span><span class='line'>   sudo -E rsync -r <span class="k">${</span><span class="nv">USER</span><span class="k">}</span>@<span class="k">${</span><span class="nv">master</span><span class="k">}</span>:/tmp/puppetyaml-<span class="nv">$USER</span>/ /var/lib/puppet-test-<span class="nv">$USER</span>/yaml/
</span><span class='line'>   ssh <span class="k">${</span><span class="nv">master</span><span class="k">}</span> <span class="s2">&quot;sudo rm -rf /tmp/puppetyaml-$USER/*&quot;</span>
</span><span class='line'>
</span><span class='line'>   <span class="k">for </span>class in <span class="nv">$classes</span>; <span class="k">do</span>
</span><span class='line'>      <span class="c"># Get host id of a node that includes $class</span>
</span><span class='line'>      <span class="nv">host_id</span><span class="o">=</span><span class="k">$(</span><span class="se">\</span>
</span><span class='line'>               ssh <span class="nv">$master</span> <span class="s2">&quot;\</span>
</span><span class='line'><span class="s2">               sudo mysql -s \</span>
</span><span class='line'><span class="s2">                     -D puppet \</span>
</span><span class='line'><span class="s2">                     -h $master \</span>
</span><span class='line'><span class="s2">                     -e \&quot;select host_id from resources \</span>
</span><span class='line'><span class="s2">                        where title = &#39;$class&#39; \</span>
</span><span class='line'><span class="s2">                        and restype = &#39;class&#39;;\&quot; \</span>
</span><span class='line'><span class="s2">               | cat \</span>
</span><span class='line'><span class="s2">               | head -1 \</span>
</span><span class='line'><span class="s2">               &quot;</span><span class="k">)</span>
</span><span class='line'>
</span><span class='line'>      <span class="c"># Continue with next class if the host_id isn&#39;t valid (such as empty)</span>
</span><span class='line'>      <span class="k">if</span> <span class="o">[[</span> <span class="nv">$host_id</span> <span class="o">=</span>~ <span class="o">[[</span>:digit:<span class="o">]]</span>+ <span class="o">]]</span>; <span class="k">then</span>
</span><span class='line'>         :
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'><span class="k">         continue</span>
</span><span class='line'><span class="k">      fi</span>
</span><span class='line'>
</span><span class='line'>      <span class="c"># Get host_name from host_id</span>
</span><span class='line'>      <span class="nv">host_name</span><span class="o">=</span><span class="k">$(</span><span class="se">\</span>
</span><span class='line'>                  ssh <span class="nv">$master</span> <span class="s2">&quot;\</span>
</span><span class='line'><span class="s2">                  sudo mysql -s \</span>
</span><span class='line'><span class="s2">                        -D puppet \</span>
</span><span class='line'><span class="s2">                        -e \&quot;select name from hosts where id = &#39;$host_id&#39;;\&quot; \</span>
</span><span class='line'><span class="s2">                  | cat \</span>
</span><span class='line'><span class="s2">                 &quot;</span><span class="k">)</span>
</span><span class='line'>
</span><span class='line'>      <span class="c"># If the server is already in the list to compile, don&#39;t add.</span>
</span><span class='line'>      <span class="k">if </span><span class="nb">echo</span> <span class="nv">$servers</span> | grep -q <span class="nv">$host_name</span>; <span class="k">then</span>
</span><span class='line'><span class="k">         continue</span>
</span><span class='line'><span class="k">      fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">      </span><span class="nv">servers</span><span class="o">=</span><span class="s2">&quot;$servers $host_name&quot;</span>
</span><span class='line'>   <span class="k">done</span>
</span><span class='line'><span class="k">done</span>
</span><span class='line'>
</span><span class='line'>sudo parallel -P 4 <span class="se">\</span>
</span><span class='line'>   <span class="s2">&quot;puppet master \</span>
</span><span class='line'><span class="s2">   --config_version=&#39;cd $HOME/working/git/puppet; git rev-parse HEAD&#39; \</span>
</span><span class='line'><span class="s2">   --color=false \</span>
</span><span class='line'><span class="s2">   --no-daemonize \</span>
</span><span class='line'><span class="s2">   -l console \</span>
</span><span class='line'><span class="s2">   --confdir=$puppetroot \</span>
</span><span class='line'><span class="s2">   --manifest=$puppetroot/$environment/manifests/site.pp \</span>
</span><span class='line'><span class="s2">   --modulepath=$puppetroot/$environment/grumps-modules:$puppetroot/$environment/yoursite-modules \</span>
</span><span class='line'><span class="s2">   --ssldir=/var/lib/puppet-test-$USER/ssl \</span>
</span><span class='line'><span class="s2">   --vardir=/var/lib/puppet-test-$USER \</span>
</span><span class='line'><span class="s2">   --compile {} \</span>
</span><span class='line'><span class="s2">   | egrep \&quot;^(err|notice|warning|Fail)\&quot;&quot;</span> <span class="se">\</span>
</span><span class='line'>   ::: <span class="nv">$servers</span> <span class="se">\</span>
</span><span class='line'>| tee <span class="nv">$compile_failure_log</span>
</span><span class='line'>
</span><span class='line'><span class="k">if </span>egrep -q <span class="s1">&#39;^(err|Fail)&#39;</span> <span class="s2">&quot;$compile_failure_log&quot;</span>; <span class="k">then</span>
</span><span class='line'><span class="k">    </span><span class="nb">printf</span> <span class="s1">&#39;Compilation errors, please fix.\n&#39;</span> &gt;&amp;2
</span><span class='line'>    rm -f <span class="s2">&quot;$compile_failure_log&quot;</span>
</span><span class='line'>    <span class="nb">exit</span> -1
</span><span class='line'><span class="k">else</span>
</span><span class='line'><span class="k">    </span><span class="nb">printf</span> <span class="s2">&quot;Changed catalogs compiled successfully.\n&quot;</span>
</span><span class='line'>    rm -f <span class="s2">&quot;$compile_failure_log&quot;</span>
</span><span class='line'>    <span class="nb">exit </span>0
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="c">#vim: set expandtab ts=3 sw=3:</span>
</span></code></pre></td></tr></table></div></figure>


<p>If you end up using Git submodules like I have outlined in my previous post,
you will need the uberdiff.rb script:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1">#!/usr/bin/env ruby</span>
</span><span class='line'><span class="c1"># This is a script that takes a revision or revision range from a super-</span>
</span><span class='line'><span class="c1"># project, and spits out all the files under submodules that have changed.</span>
</span><span class='line'><span class="c1"># Note that this will not output removed files.</span>
</span><span class='line'>
</span><span class='line'><span class="n">rev</span> <span class="o">=</span> <span class="no">ARGV</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span>
</span><span class='line'><span class="n">submodules</span> <span class="o">=</span> <span class="o">[</span> <span class="o">]</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="no">Dir</span><span class="o">.</span><span class="n">pwd</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">)</span><span class="o">[-</span><span class="mi">1</span><span class="o">]</span> <span class="o">!=</span> <span class="s2">&quot;puppet&quot;</span>
</span><span class='line'>   <span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="s2">&quot;You must run this script from the root of the super-project.&quot;</span>
</span><span class='line'>   <span class="nb">exit</span> <span class="o">-</span><span class="mi">1</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="sb">`git diff </span><span class="si">#{</span><span class="n">rev</span><span class="si">}</span><span class="sb"> --submodule=&#39;log&#39; | egrep &#39;^Submodule (staging|production)&#39;`</span><span class="o">.</span><span class="n">each_line</span> <span class="k">do</span> <span class="o">|</span><span class="n">submodule</span><span class="o">|</span>
</span><span class='line'>   <span class="k">if</span> <span class="n">submodule</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot; &quot;</span><span class="p">)</span><span class="o">[</span><span class="mi">2</span><span class="o">].</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/:$/</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="s2">&quot;contains&quot;</span>
</span><span class='line'>      <span class="k">next</span>
</span><span class='line'>   <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">submodules</span> <span class="o">&lt;&lt;</span> <span class="p">{</span>
</span><span class='line'>      <span class="ss">:modulename</span> <span class="o">=&gt;</span> <span class="n">submodule</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot; &quot;</span><span class="p">)</span><span class="o">[</span><span class="mi">1</span><span class="o">]</span><span class="p">,</span>
</span><span class='line'>      <span class="ss">:revrange</span>   <span class="o">=&gt;</span> <span class="n">submodule</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot; &quot;</span><span class="p">)</span><span class="o">[</span><span class="mi">2</span><span class="o">].</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/:$/</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">),</span>
</span><span class='line'>      <span class="ss">:changes</span>    <span class="o">=&gt;</span> <span class="o">[</span> <span class="o">]</span>
</span><span class='line'>   <span class="p">}</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">submodules</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">submodule</span><span class="o">|</span>
</span><span class='line'>   <span class="n">submodule</span><span class="o">[</span><span class="ss">:changes</span><span class="o">]</span> <span class="o">=</span> <span class="sb">`git submodule --quiet foreach &#39;if [ $path == &quot;</span><span class="si">#{</span><span class="n">submodule</span><span class="o">[</span><span class="ss">:modulename</span><span class="o">]</span><span class="si">}</span><span class="sb">&quot; ]; then git diff --diff-filter=ACM --name-only </span><span class="si">#{</span><span class="n">submodule</span><span class="o">[</span><span class="ss">:revrange</span><span class="o">]</span><span class="si">}</span><span class="sb">; fi&#39;`</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
</span><span class='line'>   <span class="n">submodule</span><span class="o">[</span><span class="ss">:changes</span><span class="o">].</span><span class="n">map!</span> <span class="p">{</span> <span class="o">|</span><span class="n">change</span><span class="o">|</span> <span class="n">submodule</span><span class="o">[</span><span class="ss">:modulename</span><span class="o">]</span> <span class="o">+</span> <span class="no">File</span><span class="o">::</span><span class="no">SEPARATOR</span> <span class="o">+</span> <span class="n">change</span> <span class="p">}</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">submodules</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">submodule</span><span class="o">|</span>
</span><span class='line'>   <span class="nb">puts</span> <span class="n">submodule</span><span class="o">[</span><span class="ss">:changes</span><span class="o">]</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="c1">#vim: set expandtab ts=3 sw=3:</span>
</span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[A simple Puppet function to retrieve information from the Stored Config DB]]></title>
    <link href="http://blog.thesilentpenguin.com/blog/2012/02/22/a-simple-puppet-function-to-retrieve-information-from-the-stored-config-db/"/>
    <updated>2012-02-22T00:12:00-05:00</updated>
    <id>http://blog.thesilentpenguin.com/blog/2012/02/22/a-simple-puppet-function-to-retrieve-information-from-the-stored-config-db</id>
    <content type="html"><![CDATA[<p>Often, in Puppet manifests you will find you need some arbitrary information
about machines in your infrastructure. The stored configuration database, for
all its blemishes, can be an easy way to achieve this.</p>

<!-- more -->


<p>Here is the function I wrote to do this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s1">&#39;puppet/rails&#39;</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;puppet/rails/fact_value&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="k">module</span> <span class="nn">Puppet::Parser::Functions</span>
</span><span class='line'>  <span class="n">newfunction</span><span class="p">(</span><span class="ss">:getinfo</span><span class="p">,</span>
</span><span class='line'>  <span class="ss">:type</span> <span class="o">=&gt;</span> <span class="ss">:rvalue</span><span class="p">,</span>
</span><span class='line'>  <span class="ss">:doc</span> <span class="o">=&gt;</span> <span class="s2">&quot;This is a function that will return an array of information based</span>
</span><span class='line'><span class="s2">  on what you ask for. For example this call:</span>
</span><span class='line'><span class="s2">  </span>
</span><span class='line'><span class="s2">    getinfo(&#39;Class&#39;, &#39;httpd&#39;, &#39;ec2_public_ipv4&#39;)</span>
</span><span class='line'><span class="s2">  </span>
</span><span class='line'><span class="s2">  will return a list of the ec2_public_ipv4 fact values for any node that has</span>
</span><span class='line'><span class="s2">  the resource Class[&#39;httpd&#39;]. If you leave off the third argument, fqdn will be</span>
</span><span class='line'><span class="s2">  assumed. Also note you can pass an environment to this function, but likely</span>
</span><span class='line'><span class="s2">  you won&#39;t need to because by default it will find the node&#39;s environment and</span>
</span><span class='line'><span class="s2">  use that. &quot;</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">args</span><span class="o">|</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">resource_type</span> <span class="o">=</span> <span class="n">args</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span>
</span><span class='line'>    <span class="n">resource_title</span>  <span class="o">=</span> <span class="n">args</span><span class="o">[</span><span class="mi">1</span><span class="o">]</span>
</span><span class='line'>    <span class="n">return_info</span> <span class="o">=</span> <span class="n">args</span><span class="o">[</span><span class="mi">2</span><span class="o">]</span>
</span><span class='line'>    <span class="n">environment</span> <span class="o">=</span> <span class="n">args</span><span class="o">[</span><span class="mi">3</span><span class="o">]</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">return_info</span> <span class="o">||=</span> <span class="s2">&quot;fqdn&quot;</span>
</span><span class='line'>    <span class="n">environment</span> <span class="o">||=</span> <span class="n">lookupvar</span><span class="p">(</span><span class="s2">&quot;::environment&quot;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">raise</span> <span class="no">Puppet</span><span class="o">::</span><span class="no">ParseError</span><span class="p">,</span> <span class="p">(</span><span class="s2">&quot;getinfo(): wrong number of arguments (</span><span class="si">#{</span><span class="n">args</span><span class="o">.</span><span class="n">length</span><span class="si">}</span><span class="s2">; must be &gt;= 2)&quot;</span><span class="p">)</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">length</span> <span class="o">&lt;</span> <span class="mi">2</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">info</span> <span class="o">=</span> <span class="o">[</span> <span class="o">]</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">info</span> <span class="o">=</span> <span class="no">Puppet</span><span class="o">::</span><span class="no">Rails</span><span class="o">::</span><span class="no">FactValue</span><span class="o">.</span><span class="n">find_by_sql</span><span class="p">(</span><span class="s2">&quot;</span>
</span><span class='line'><span class="s2">             SELECT fv.value from fact_values fv, fact_names fn, resources r, hosts h</span>
</span><span class='line'><span class="s2">             WHERE fn.name = &#39;</span><span class="si">#{</span><span class="n">return_info</span><span class="si">}</span><span class="s2">&#39;</span>
</span><span class='line'><span class="s2">               AND h.environment = &#39;</span><span class="si">#{</span><span class="n">environment</span><span class="si">}</span><span class="s2">&#39;</span>
</span><span class='line'><span class="s2">               AND h.id = r.host_id</span>
</span><span class='line'><span class="s2">               AND r.restype = &#39;</span><span class="si">#{</span><span class="n">resource_type</span><span class="si">}</span><span class="s2">&#39;</span>
</span><span class='line'><span class="s2">               AND r.title = &#39;</span><span class="si">#{</span><span class="n">resource_title</span><span class="si">}</span><span class="s2">&#39;</span>
</span><span class='line'><span class="s2">               AND fv.host_id = h.id</span>
</span><span class='line'><span class="s2">               AND fv.fact_name_id = fn.id;</span>
</span><span class='line'><span class="s2">           &quot;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">info</span><span class="o">.</span><span class="n">map!</span> <span class="p">{</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span> <span class="n">i</span><span class="o">.</span><span class="n">value</span> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">info</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Put this in a module and you can start using it in manifests:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>   <span class="k">class</span> <span class="p">{</span>
</span><span class='line'>      <span class="s2">&quot;firewall::iptables&quot;</span><span class="p">:</span>
</span><span class='line'>         <span class="k">ensure</span>                              <span class="o">=&gt;</span> <span class="vg">$ensure</span><span class="p">,</span>
</span><span class='line'>         <span class="n">nodenets</span>                            <span class="o">=&gt;</span> <span class="n">getinfo</span><span class="p">(</span><span class="s1">&#39;Class&#39;</span><span class="p">,</span> <span class="s1">&#39;httpd&#39;</span><span class="p">,</span> <span class="s1">&#39;ec2_public_ipv4&#39;</span><span class="p">),</span>
</span><span class='line'>         <span class="n">open_tcp_ports</span>                      <span class="o">=&gt;</span> <span class="s2">&quot;22&quot;</span><span class="p">,</span>
</span><span class='line'>         <span class="n">restricted_to_node_nets_tcp_ports</span>   <span class="o">=&gt;</span> <span class="s2">&quot;5432&quot;</span><span class="p">;</span>
</span><span class='line'>   <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>This will make the nodenets parameter to be an array of ec2 public IPs from
any nodes that have the httpd class.</p>

<p>Here is an example of using it in an Apache load balancer config:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='erb'><span class='line'><span class="x">   &lt;Location ~ &quot;^/(SYSTEM|system)&quot;&gt;</span>
</span><span class='line'><span class="x">      Order allow,deny</span>
</span><span class='line'><span class="x">      Allow from 127.0.0.1</span>
</span><span class='line'><span class="cp">&lt;%</span> <span class="n">scope</span><span class="o">.</span><span class="n">function_getinfo</span><span class="p">(</span><span class="s1">&#39;Class&#39;</span><span class="p">,</span> <span class="s1">&#39;moodle&#39;</span><span class="p">,</span> <span class="s1">&#39;ipaddress&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">ip</span><span class="o">|</span> <span class="cp">-%&gt;</span><span class="x"></span>
</span><span class='line'><span class="x">      Allow from </span><span class="cp">&lt;%=</span> <span class="n">ip</span> <span class="cp">%&gt;</span><span class="x"></span>
</span><span class='line'><span class="cp">&lt;%</span> <span class="k">end</span> <span class="cp">-%&gt;</span><span class="x"></span>
</span><span class='line'><span class="x">      Satisfy Any</span>
</span><span class='line'><span class="x">   &lt;/Location&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>The third parameter makes it so you can get any arbitrary information. You
could for instance compile more complex configuration files that use hostname
and something like architecture. This would take two calls to getinfo(), but
I think you get the picture. Eventually I think I&#8217;d like to take an array of
resources and write a query builder method to keep the amount of SQL queries
to a minimum. For now this is working fine for me to solve some real problems.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Puppet with Git Submodules for Fun and Profit]]></title>
    <link href="http://blog.thesilentpenguin.com/blog/2012/02/21/puppet-with-git-submodules-for-fun-and-profit/"/>
    <updated>2012-02-21T22:05:00-05:00</updated>
    <id>http://blog.thesilentpenguin.com/blog/2012/02/21/puppet-with-git-submodules-for-fun-and-profit</id>
    <content type="html"><![CDATA[<p>Git submodules are somewhat of an &#8216;advanced&#8217; git feature, akin to Subversion
externals for those of us unlucky enough to have the pleasure of knowing svn.
The most common usage is pulling in third party libraries to your project. You
can think of git submodules as git checkouts within checkouts. The &#8216;parent&#8217;
checkout or &#8216;super-project&#8217; as I call it, knows that there are submodules, and
knows which SHA each submodule is at. Since most of my work as both a Systems
Engineer at $dayjob and a general IT consultant part-time, I needed to use
submodules slightly differently than the most common use-case.</p>

<p>During some time off during 2011 from having a dayjob, I developed a lot of
Puppet code that used what was at the time new features like Parameterized
classes, hashes, etc. I also pretty painstakingly made sure the code would
work on OpenBSD, Debian, Ubuntu, Red Hat, and CentOS. The plan was to keep
this code private and charge people for the service of supporting this set of
modules and develop new ones etc. So, I needed a way to let people pull this
code into their Puppet repo and use it. Submodules are the only easy way to do
this. This code, along with some scripts to set up an environment utilizing
this code was what I called the GRand Unified Modular Puppet System (GRUMPS).</p>

<!-- more -->


<p>First, not to go too far off track, but if you are pulling puppet modules
on the net, you should already be aware of git submodules. If you are down
loading modules then just copying them into your setup you&#8217;re doing it wrong.
Puppet code <em>is</em> code. You need to treat improvements to public modules the
same way you treat any open-source project. You have your own local branch,
submit fixes to upstream etc.</p>

<p>Now let&#8217;s talk about Puppet environments. You should at the very least have
two environments. The name of the one that isn&#8217;t production probably doesn&#8217;t
matter much, but we&#8217;ll call this staging, since that&#8217;s what I use in the code
snippets later on. Many people will make these git checkouts under /etc/puppet
that they run git pull on to update. This is an atrocious update mechanism, and
a poor development layout.</p>

<p>Instead, what I&#8217;ve done is to make each sub-directory of each Puppet env correspond
to specific branches in various sub-modules. Example:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>Module Layout
</span><span class='line'>
</span><span class='line'>                          _ grumps-modules => git@github.com://thesilentpenguin/grumps-modules  | master
</span><span class='line'>                         /  dayjob-modules => git@github.com://dayjob/dayjob-modules            | master
</span><span class='line'>/etc/puppet/production ->   manifests      => ssh://git.yoursite.com/dayjob-manifests           | master
</span><span class='line'>                         \_ extdata        => ssh://git.yoursite.com/dayjob-extdata             | master
</span><span class='line'>
</span><span class='line'>                          _ grumps-modules => git@github.com://thesilentpenguin/grumps-modules  | develop
</span><span class='line'>                         /  dayjob-modules => git@github.com://dayjob/dayjob-modules            | develop
</span><span class='line'>/etc/puppet/staging    ->   manifests      => ssh://git.yoursite.com/dayjob-manifests           | develop
</span><span class='line'>                         \_ extdata        => ssh://git.yoursite.com/dayjob-extdata             | develop</span></code></pre></td></tr></table></div></figure>


<p>&#8220;Develop&#8221; was a pre-existing convention I had for branch naming, but that&#8217;s
really irrelevant, make it what you want. Now this shows I have 8 submodules
for my two environments. I actually have one more for the SSL dir, but that
is off-topic really. Some of the code samples may reference develop or master.</p>

<p>To get all this setup you will need to run git submodule add from the root of
your checkout for each submodule, and you will also need to run git submodule
init, which adds the added submodules to the .gitmodules file. Totally not
confusing :-).</p>

<p>The 1000-foot view of the workflow after setup is complete:</p>

<ol>
<li>Team members committing like it&#8217;s April 29 1992 on develop</li>
<li>Everybody&#8217;s seeing each other&#8217;s work, reviews it</li>
<li>Merge every sub-module&#8217;s develop branch to merge</li>
<li>Update super-project</li>
<li>Push and Deploy</li>
</ol>


<p>Another, more common workflow for me is:</p>

<ol>
<li>Committing like fire on develop</li>
<li>Reviewing work</li>
<li>Some guy runs up to your desk and needs XXX fixed in production</li>
<li>O NO! you have about 20 commits that can&#8217;t go to prod</li>
<li>Relax, we use modern version control, Cherry pick change(s)</li>
<li>Update super-project</li>
<li>Push and Deploy</li>
</ol>


<p>You&#8217;re thinking &#8220;this is just a bunch of overhead&#8221;. Well yea if I didn&#8217;t
script all this monotony away from me I would say the same thing. But one
thing I&#8217;ve learned from heavy git sub-module usage, is that if you don&#8217;t
script all these things, you will forget a step and break something. You&#8217;re
also constantly repeating yourself, since you always require N+1 changes for
N changes (you must update the git super-project, which updates the SHA&#8217;s
found in .gitmodules).</p>

<p>So, here is the script for committing a single change, which may be across
several submodules. Please note that I have had to on one system change the
git-submodule script that comes with git to use bash in the shebang. This is
because I use shell regex in the foreach commands, often:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c">#!/usr/bin/env bash</span>
</span><span class='line'><span class="c"># This is a silly QnD that lets you develop in the staging sub modules, then</span>
</span><span class='line'><span class="c"># run this to go into each one to commit and push. Saves you some keystrokes.</span>
</span><span class='line'><span class="c"># Force needs to be used sometimes to really push things. What force does is</span>
</span><span class='line'><span class="c"># just change the command chain to use ; instead of &amp;&amp;.</span>
</span><span class='line'>
</span><span class='line'><span class="nb">export </span><span class="nv">COMMIT_MESSAGE</span><span class="o">=</span><span class="s2">&quot;$1&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -z <span class="s2">&quot;$COMMIT_MESSAGE&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span><span class="nb">printf</span> <span class="s2">&quot;You must enter a commit message as the only argument to this script!\n&quot;</span> &gt;&amp;2
</span><span class='line'>   <span class="nb">exit</span> -1
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$2&quot;</span> <span class="o">==</span> <span class="s2">&quot;force&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span><span class="nb">printf</span> <span class="s2">&quot;Forcing the operation...\n&quot;</span>
</span><span class='line'>   git submodule foreach <span class="s1">&#39;if [[ $path =~ ^staging.* ]]; then git checkout develop; git add .; git commit -am &quot;$COMMIT_MESSAGE&quot;; git push -u origin develop; fi&#39;</span>
</span><span class='line'><span class="k">else</span>
</span><span class='line'><span class="k">   </span>git submodule foreach <span class="s1">&#39;if [[ $path =~ ^staging.* ]]; then git checkout develop &amp;&amp; git add . &amp;&amp; git commit -am &quot;$COMMIT_MESSAGE&quot; &amp;&amp; git push -u origin develop; fi&#39;</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'>git commit -am <span class="s2">&quot;Updated submodules: $COMMIT_MESSAGE&quot;</span>
</span><span class='line'>git push
</span><span class='line'>
</span><span class='line'><span class="c">#vim: set expandtab ts=3 sw=3:</span>
</span></code></pre></td></tr></table></div></figure>


<p>So, this needs to be run from the root of the checkout. My convention for all
code checkouts is $HOME/working/$vcs/$project, so I do:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>[~/working/git/puppet]> vim staging/grumps-modules/common/manifests/debuntu.pp
</span><span class='line'>[~/working/git/puppet]> vim staging/manifests/node_templates.pp
</span><span class='line'>[~/working/git/puppet]> scripts/stagcom.sh "Wrote debuntu class for Debian and Ubuntu machines, made sure basenode includes it"
</span><span class='line'>[~/working/git/puppet]> cap deploy</span></code></pre></td></tr></table></div></figure>


<p>This is all I need to do to get commits in staging out to the master. The
snippet which shows the capistrano stuff I will show last. Promotion is as
easy as:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>[~/working/git/puppet]> scripts/promote.sh
</span><span class='line'>[~/working/git/puppet]> cap deploy</span></code></pre></td></tr></table></div></figure>


<p>Or to promote a single commit:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>[~/working/git/puppet]> scripts/promote.sh -c 73acef8 -m grumps-modules
</span><span class='line'>[~/working/git/puppet]> cap deploy</span></code></pre></td></tr></table></div></figure>


<p>Now let&#8217;s talk about promotion of changes. This is somewhat dependent on your
CR process (if you have one), but here is the script I use for full-env pro
motion as well as cherry-pick promotions:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
<span class='line-number'>106</span>
<span class='line-number'>107</span>
<span class='line-number'>108</span>
<span class='line-number'>109</span>
<span class='line-number'>110</span>
<span class='line-number'>111</span>
<span class='line-number'>112</span>
<span class='line-number'>113</span>
<span class='line-number'>114</span>
<span class='line-number'>115</span>
<span class='line-number'>116</span>
<span class='line-number'>117</span>
<span class='line-number'>118</span>
<span class='line-number'>119</span>
<span class='line-number'>120</span>
<span class='line-number'>121</span>
<span class='line-number'>122</span>
<span class='line-number'>123</span>
<span class='line-number'>124</span>
<span class='line-number'>125</span>
<span class='line-number'>126</span>
<span class='line-number'>127</span>
<span class='line-number'>128</span>
<span class='line-number'>129</span>
<span class='line-number'>130</span>
<span class='line-number'>131</span>
<span class='line-number'>132</span>
<span class='line-number'>133</span>
<span class='line-number'>134</span>
<span class='line-number'>135</span>
<span class='line-number'>136</span>
<span class='line-number'>137</span>
<span class='line-number'>138</span>
<span class='line-number'>139</span>
<span class='line-number'>140</span>
<span class='line-number'>141</span>
<span class='line-number'>142</span>
<span class='line-number'>143</span>
<span class='line-number'>144</span>
<span class='line-number'>145</span>
<span class='line-number'>146</span>
<span class='line-number'>147</span>
<span class='line-number'>148</span>
<span class='line-number'>149</span>
<span class='line-number'>150</span>
<span class='line-number'>151</span>
<span class='line-number'>152</span>
<span class='line-number'>153</span>
<span class='line-number'>154</span>
<span class='line-number'>155</span>
<span class='line-number'>156</span>
<span class='line-number'>157</span>
<span class='line-number'>158</span>
<span class='line-number'>159</span>
<span class='line-number'>160</span>
<span class='line-number'>161</span>
<span class='line-number'>162</span>
<span class='line-number'>163</span>
<span class='line-number'>164</span>
<span class='line-number'>165</span>
<span class='line-number'>166</span>
<span class='line-number'>167</span>
<span class='line-number'>168</span>
<span class='line-number'>169</span>
<span class='line-number'>170</span>
<span class='line-number'>171</span>
<span class='line-number'>172</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c">#!/usr/bin/env bash</span>
</span><span class='line'><span class="c"># == Synopsis</span>
</span><span class='line'><span class="c"># This is a small script that will promote the develop branches in each git</span>
</span><span class='line'><span class="c"># submodule in the Puppet staging environment to master, then then pull in</span>
</span><span class='line'><span class="c"># the changes to the production environment. Note that you can promote single</span>
</span><span class='line'><span class="c"># commits by using the cherry-pick (-c) functionality. If you use cherry pick</span>
</span><span class='line'><span class="c"># you must pass a modulename, ie &#39;grumps-modules&#39; or &#39;manifests&#39;, with the -m</span>
</span><span class='line'><span class="c"># switch</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># == Usage</span>
</span><span class='line'><span class="c"># See usage() function below</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># == Notes</span>
</span><span class='line'><span class="c"># This script does serious changes and pushes to master. Don&#39;t run it all</span>
</span><span class='line'><span class="c"># willy nilly.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># == Authors</span>
</span><span class='line'><span class="c"># Joe McDonagh &lt;jmcdonagh@thesilentpenguin.com&gt;</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># == Copyright</span>
</span><span class='line'><span class="c"># 2012 The Silent Penguin LLC</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># == License</span>
</span><span class='line'><span class="c"># Licensed under The Silent Penguin Proprietary License</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'>
</span><span class='line'><span class="nv">puppetroot</span><span class="o">=</span><span class="s2">&quot;$HOME/working/git/puppet&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Useful helper function, shorthand for cat&#39;ing files that have error output</span>
</span><span class='line'><span class="k">function </span>caterror<span class="o">()</span> <span class="o">{</span>
</span><span class='line'>   cat <span class="s2">&quot;$1&quot;</span> &gt;&amp;2
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Like caterror, shorthand for sending strings to stderr</span>
</span><span class='line'><span class="k">function </span>perror<span class="o">()</span> <span class="o">{</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;%s\n&quot;</span> <span class="s2">&quot;$1&quot;</span> &gt;&amp;2
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Print a fatal error and exit with exit code $2</span>
</span><span class='line'><span class="k">function </span>die<span class="o">()</span> <span class="o">{</span>
</span><span class='line'>   perror <span class="s2">&quot;$1&quot;</span>
</span><span class='line'>   <span class="nb">exit</span> <span class="nv">$2</span>
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="c"># This will go through all submodules and run the appropriate git log command</span>
</span><span class='line'><span class="c"># to show what commits master needs to be on track with develop.</span>
</span><span class='line'><span class="k">function </span>list_pending_commits<span class="o">()</span> <span class="o">{</span>
</span><span class='line'>   <span class="nb">pushd</span> <span class="nv">$puppetroot</span> &gt;/dev/null 2&gt;&amp;1
</span><span class='line'>   git submodule --quiet foreach <span class="s1">&#39;if [[ $path =~ ^production.* ]]; then printf &quot;%s:\n&quot; &quot;$(basename $name)&quot;; changes=$(git log master..develop); if [ -z &quot;$changes&quot; ]; then printf &quot;No pending commits.\n&quot;; else printf &quot;%s\n&quot; &quot;$changes&quot;; fi; fi&#39;</span>
</span><span class='line'>   <span class="nb">popd</span> <span class="nv">$puppetroot</span> &gt;/dev/null 2&gt;&amp;1
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Use this function to print out usage information, and exit with code of $2.</span>
</span><span class='line'><span class="c"># This is useful to exit with a non-zero code due to an error in argument</span>
</span><span class='line'><span class="c"># processing.</span>
</span><span class='line'><span class="k">function </span>usage<span class="o">()</span> <span class="o">{</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;Usage:\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   %s  [-c commit -m modulename] [-h]\n&quot;</span> <span class="s2">&quot;$(basename $0)&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   -l  List all commits that master needs in all submodules. Make sure\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;       your checkout is up to date if you run this, otherwise results may\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;       be inaccurate.\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   -c  Cherry pick the commit given as the argument to this switch\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   -f  Force mode- this will bypass the prompt when promoting all of staging\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   -h  Print this message\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   -m  This is required if you use -c; it is the submodule directory name\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   -M  This overrides the default commit message with whatever you specify\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;Example:\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;   %s -c d4cb267 -m manifests\n\n&quot;</span> <span class="s2">&quot;$(basename $0)&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;This will cherry-pick commit d4cb267 from the manifests submodule.\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;Passing no arguments to this script will promote the entire staging env to\n&quot;</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;production.\n&quot;</span>
</span><span class='line'>
</span><span class='line'>   <span class="nb">exit</span> <span class="nv">$1</span>
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">while </span><span class="nb">getopts </span>c:lfm:M:h option; <span class="k">do</span>
</span><span class='line'><span class="k">   case</span> <span class="s2">&quot;$option&quot;</span> in
</span><span class='line'>      c<span class="o">)</span>
</span><span class='line'>         <span class="nb">export </span><span class="nv">COMMIT</span><span class="o">=</span><span class="s2">&quot;$OPTARG&quot;</span>
</span><span class='line'>      ;;
</span><span class='line'>      f<span class="o">)</span>
</span><span class='line'>         <span class="nv">force</span><span class="o">=</span><span class="s2">&quot;true&quot;</span>
</span><span class='line'>      ;;
</span><span class='line'>      h<span class="o">)</span>
</span><span class='line'>         usage 0
</span><span class='line'>      ;;
</span><span class='line'>      l<span class="o">)</span>
</span><span class='line'>         list_pending_commits
</span><span class='line'>         <span class="nb">exit </span>0
</span><span class='line'>      ;;
</span><span class='line'>      m<span class="o">)</span>
</span><span class='line'>         <span class="nb">export </span><span class="nv">MODULE</span><span class="o">=</span><span class="s2">&quot;$OPTARG&quot;</span>
</span><span class='line'>      ;;
</span><span class='line'>      M<span class="o">)</span>
</span><span class='line'>         <span class="nb">export </span><span class="nv">MESSAGE</span><span class="o">=</span><span class="s2">&quot;$OPTARG&quot;</span>
</span><span class='line'>      ;;
</span><span class='line'>      *<span class="o">)</span>
</span><span class='line'>         perror <span class="s2">&quot;Passing bad arguments&quot;</span>
</span><span class='line'>         usage -1
</span><span class='line'>   <span class="k">esac</span>
</span><span class='line'><span class="k">done</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -n <span class="s2">&quot;$MODULE&quot;</span> -a -z <span class="s2">&quot;$COMMIT&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span>perror <span class="s2">&quot;You passed -m but did not pass -c, you need both.&quot;</span>
</span><span class='line'>   usage -10
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -z <span class="s2">&quot;$MODULE&quot;</span> -a -n <span class="s2">&quot;$COMMIT&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span>perror <span class="s2">&quot;You passed -c but did not pass -m, you need both.&quot;</span>
</span><span class='line'>   usage -20
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> ! -e <span class="s2">&quot;production/$MODULE&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span>die <span class="s2">&quot;The module $MODULE does not exist!&quot;</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Verify whether or not commit given actually exists in develop branch</span>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -n <span class="s2">&quot;$COMMIT&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span><span class="nb">pushd </span>staging/<span class="nv">$MODULE</span> &gt;/dev/null 2&gt;&amp;1
</span><span class='line'>
</span><span class='line'>   <span class="k">if </span>git branch --contains <span class="s2">&quot;$COMMIT&quot;</span> 2&gt;/dev/null | grep -q develop; <span class="k">then</span>
</span><span class='line'><span class="k">      </span><span class="nv">commit_exists</span><span class="o">=</span><span class="s2">&quot;true&quot;</span>
</span><span class='line'>   <span class="k">else</span>
</span><span class='line'><span class="k">      </span><span class="nv">commit_exists</span><span class="o">=</span><span class="s2">&quot;false&quot;</span>
</span><span class='line'>   <span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">   </span><span class="nb">popd</span> &gt;/dev/null 2&gt;&amp;1
</span><span class='line'>
</span><span class='line'>   <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$commit_exists&quot;</span> <span class="o">==</span> <span class="s2">&quot;false&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">      </span>die <span class="s2">&quot;It appears commit $COMMIT does not exist in the develop branch of module $MODULE!&quot;</span>
</span><span class='line'>   <span class="k">fi</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Force mode in case the script is being used in a batch fashion.</span>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$force&quot;</span> !<span class="o">=</span> <span class="s2">&quot;true&quot;</span> -a -z <span class="s2">&quot;$COMMIT&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span><span class="nb">read</span> -p <span class="s2">&quot;Are you sure you want to promote the entire staging environment? (y/N) &quot;</span> answer
</span><span class='line'>
</span><span class='line'>   <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$answer&quot;</span> !<span class="o">=</span> <span class="s2">&quot;y&quot;</span> -a <span class="s2">&quot;$answer&quot;</span> !<span class="o">=</span> <span class="s2">&quot;Y&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">      </span>die <span class="s2">&quot;Did not confirm full promotion, exiting.&quot;</span> -5
</span><span class='line'>   <span class="k">fi</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Set commit message, dependent on whether message is passed and if cherry</span>
</span><span class='line'><span class="c"># picking or promoting the whole environment.</span>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -z <span class="s2">&quot;$MESSAGE&quot;</span> -a -n <span class="s2">&quot;$COMMIT&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span><span class="nv">MESSAGE</span><span class="o">=</span><span class="s2">&quot;Promote commit $COMMIT in submodule $MODULE from staging to production&quot;</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -z <span class="s2">&quot;$MESSAGE&quot;</span> -a -z <span class="s2">&quot;$COMMIT&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span><span class="nv">MESSAGE</span><span class="o">=</span><span class="s2">&quot;Promote all of staging to production.&quot;</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Change dir into puppetroot with pushd so we can keep track of where we were</span>
</span><span class='line'><span class="nb">pushd</span> <span class="nv">$puppetroot</span> &gt;/dev/null 2&gt;&amp;1
</span><span class='line'>
</span><span class='line'><span class="c"># Make sure everything is up to date.</span>
</span><span class='line'>scripts/updatecheckout.sh
</span><span class='line'>
</span><span class='line'><span class="c"># Do the actual merging or cherry-picking into production and push</span>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -z <span class="s2">&quot;$COMMIT&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">   </span>git submodule foreach --quiet <span class="s1">&#39;if [[ $path =~ ^production.* ]]; then git checkout develop &amp;&amp; git pull &amp;&amp; git checkout master &amp;&amp; git merge develop &amp;&amp; git push; fi&#39;</span>
</span><span class='line'><span class="k">else</span>
</span><span class='line'><span class="k">   </span>git submodule foreach --quiet <span class="s1">&#39;if [ &quot;$name&quot; == &quot;production/$MODULE&quot; ]; then git checkout develop &amp;&amp; git pull &amp;&amp; git checkout master &amp;&amp; git cherry-pick $COMMIT &amp;&amp; git push; fi&#39;</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'>git commit -am <span class="s2">&quot;$MESSAGE&quot;</span>
</span><span class='line'>git push
</span><span class='line'>
</span><span class='line'><span class="nb">popd</span> &gt;/dev/null 2&gt;&amp;1
</span><span class='line'><span class="c">#vim: set expandtab ts=3 sw=3:</span>
</span></code></pre></td></tr></table></div></figure>


<p>One major point I want to drive home is that your commits in git should fix
the smallest error or add the smallest feature as possible. This is just a
version control best practice, and makes cherry picking possible. If you&#8217;re doing
giant commits that change a million things, cherry pick promotions aren&#8217;t
going to work for you.</p>

<p>You may have noticed that I call a script named updatecheckout.sh above. This
is the script for updating all the submodules because it&#8217;s a serious PITA to
do <em>anything</em> with sub-modules that isn&#8217;t scripted. That includes just keeping
your checkout up to date and on the proper branches:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c">#!/usr/bin/env bash</span>
</span><span class='line'><span class="c"># == Synopsis</span>
</span><span class='line'><span class="c"># This is a small script that will update your whole checkout.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># == Usage</span>
</span><span class='line'><span class="c"># See usage() function below.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># == Notes</span>
</span><span class='line'><span class="c"># Don&#39;t eat the yellow snow.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># == Authors</span>
</span><span class='line'><span class="c"># Joe McDonagh &lt;jmcdonagh@thesilentpenguin.com&gt;</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># == Copyright</span>
</span><span class='line'><span class="c"># 2012 The Silent Penguin LLC</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># == License</span>
</span><span class='line'><span class="c"># Licensed under The Silent Penguin Proprietary License</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'>
</span><span class='line'><span class="nv">puppetroot</span><span class="o">=</span><span class="s2">&quot;$HOME/working/git/puppet&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Useful helper function, shorthand for cat&#39;ing files that have error output</span>
</span><span class='line'><span class="k">function </span>caterror<span class="o">()</span> <span class="o">{</span>
</span><span class='line'>   cat <span class="s2">&quot;$1&quot;</span> &gt;&amp;2
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Like caterror, shorthand for sending strings to stderr</span>
</span><span class='line'><span class="k">function </span>perror<span class="o">()</span> <span class="o">{</span>
</span><span class='line'>   <span class="nb">printf</span> <span class="s2">&quot;%s\n&quot;</span> <span class="s2">&quot;$1&quot;</span> &gt;&amp;2
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Print a fatal error and exit with exit code $2</span>
</span><span class='line'><span class="k">function </span>die<span class="o">()</span> <span class="o">{</span>
</span><span class='line'>   perror <span class="s2">&quot;$1&quot;</span>
</span><span class='line'>   <span class="nb">exit</span> <span class="nv">$2</span>
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Change dir into puppetroot with pushd so we can keep track of where we were</span>
</span><span class='line'><span class="nb">pushd</span> <span class="nv">$puppetroot</span> &gt;/dev/null 2&gt;&amp;1
</span><span class='line'>
</span><span class='line'><span class="c"># Make sure everything is up to date.</span>
</span><span class='line'>git pull --all
</span><span class='line'>git submodule update --merge
</span><span class='line'>git submodule foreach --quiet <span class="s1">&#39;if [[ $path =~ ^staging.* ]]; then git checkout develop &amp;&amp; git pull; fi&#39;</span>
</span><span class='line'>git submodule foreach --quiet <span class="s1">&#39;if [[ $path =~ ^production.* ]]; then git checkout master &amp;&amp; git pull &amp;&amp; git checkout develop &amp;&amp; git pull &amp;&amp; git checkout master; fi&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="nb">popd</span> &gt;/dev/null 2&gt;&amp;1
</span><span class='line'><span class="c">#vim: set expandtab ts=3 sw=3:</span>
</span></code></pre></td></tr></table></div></figure>


<p>Last but not least, you&#8217;ll need some capistrano action. I use capistrano to
deploy, with the railsless-deploy.rb floating around the net. I have one small
modification to the railsless-deploy.rb which will ensure that the submodules
are on the proper branch in the cached-checkout:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="c1"># Override deploy! to do some submodule branch stuff</span>
</span><span class='line'>  <span class="k">module</span> <span class="nn">Capistrano</span>
</span><span class='line'>    <span class="k">module</span> <span class="nn">Deploy</span>
</span><span class='line'>      <span class="k">module</span> <span class="nn">Strategy</span>
</span><span class='line'>        <span class="k">class</span> <span class="nc">RemoteCache</span> <span class="o">&lt;</span> <span class="no">Remote</span>
</span><span class='line'>          <span class="k">def</span> <span class="nf">deploy!</span>
</span><span class='line'>            <span class="n">update_repository_cache</span>
</span><span class='line'>
</span><span class='line'>            <span class="c1"># This will make sure the proper branches are used in the submodules</span>
</span><span class='line'>            <span class="n">logger</span><span class="o">.</span><span class="n">info</span> <span class="s2">&quot;Ensuring staging sub-modules are using proper develop branches...&quot;</span>
</span><span class='line'>
</span><span class='line'>            <span class="n">devmodules</span> <span class="o">=</span> <span class="n">capture</span><span class="p">(</span><span class="s2">&quot;ls -d </span><span class="si">#{</span><span class="n">shared_path</span><span class="si">}</span><span class="s2">/cached-copy/staging/*&quot;</span><span class="p">)</span>
</span><span class='line'>            <span class="n">devmodules</span> <span class="o">=</span> <span class="n">devmodules</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
</span><span class='line'>            <span class="n">devmodules</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">devmod</span><span class="o">|</span>
</span><span class='line'>              <span class="n">run</span> <span class="s2">&quot;cd  </span><span class="si">#{</span><span class="n">devmod</span><span class="si">}</span><span class="s2">; git checkout develop; git pull; cd -&quot;</span>
</span><span class='line'>            <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>            <span class="n">logger</span><span class="o">.</span><span class="n">info</span> <span class="s2">&quot;Ensuring production sub-modules are using proper master branches...&quot;</span>
</span><span class='line'>
</span><span class='line'>            <span class="n">prodmodules</span> <span class="o">=</span> <span class="n">capture</span><span class="p">(</span><span class="s2">&quot;ls -d </span><span class="si">#{</span><span class="n">shared_path</span><span class="si">}</span><span class="s2">/cached-copy/production/*&quot;</span><span class="p">)</span>
</span><span class='line'>            <span class="n">prodmodules</span> <span class="o">=</span> <span class="n">prodmodules</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
</span><span class='line'>            <span class="n">prodmodules</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">prodmod</span><span class="o">|</span>
</span><span class='line'>              <span class="n">run</span> <span class="s2">&quot;cd </span><span class="si">#{</span><span class="n">prodmod</span><span class="si">}</span><span class="s2">; git checkout master; git pull; cd -&quot;</span>
</span><span class='line'>            <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>            <span class="n">copy_repository_cache</span>
</span><span class='line'>          <span class="k">end</span>
</span><span class='line'>        <span class="k">end</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>This is done for posterity and to avoid confusion. If you are familiar with
git submodules you know they are typically in a detached state. This means
they are not on any branch in particular. The super-project simply knows what
SHA a given submodule is at. That SHA may correspond to the tip of a branch,
but git submodule isn&#8217;t really aware of that. So, the enable submodule var
of Capistrano should be enough, but I like to make sure the cached-checkout is an
exact mirror of what Puppet developers have locally. You also don&#8217;t want to
ever be developing in a detached state cause you want your commits to stay
on the proper branch. In fact you probably get an error when trying to commit in
a detached state. Haven&#8217;t had to deal with those little mistakes since I wrote
this set of scripts. Here is the actual deploy.rb:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
<span class='line-number'>106</span>
<span class='line-number'>107</span>
<span class='line-number'>108</span>
<span class='line-number'>109</span>
<span class='line-number'>110</span>
<span class='line-number'>111</span>
<span class='line-number'>112</span>
<span class='line-number'>113</span>
<span class='line-number'>114</span>
<span class='line-number'>115</span>
<span class='line-number'>116</span>
<span class='line-number'>117</span>
<span class='line-number'>118</span>
<span class='line-number'>119</span>
<span class='line-number'>120</span>
<span class='line-number'>121</span>
<span class='line-number'>122</span>
<span class='line-number'>123</span>
<span class='line-number'>124</span>
<span class='line-number'>125</span>
<span class='line-number'>126</span>
<span class='line-number'>127</span>
<span class='line-number'>128</span>
<span class='line-number'>129</span>
<span class='line-number'>130</span>
<span class='line-number'>131</span>
<span class='line-number'>132</span>
<span class='line-number'>133</span>
<span class='line-number'>134</span>
<span class='line-number'>135</span>
<span class='line-number'>136</span>
<span class='line-number'>137</span>
<span class='line-number'>138</span>
<span class='line-number'>139</span>
<span class='line-number'>140</span>
<span class='line-number'>141</span>
<span class='line-number'>142</span>
<span class='line-number'>143</span>
<span class='line-number'>144</span>
<span class='line-number'>145</span>
<span class='line-number'>146</span>
<span class='line-number'>147</span>
<span class='line-number'>148</span>
<span class='line-number'>149</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1"># Configuration Variables</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:admin_group</span><span class="p">,</span>             <span class="s2">&quot;webops&quot;</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:admin_group_gid</span><span class="p">,</span>         <span class="s2">&quot;1337&quot;</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:app_user</span><span class="p">,</span>                <span class="s2">&quot;puppet&quot;</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:application</span><span class="p">,</span>             <span class="s2">&quot;puppet&quot;</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:copy_exclude</span><span class="p">,</span>            <span class="o">[</span> <span class="s2">&quot;.git&quot;</span> <span class="o">]</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:deploy_lockfile</span><span class="p">,</span>         <span class="s2">&quot;/tmp/puppet_being_deployed&quot;</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:deploy_to</span><span class="p">,</span>               <span class="s2">&quot;/usr/local/puppet&quot;</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:deploy_via</span><span class="p">,</span>              <span class="s2">&quot;remote_cache&quot;</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:git_enable_submodules</span><span class="p">,</span>   <span class="mi">1</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:keep_releases</span><span class="p">,</span>           <span class="mi">5</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:local_checkout</span><span class="p">,</span>          <span class="s2">&quot;</span><span class="si">#{</span><span class="no">ENV</span><span class="o">[</span><span class="s1">&#39;HOME&#39;</span><span class="o">]</span><span class="si">}</span><span class="s2">/working/git/puppet&quot;</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:notification_email</span><span class="p">,</span>      <span class="s2">&quot;webops@yourorg.com&quot;</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:repository</span><span class="p">,</span>              <span class="s2">&quot;ssh://git@github.com/yourorg/puppet&quot;</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:scm</span><span class="p">,</span>                     <span class="s2">&quot;git&quot;</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:storeconfig_password</span><span class="p">,</span>    <span class="s2">&quot;oFzx.218.jkshfkh82.&quot;</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:use_sudo</span><span class="p">,</span>                <span class="s2">&quot;true&quot;</span>
</span><span class='line'><span class="n">set</span> <span class="ss">:use_storeconfigs</span><span class="p">,</span>        <span class="s2">&quot;true&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># SSH Config Variables</span>
</span><span class='line'><span class="n">ssh_options</span><span class="o">[</span><span class="ss">:forward_agent</span><span class="o">]</span> <span class="o">=</span> <span class="kp">true</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Role for deployment</span>
</span><span class='line'><span class="n">role</span> <span class="ss">:puppet_masters</span><span class="p">,</span>
</span><span class='line'>   <span class="s2">&quot;puppet.yourorg.com&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Task to run after everything is done. This runs every time.</span>
</span><span class='line'><span class="n">task</span> <span class="ss">:afterparty</span> <span class="k">do</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;if [ ! -d /etc/</span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2"> ]; then sudo -u root mkdir /etc/</span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2">; fi&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo -u root rsync --exclude=&#39;tagmail.conf&#39; --delete -cvrP --no-o --no-g --no-p </span><span class="si">#{</span><span class="n">deploy_to</span><span class="si">}</span><span class="s2">/current/ /etc/</span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2">/&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo -u root chown -R root:</span><span class="si">#{</span><span class="n">app_user</span><span class="si">}</span><span class="s2"> /etc/</span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2">; sudo -u root find /etc/</span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2"> -type d -name &#39;lib&#39; -prune -o -type d -exec chmod 750 {} </span><span class="se">\\</span><span class="s2">; &amp;&amp; sudo chmod -R g+r /etc/</span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo -u root find /etc/</span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2"> -type d -name &#39;lib/*&#39; -exec chmod -R 755 {} </span><span class="se">\\</span><span class="s2">;&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo -u root chmod -R g+w </span><span class="si">#{</span><span class="n">deploy_to</span><span class="si">}</span><span class="s2">/shared/cached-copy&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo -u root /etc/init.d/apache2 restart&quot;</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Generate puppet docs</span>
</span><span class='line'><span class="n">task</span> <span class="ss">:gendocs</span><span class="p">,</span> <span class="ss">:on_error</span> <span class="o">=&gt;</span> <span class="ss">:continue</span> <span class="k">do</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo rm -rf /var/www/puppetdocs/staging /var/www/puppetdocs/production&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo /usr/bin/puppet doc -a -m rdoc --outputdir /var/www/puppetdocs/staging/ --manifestdir /etc/puppet/staging/manifests --modulepath &#39;/etc/puppet/staging/grumps-modules:/etc/puppet/staging/yourorg-modules&#39;&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo /usr/bin/puppet doc -a -m rdoc --outputdir /var/www/puppetdocs/production/ --manifestdir /etc/puppet/production/manifests --modulepath &#39;/etc/puppet/production/grumps-modules:/etc/puppet/production/yourorg-modules&#39;&quot;</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># This task won&#39;t do much to repair a broken git repo</span>
</span><span class='line'><span class="n">task</span> <span class="ss">:fix_deploys</span><span class="p">,</span> <span class="ss">:on_error</span> <span class="o">=&gt;</span> <span class="ss">:continue</span> <span class="k">do</span>
</span><span class='line'>   <span class="n">logger</span><span class="o">.</span><span class="n">info</span> <span class="s2">&quot;Make cached check out group-writeable by </span><span class="si">#{</span><span class="n">admin_group</span><span class="si">}</span><span class="s2">...&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo -u root chgrp -R </span><span class="si">#{</span><span class="n">admin_group</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">deploy_to</span><span class="si">}</span><span class="s2">/shared/cached-copy&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo -u root chmod -R g+w </span><span class="si">#{</span><span class="n">deploy_to</span><span class="si">}</span><span class="s2">/shared/cached-copy&quot;</span>
</span><span class='line'>   <span class="n">logger</span><span class="o">.</span><span class="n">info</span> <span class="s2">&quot;Get repo to pristine state...&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;git checkout </span><span class="si">#{</span><span class="n">deploy_to</span><span class="si">}</span><span class="s2">/shared/cached-copy&quot;</span>
</span><span class='line'>   <span class="n">logger</span><span class="o">.</span><span class="n">info</span> <span class="s2">&quot;Force permission fixes...&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo -u root find </span><span class="si">#{</span><span class="n">deploy_to</span><span class="si">}</span><span class="s2">/shared/cached-copy -type d -exec chmod 2770 {} </span><span class="se">\\</span><span class="s2">;&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo -u root find </span><span class="si">#{</span><span class="n">deploy_to</span><span class="si">}</span><span class="s2">/shared/cached-copy -type f -exec chmod 660 {} </span><span class="se">\\</span><span class="s2">;&quot;</span>
</span><span class='line'>   <span class="n">logger</span><span class="o">.</span><span class="n">info</span> <span class="s2">&quot;Unlocking deploys...&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo -u root rm -f </span><span class="si">#{</span><span class="n">deploy_lockfile</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">task</span> <span class="ss">:notify</span> <span class="k">do</span>
</span><span class='line'>   <span class="nb">require</span> <span class="s1">&#39;etc&#39;</span>
</span><span class='line'>   <span class="nb">require</span> <span class="s1">&#39;rubygems&#39;</span>
</span><span class='line'>   <span class="nb">require</span> <span class="s1">&#39;action_mailer&#39;</span>
</span><span class='line'>
</span><span class='line'>   <span class="no">ActionMailer</span><span class="o">::</span><span class="no">Base</span><span class="o">.</span><span class="n">delivery_method</span> <span class="o">=</span> <span class="ss">:sendmail</span>
</span><span class='line'>   <span class="no">ActionMailer</span><span class="o">::</span><span class="no">Base</span><span class="o">.</span><span class="n">sendmail_settings</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'>      <span class="ss">:location</span>   <span class="o">=&gt;</span> <span class="s1">&#39;/usr/sbin/sendmail&#39;</span><span class="p">,</span>
</span><span class='line'>      <span class="ss">:arguments</span>  <span class="o">=&gt;</span> <span class="s1">&#39;-i -t&#39;</span>
</span><span class='line'>   <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>   <span class="k">class</span> <span class="nc">NotificationMailer</span> <span class="o">&lt;</span> <span class="no">ActionMailer</span><span class="o">::</span><span class="no">Base</span>
</span><span class='line'>      <span class="k">def</span> <span class="nf">deployment</span><span class="p">(</span><span class="n">application</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">notification_email</span><span class="p">)</span>
</span><span class='line'>         <span class="n">mail</span><span class="p">(</span>
</span><span class='line'>            <span class="ss">:from</span>    <span class="o">=&gt;</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="no">Etc</span><span class="o">.</span><span class="n">getpwnam</span><span class="p">(</span><span class="no">ENV</span><span class="o">[</span><span class="s1">&#39;USER&#39;</span><span class="o">]</span><span class="p">)</span><span class="o">.</span><span class="n">gecos</span><span class="si">}</span><span class="s2"> &lt;</span><span class="si">#{</span><span class="no">ENV</span><span class="o">[</span><span class="s1">&#39;USER&#39;</span><span class="o">]</span><span class="si">}</span><span class="s2">@yourorg.com&gt;&quot;</span><span class="p">,</span>
</span><span class='line'>            <span class="ss">:to</span>      <span class="o">=&gt;</span> <span class="n">notification_email</span><span class="p">,</span>
</span><span class='line'>            <span class="ss">:subject</span> <span class="o">=&gt;</span> <span class="s2">&quot;Puppet Deployment - </span><span class="si">#{</span><span class="no">Time</span><span class="o">.</span><span class="n">now</span><span class="o">.</span><span class="n">to_s</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span>
</span><span class='line'>            <span class="ss">:body</span>    <span class="o">=&gt;</span> <span class="n">message</span>
</span><span class='line'>         <span class="p">)</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>   <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">message</span> <span class="o">=</span> <span class="s2">&quot;This is a notification of deployment of a Puppet update.</span><span class="se">\n\n</span><span class="s2">&quot;</span>
</span><span class='line'>   <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">&quot;Deployed at: </span><span class="si">#{</span><span class="no">Time</span><span class="o">.</span><span class="n">now</span><span class="o">.</span><span class="n">to_s</span><span class="si">}</span><span class="se">\n</span><span class="s2">&quot;</span>
</span><span class='line'>   <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">&quot;Revision: </span><span class="si">#{</span><span class="n">real_revision</span><span class="si">}</span><span class="se">\n\n</span><span class="s2">&quot;</span>
</span><span class='line'>
</span><span class='line'>   <span class="c1"># if the revision has not changed then don&#39;t look for logs, also if #SEC</span>
</span><span class='line'>   <span class="c1"># is in the commit message, a full diff is not displayed for security</span>
</span><span class='line'>   <span class="c1"># reasons.</span>
</span><span class='line'>   <span class="k">begin</span>
</span><span class='line'>      <span class="k">if</span> <span class="n">previous_revision</span> <span class="o">!=</span> <span class="n">real_revision</span>
</span><span class='line'>         <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">&quot;SCM Revisions Deployed</span><span class="se">\n</span><span class="s2">&quot;</span>
</span><span class='line'>         <span class="n">gitlog</span> <span class="o">=</span> <span class="sb">`</span><span class="si">#{</span><span class="n">source</span><span class="o">.</span><span class="n">local</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">latest_revision</span><span class="p">,</span> <span class="n">real_revision</span><span class="p">)</span><span class="si">}</span><span class="sb"> -v --oneline`</span>
</span><span class='line'>         <span class="k">if</span> <span class="n">gitlog</span><span class="o">.</span><span class="n">include?</span> <span class="s1">&#39;#SEC&#39;</span>
</span><span class='line'>            <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="n">gitlog</span>
</span><span class='line'>         <span class="k">else</span>
</span><span class='line'>            <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="sb">`</span><span class="si">#{</span><span class="n">source</span><span class="o">.</span><span class="n">local</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">latest_revision</span><span class="p">,</span> <span class="n">real_revision</span><span class="p">)</span><span class="si">}</span><span class="sb"> --submodule=log -v --patch-with-stat`</span>
</span><span class='line'>         <span class="k">end</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>   <span class="k">rescue</span>
</span><span class='line'>      <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s2">&quot;SCM Revisions Deployed</span><span class="se">\n</span><span class="s2">&quot;</span>
</span><span class='line'>      <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="s1">&#39;Previous revision not available&#39;</span>
</span><span class='line'>   <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">mail</span> <span class="o">=</span> <span class="no">NotificationMailer</span><span class="o">.</span><span class="n">deployment</span><span class="p">(</span><span class="n">application</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">notification_email</span><span class="p">)</span>
</span><span class='line'>   <span class="n">mail</span><span class="o">.</span><span class="n">deliver</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Task that cats out what revision is deployed</span>
</span><span class='line'><span class="n">task</span> <span class="ss">:getrev</span> <span class="k">do</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;sudo -u root cat /etc/puppet/REVISION&quot;</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Task to add a lock file and bail deploys with a message if one exists</span>
</span><span class='line'><span class="n">task</span> <span class="ss">:lock_deploys</span> <span class="k">do</span>
</span><span class='line'>   <span class="nb">require</span> <span class="s1">&#39;etc&#39;</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">logger</span><span class="o">.</span><span class="n">info</span> <span class="s2">&quot;Locking deploys...&quot;</span>
</span><span class='line'>
</span><span class='line'>   <span class="k">if</span> <span class="no">ENV</span><span class="o">.</span><span class="n">has_key?</span><span class="p">(</span><span class="s1">&#39;lock_reason&#39;</span><span class="p">)</span>
</span><span class='line'>      <span class="n">lock_reason</span> <span class="o">=</span> <span class="no">ENV</span><span class="o">[</span><span class="s1">&#39;lock_reason&#39;</span><span class="o">]</span>
</span><span class='line'>   <span class="k">else</span>
</span><span class='line'>      <span class="n">lock_reason</span> <span class="o">=</span> <span class="s2">&quot;Deployment&quot;</span>
</span><span class='line'>   <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">data</span> <span class="o">=</span> <span class="n">capture</span><span class="p">(</span><span class="s2">&quot;cat </span><span class="si">#{</span><span class="n">deploy_lockfile</span><span class="si">}</span><span class="s2"> 2&gt;/dev/null; echo&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">to_s</span><span class="o">.</span><span class="n">strip</span>
</span><span class='line'>
</span><span class='line'>   <span class="k">if</span> <span class="o">!</span><span class="n">data</span><span class="o">.</span><span class="n">empty?</span>
</span><span class='line'>      <span class="n">logger</span><span class="o">.</span><span class="n">info</span> <span class="s2">&quot;</span><span class="se">\e</span><span class="s2">[0;31;1mATTENTION:</span><span class="se">\e</span><span class="s2">[0m </span><span class="si">#{</span><span class="n">data</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span class='line'>      <span class="nb">abort</span> <span class="s2">&quot;Deploys are locked.&quot;</span>
</span><span class='line'>   <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">timestamp</span> <span class="o">=</span> <span class="no">Time</span><span class="o">.</span><span class="n">now</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&quot;%m/%d/%Y %H:%M:%S %Z&quot;</span><span class="p">)</span>
</span><span class='line'>   <span class="n">lock_message</span> <span class="o">=</span> <span class="s2">&quot;Deploys locked by </span><span class="si">#{</span><span class="no">Etc</span><span class="o">.</span><span class="n">getpwnam</span><span class="p">(</span><span class="no">ENV</span><span class="o">[</span><span class="s1">&#39;USER&#39;</span><span class="o">]</span><span class="p">)</span><span class="o">.</span><span class="n">gecos</span><span class="si">}</span><span class="s2"> (</span><span class="si">#{</span><span class="no">ENV</span><span class="o">[</span><span class="s1">&#39;USER&#39;</span><span class="o">]</span><span class="si">}</span><span class="s2">) at </span><span class="si">#{</span><span class="n">timestamp</span><span class="si">}</span><span class="s2"> for </span><span class="si">#{</span><span class="n">lock_reason</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span class='line'>   <span class="n">put</span> <span class="n">lock_message</span><span class="p">,</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="n">deploy_lockfile</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span> <span class="ss">:mode</span> <span class="o">=&gt;</span> <span class="mo">0644</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">task</span> <span class="ss">:unlock_deploys</span> <span class="k">do</span>
</span><span class='line'>   <span class="n">logger</span><span class="o">.</span><span class="n">info</span> <span class="s2">&quot;Unlocking deploys...&quot;</span>
</span><span class='line'>   <span class="n">run</span> <span class="s2">&quot;rm -f </span><span class="si">#{</span><span class="n">deploy_lockfile</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Before and After hooks</span>
</span><span class='line'><span class="n">after</span> <span class="s2">&quot;deploy:symlink&quot;</span><span class="p">,</span> <span class="ss">:afterparty</span>
</span><span class='line'><span class="n">after</span> <span class="s2">&quot;deploy:rollback&quot;</span><span class="p">,</span> <span class="ss">:afterparty</span>
</span><span class='line'><span class="n">before</span> <span class="s2">&quot;deploy&quot;</span><span class="p">,</span> <span class="s2">&quot;deploy:cleanup&quot;</span>
</span><span class='line'><span class="n">before</span> <span class="s2">&quot;deploy:cleanup&quot;</span><span class="p">,</span> <span class="ss">:lock_deploys</span>
</span><span class='line'><span class="n">after</span> <span class="s2">&quot;deploy&quot;</span><span class="p">,</span> <span class="ss">:notify</span>
</span><span class='line'><span class="n">before</span> <span class="s2">&quot;notify&quot;</span><span class="p">,</span> <span class="ss">:unlock_deploys</span>
</span><span class='line'><span class="n">after</span> <span class="s2">&quot;notify&quot;</span><span class="p">,</span> <span class="ss">:gendocs</span>
</span><span class='line'>
</span><span class='line'><span class="c1">#vim: set expandtab ts=3 sw=3:</span>
</span></code></pre></td></tr></table></div></figure>


<p>I take no responsibility whatsoever for how you use these scripts. This is
mostly just a demonstration of a workflow that works for me, and keeps everything
clearly separated. I might be able to help people who try to do this, or I
might not (unless you are a paying customer).</p>
]]></content>
  </entry>
  
</feed>
