<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Andy Dote</title><link>https://andydote.co.uk/</link><description>Recent content on Andy Dote</description><generator>Hugo -- gohugo.io</generator><language>en-gb</language><lastBuildDate>Thu, 02 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://andydote.co.uk/rss.xml" rel="self" type="application/rss+xml"/><item><title>On Magic, Convetions, and Implicit vs Explicit</title><link>https://andydote.co.uk/2026/04/02/magic-conventions-implicit-explicit/</link><pubDate>Thu, 02 Apr 2026 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2026/04/02/magic-conventions-implicit-explicit/</guid><description>Earlier in my career I was working as a C# developer, and had read a lot about testing and testability from the Alt.Net crowd, a lose group of people with ideas outside of how Microsoft did things in C#. When I came to needing to write an API, the impossibility of testing in ASP.NET made me look elsewhere.
ASP.NET made heavy usage of Annotations, where you add decorators to methods which at runtime are interpreted by a framework to add functionality, or configure how a function is used.</description><content:encoded><![CDATA[<p>Earlier in my career I was working as a C# developer, and had read a lot about testing and testability from the Alt.Net crowd, a lose group of people with ideas outside of how Microsoft did things in C#.  When I came to needing to write an API, the impossibility of testing in ASP.NET made me look elsewhere.</p>
<p>ASP.NET made heavy usage of Annotations, where you add decorators to methods which at runtime are interpreted by a framework to add functionality, or configure how a function is used.  It wasn&rsquo;t uncommon to see a method with 5 or more Annotations:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c#" data-lang="c#"><span style="display:flex;"><span>HttpRoute(<span style="color:#e6db74">&#34;/user&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UserAddressesController</span> : Controller {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  HttpPost()
</span></span><span style="display:flex;"><span>  HttpPut()
</span></span><span style="display:flex;"><span>  HttpRoute(<span style="color:#e6db74">&#34;/addresses&#34;</span>)
</span></span><span style="display:flex;"><span>  Authenticate()
</span></span><span style="display:flex;"><span>  Accept(<span style="color:#e6db74">&#34;application/json&#34;</span>)
</span></span><span style="display:flex;"><span>  Response(<span style="color:#e6db74">&#34;application/json&#34;</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> function AddAddress() {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> body = HttpContext.Body;
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//...</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Other tools in the .NET world used the concept of Marker interfaces to remove some of the inheritance.  A marker interface doesn&rsquo;t have any methods, but by implementing it the framework finds the class at runtime to use.</p>
<p>FubuMVC (&ldquo;For Us, By Us&rdquo;) was heavily inspired by Ruby, and more specifically Rails.  It favoured <strong>Convention over Configuration</strong> heavily.  Rather than Annotations or Marker Interfaces, it used naming conventions.  Name your class <code>ThingController</code>? it became a controller.  Name it <code>OtherEndpoint</code> and it became an Endpoint.  I don&rsquo;t currently remember what the difference was.  Name your method <code>GetUserAddress</code> and it would handle <code>GET</code> requests to <code>/user/address</code></p>
<p>This was fine when you were doing the obvious parts of the application, like Controllers, and Views and Models etc, but when you started to need to do other things, it got a little harder.  How do you do some error handling decoration to all routes? Add a class called <code>ErrorFilter</code>, with a method with the right signature, and it just works.  As the <a href="https://groups.google.com/g/fubumvc-devel/c/FWhrZcLpAso/m/VuFu8GpyfyYJ?pli=1">author wrote in a retrospective</a> about the project, the documentation was&hellip;limited to put it lightly.  A lot of questions and answers were in a chatroom on Gitter (I think) which was hard to search.</p>
<p>This experience wasn&rsquo;t all negative.  Far from it in fact; it had amazing testability, worked with a decent dependency injection container, and didn&rsquo;t use Annotations at all, which was fantastic.</p>
<p>The system worked well once you knew how it worked, but new developers on the system?  They had better hope there was a more experienced developer around to show them how to add routes, handlers, controllers, and whatnot.</p>
<p>Over time, I have drifted further and further away from Convention over Configuration in this sense.  Conventions in a codebase are still important; things like &ldquo;we name all identifiers <code>ThingId</code>&rdquo;, or &ldquo;cli actions are referred to as Commands&rdquo; give a lot of consistency, without an extra mental hurdle.</p>
<h2 id="being-the-new-guy">Being the New Guy</h2>
<p>At work recently, my friend and I have been given a service to take ownership of, modernise, and start implementing new features in.  The codebase could be generously described as &ldquo;awaiting care&rdquo;, but, it does work.  The issue we are having however is that it is heavily Convention over Configuration based, highly abstracted, and very un-explicit everywhere.  It is borderline magical how the system actually works.</p>
<p>The project is Java based which in itself is not a bad thing, but it leans heavily on Annotations (or Attributes), and two gigantic &ldquo;common&rdquo; libraries which both can do so much based solely off of configuration values.</p>
<p>For example, the codebase uses some kind of role based authentication via an Annotation on the class, and then further annotations on the methods.  I want to know what is actually doing the authentication, but in the <code>.properties</code> files there are several oauth clients configured, all with fairly generic names like &ldquo;oauth&rdquo;, &ldquo;clients&rdquo;, &ldquo;accounts&rdquo;,  kind of names.  None of them are referenced in application code, and it took a lot of digging through shared libraries to figure out what was going on.</p>
<p>Another example are the many HTTP route handlers, which are also configured with Annotations, and <code>@bean</code> magic.  I want to find the handler for some long path, ending with <code>/bulk</code>, which is quite hard to do when the path is split across multiple Annotations (class level, method level), and half the time (yay for inconsistencies!) the route is defined on an abstract class then I have to find the (only) <code>ClassWhateverImpl</code> to see the handler.</p>
<p>These kind of things are problematic for several reasons:</p>
<ol>
<li>I am owning the service.  If auth breaks, I should be able to debug it</li>
<li>We want to refactor and remove unused dependencies.  Are these properties used?</li>
<li>We might replace the service, can we rely on a common auth module for another language?</li>
</ol>
<h2 id="what-i-would-do-instead">What I would do instead</h2>
<p>Be explicit.  Figure out how the team wants to define routes, then do that one thing everywhere.  I love opening a <code>server.go</code> file and finding a method that looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">NewHttpAPI</span>(<span style="color:#f92672">...</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">server</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">createServer</span>(<span style="color:#f92672">...</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// imagine error handling here
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">signals</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">withOsSignals</span>(<span style="color:#a6e22e">ctx</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">withGracefulShutdown</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">server</span>, <span style="color:#a6e22e">signals</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">withTracing</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">server</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">withMetrics</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">server</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">withPanicRecovery</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">server</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">server</span>.<span style="color:#a6e22e">Handle</span>(<span style="color:#e6db74">&#34;GET /_info&#34;</span>, <span style="color:#a6e22e">infoHandler</span>(<span style="color:#a6e22e">config</span>, <span style="color:#a6e22e">deploymentInfo</span>))
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">server</span>.<span style="color:#a6e22e">Handle</span>(<span style="color:#e6db74">&#34;GET /_info/ready&#34;</span>, <span style="color:#a6e22e">readyHandler</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">db</span>, <span style="color:#a6e22e">cache</span>, <span style="color:#a6e22e">signals</span>))
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">server</span>.<span style="color:#a6e22e">Handle</span>(<span style="color:#e6db74">&#34;GET /_info/live&#34;</span>, <span style="color:#a6e22e">liveHandler</span>(<span style="color:#a6e22e">ctx</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">auth</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">authMiddleware</span>(<span style="color:#a6e22e">db</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">server</span>.<span style="color:#a6e22e">Handle</span>(<span style="color:#e6db74">&#34;GET /users&#34;</span>, <span style="color:#a6e22e">getUsersHandler</span>(<span style="color:#a6e22e">cache</span>))
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">server</span>.<span style="color:#a6e22e">Handle</span>(<span style="color:#e6db74">&#34;POST /users&#34;</span>, <span style="color:#a6e22e">auth</span>(<span style="color:#e6db74">&#34;user:create&#34;</span>), <span style="color:#a6e22e">creatUserHandler</span>(<span style="color:#a6e22e">db</span>, <span style="color:#a6e22e">cache</span>))
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">server</span>.<span style="color:#a6e22e">Handler</span>(<span style="color:#e6db74">&#34;DELETE /users/{userid}&#34;</span>, <span style="color:#a6e22e">auth</span>(<span style="color:#e6db74">&#34;user:delete&#34;</span>), <span style="color:#a6e22e">deleteUserHandler</span>(<span style="color:#a6e22e">db</span>, <span style="color:#a6e22e">cache</span>))
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">//...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><p>This code tells me so many things all in once place:</p>
<ul>
<li>all routes are handled by functions called <code>...Handler</code></li>
<li>the server is listening to some OS signals</li>
<li>the signals are used for graceful shutdown</li>
<li>there are tracing, and metrics globally</li>
<li>there is a panic handler to prevent crashes</li>
<li>there is a db and a cache</li>
<li>listing users comes from cache, NOT db</li>
<li>listing users is anonymous allowed</li>
<li>creating a user requires <code>user:create</code> permission, deleting requires <code>user:delete</code></li>
</ul>
<p>This code is possibly longer than a convention based system, but typing speed is not the part of development that slows people down (thinking is).  Code is read far more than written, and having all this information explicitly defined means any new person to the project has a reasonable chance of getting started.</p>
<p>There are also good abstractions hinted at:  I don&rsquo;t need to know how graceful shutdown works, or how OS signals are handled.  If graceful shutdown stops working, the first place I am checking is <code>withGracefulShutdown</code>, followed by <code>withOsSignals</code>.</p>
<h2 id="for-the-future">For the future</h2>
<p>Be explicit, reduce magic, and remember code is read more than written.</p>
<p>Be kind to the new people joining your codebase.  It might just be you in the future!</p>
]]></content:encoded></item><item><title>Database Column Prefixes</title><link>https://andydote.co.uk/2025/01/26/database-column-prefixes/</link><pubDate>Sun, 26 Jan 2025 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2025/01/26/database-column-prefixes/</guid><description>Back in a previous company (the same place as where Debugging GDI Handle Leaks happened), there was an interesting convention in the database: all tables had a unique 3-letter prefix assigned to them, and all columns in that table must start with the prefix, which I&amp;rsquo;ve written about before.
For example, a person table would have the prefix PEO, and the columns would be PEO_PersonID, PEO_FirstName, PEO_DateOfBirth, etc. When you wanted to create a new table, you opened the shared Excel sheet, added your table to the bottom, and made up a prefix that wasn&amp;rsquo;t already in the sheet.</description><content:encoded><![CDATA[<p>Back in a previous company (the same place as where <a href="/2025/01/11/debugging-gdi-handles/">Debugging GDI Handle Leaks</a> happened), there was an interesting convention in the database: all tables had a unique 3-letter prefix assigned to them, and all columns in that table <strong>must</strong> start with the prefix, which I&rsquo;ve written about <a href="/2014/03/29/using-a-micro-orm-to-decouple-your-db-access/">before</a>.</p>
<p>For example, a <code>person</code> table would have the prefix <code>PEO</code>, and the columns would be <code>PEO_PersonID</code>, <code>PEO_FirstName</code>, <code>PEO_DateOfBirth</code>, etc.  When you wanted to create a new table, you opened the shared Excel sheet, added your table to the bottom, and made up a prefix that wasn&rsquo;t already in the sheet.  Even link tables (for many-to-many relationships) were not immune to this rule.</p>
<p>With over 100 tables in the database, finding a prefix which was vaguely related to the table&rsquo;s purpose became harder and harder, especially for common letters, such as <code>C</code> which off the top of my head had tables like <code>Companies</code>, <code>Candidates</code>, <code>Contacts</code>, <code>Categories</code>,<code>Contracts</code>, <code>ContractAttachments</code>, <code>ContractExceptions</code>, and a bunch of link tables to go with them all.</p>
<p>When asked, the DBA said that the reason the convention existed was to prevent column name conflicts when joining tables; all columns would be globally unique!  This made some level of sense for simple queries:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">select</span>  CAN_CandidateID,
</span></span><span style="display:flex;"><span>        PEO_FirstName,
</span></span><span style="display:flex;"><span>        PEO_LastName
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">from</span>    candidates
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">join</span>    people <span style="color:#66d9ef">on</span> CAN_PersonID <span style="color:#f92672">=</span> PEO_PersonID
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">where</span>   CAN_CandidateID <span style="color:#f92672">=</span> <span style="color:#f92672">@</span>candidateID
</span></span></code></pre></div><p>The problem was that this didn&rsquo;t really solve the issue of columns not being ambiguous; queries often needed to join to the person table mulitple times, often via another table:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">select</span>  CAN_CandidateID,
</span></span><span style="display:flex;"><span>        peo.PEO_FirstName <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39; &#39;</span> <span style="color:#f92672">+</span> peo.PEO_LastName <span style="color:#66d9ef">as</span> <span style="color:#e6db74">&#39;name&#39;</span>,
</span></span><span style="display:flex;"><span>        creatorperson.PEO_FirstName <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39; &#39;</span> <span style="color:#f92672">+</span> creatorperson.PEO_LastName <span style="color:#66d9ef">as</span> <span style="color:#e6db74">&#39;creator&#39;</span>,
</span></span><span style="display:flex;"><span>        modifierperson.PEO_FirstName <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39; &#39;</span> <span style="color:#f92672">+</span> modifierperson.PEO_LastName <span style="color:#66d9ef">as</span> <span style="color:#e6db74">&#39;modifier&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">from</span>    candidates
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">join</span>    people peo             <span style="color:#66d9ef">on</span> CAN_PersonID <span style="color:#f92672">=</span> peo.PEO_PersonID
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">join</span>    users creator          <span style="color:#66d9ef">on</span> creator.USR_UserID <span style="color:#f92672">=</span> CAN_CreatedBy
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">join</span>    people creatorperson   <span style="color:#66d9ef">on</span> creatorperson.PEO_PersonID <span style="color:#f92672">=</span> creator.USR_PersonID
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">join</span>    users modifier         <span style="color:#66d9ef">on</span> modifier.USR_UserID <span style="color:#f92672">=</span> CAN_ModifiedBy
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">join</span>    people modifierperson  <span style="color:#66d9ef">on</span> modifierperson.PEO_PersonID <span style="color:#f92672">=</span> creator.USR_PersonID
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">where</span>   CAN_CandidateID <span style="color:#f92672">=</span> <span style="color:#f92672">@</span>candidateID
</span></span></code></pre></div><p>A thing of pure beauty, as you can see.  Not only were all the sql statements far longer than they needed to be, and you often needed to figure out some obscure prefixes, you end up &ldquo;stuttering&rdquo; with things like <code>person.PEO_PersonID</code> - how many times do I need to know this is a PersonID in a single sentence?</p>
<p>The primary key of each table had to include the table name too.  I&rsquo;m not actually convinced this is a bad idea; having a bunch of columns called <code>id</code> doesn&rsquo;t really make things clear when joining 6 tables.</p>
<p>The interesting part of this is that it&rsquo;s all useless; the database server we used supported table aliases (as seen above), so we could use those and drop the prefixes entirely:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">select</span>  CandidateID,
</span></span><span style="display:flex;"><span>        p.FirstName <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39; &#39;</span> <span style="color:#f92672">+</span> p.LastName <span style="color:#66d9ef">as</span> <span style="color:#e6db74">&#39;name&#39;</span>,
</span></span><span style="display:flex;"><span>        creatorperson.FirstName <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39; &#39;</span> <span style="color:#f92672">+</span> creatorperson.LastName <span style="color:#66d9ef">as</span> <span style="color:#e6db74">&#39;creator&#39;</span>,
</span></span><span style="display:flex;"><span>        modifierperson.FirstName <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39; &#39;</span> <span style="color:#f92672">+</span> modifierperson.LastName <span style="color:#66d9ef">as</span> <span style="color:#e6db74">&#39;modifier&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">from</span>    candidates <span style="color:#66d9ef">c</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">join</span>    people p               <span style="color:#66d9ef">on</span> <span style="color:#66d9ef">c</span>.PersonID <span style="color:#f92672">=</span> p.PersonID
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">join</span>    users creator          <span style="color:#66d9ef">on</span> creator.UserID <span style="color:#f92672">=</span> <span style="color:#66d9ef">c</span>.CreatedBy
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">join</span>    people creatorperson   <span style="color:#66d9ef">on</span> creatorperson.PersonID <span style="color:#f92672">=</span> creator.PersonID
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">join</span>    users modifier         <span style="color:#66d9ef">on</span> modifier.UserID <span style="color:#f92672">=</span> <span style="color:#66d9ef">c</span>.ModifiedBy
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">join</span>    people modifierperson  <span style="color:#66d9ef">on</span> modifierperson.PersonID <span style="color:#f92672">=</span> creator.PersonID
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">where</span>   CandidateID <span style="color:#f92672">=</span> <span style="color:#f92672">@</span>candidateID
</span></span></code></pre></div><p>Shorter, at least.</p>
<p>The table relationships didn&rsquo;t always help matters either; the idea of the <code>Person</code> table was that a person could exist as multiple entities in our system; they could be a user, a candidate, and a contact.  Not that this actually happened; they had unique person records for each of their entities.</p>
<p>The table prefixes also meant that when we wanted to use a microORM (<a href="https://www.learndapper.com/">Dapper</a>, which <strong>only</strong> maps queries into objects), we had to make every query alias every column, otherwise our property names would have to also include the prefixes, and we really didn&rsquo;t want the column prefixes polluting the rest of the domain!</p>
<p>We never got rid of this scheme in the primary database; the change wasn&rsquo;t worth doing.  If we had started making new tables without prefixes, we would still have had 100+ old tables with the prefixes, and no chance of fixing them as usually it involved dropping and recreating the tables.  Definitely not worth the hassle.</p>
<p>However, when we started creating separate databases for services which didn&rsquo;t rely on any data in the main database, the column prefix was not used.  In those services, everything felt a little smoother and a little less noisy.</p>
]]></content:encoded></item><item><title>Explicit vs Implicit code</title><link>https://andydote.co.uk/2025/01/19/explicit-vs-implicit-code/</link><pubDate>Sun, 19 Jan 2025 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2025/01/19/explicit-vs-implicit-code/</guid><description>A system I am working on at the moment started giving errors occasionally, say 5 times out of 10,000 messages or so. The error was pretty straightforward:
json: cannot unmarshal array into Go struct field Thing.Parts of type Parts The data structure it is referring to looks like this:
type Thing struct { Parts Parts } type Parts struct { Part []Part } Which represents the (slightly weird) json structure we receive in a message:</description><content:encoded><![CDATA[<p>A system I am working on at the moment started giving errors occasionally, say 5 times out of 10,000 messages or so.  The error was pretty straightforward:</p>
<pre tabindex="0"><code>json: cannot unmarshal array into Go struct field Thing.Parts of type Parts
</code></pre><p>The data structure it is referring to looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">Thing</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Parts</span> <span style="color:#a6e22e">Parts</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">Parts</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Part</span> []<span style="color:#a6e22e">Part</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Which represents the (slightly weird) json structure we receive in a message:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">&#34;thing&#34;</span>: {
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">&#34;parts&#34;</span>: {
</span></span><span style="display:flex;"><span>			<span style="color:#f92672">&#34;part&#34;</span>: [
</span></span><span style="display:flex;"><span>				{ <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;one&#34;</span> },
</span></span><span style="display:flex;"><span>				{ <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;two&#34;</span> }
</span></span><span style="display:flex;"><span>			]
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>However, rarely, we receive a json document which looks like this instead, where the <code>parts</code> struct has instead become an array, with one object containing the <code>part</code> array:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">&#34;thing&#34;</span>: {
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">&#34;parts&#34;</span>: [	
</span></span><span style="display:flex;"><span>			{
</span></span><span style="display:flex;"><span>				<span style="color:#f92672">&#34;part&#34;</span>: [
</span></span><span style="display:flex;"><span>					{ <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;one&#34;</span> },
</span></span><span style="display:flex;"><span>					{ <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;two&#34;</span> }
</span></span><span style="display:flex;"><span>				]
</span></span><span style="display:flex;"><span>			}
</span></span><span style="display:flex;"><span>		]
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In the interest of keeping the software running while digging through for the root cause of this, I added an implementation of the <code>json.Unmarshaler</code> interface to the <code>Parts</code> struct to allow it to handle both forms of json:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#75715e">// duplicate of the Parts type, to prevent recursive calls to the UnmarshalJSON method
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">dto</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Part</span> []<span style="color:#a6e22e">Part</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> (<span style="color:#a6e22e">i</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">Parts</span>) <span style="color:#a6e22e">UnmarshalJSON</span>(<span style="color:#a6e22e">b</span> []<span style="color:#66d9ef">byte</span>) <span style="color:#66d9ef">error</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">// this is the standard format that json arrives in.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>	<span style="color:#a6e22e">normal</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">dto</span>{}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">json</span>.<span style="color:#a6e22e">Unmarshal</span>(<span style="color:#a6e22e">b</span>, <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">normal</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">==</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">t</span>.<span style="color:#a6e22e">Part</span> = <span style="color:#a6e22e">normal</span>.<span style="color:#a6e22e">Part</span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">// sometimes, we get json with an extra array, so if we get an error about that,
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>	<span style="color:#75715e">// try the alternative structure
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">jsonErr</span>, <span style="color:#a6e22e">ok</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">err</span>.(<span style="color:#f92672">*</span><span style="color:#a6e22e">json</span>.<span style="color:#a6e22e">UnmarshalTypeError</span>); <span style="color:#a6e22e">ok</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">jsonErr</span>.<span style="color:#a6e22e">Value</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;array&#34;</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">weird</span> <span style="color:#f92672">:=</span> []<span style="color:#a6e22e">dto</span>{}
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">json</span>.<span style="color:#a6e22e">Unmarshal</span>(<span style="color:#a6e22e">b</span>, <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">weird</span>); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> len(<span style="color:#a6e22e">weird</span>) &gt; <span style="color:#ae81ff">0</span> {
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">t</span>.<span style="color:#a6e22e">Part</span> = <span style="color:#a6e22e">weird</span>[<span style="color:#ae81ff">0</span>].<span style="color:#a6e22e">Part</span>
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>When I opened a pullrequest about this, one of my colleagues approved it, but also noted:</p>
<blockquote>
<p>for once typescript would solve something more cleanly in my opinion</p>
</blockquote>
<p>And I agree, after deserialising, doing something like this is much less code, and basically has the same result.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ts" data-lang="ts"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">thing</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">parse</span>(<span style="color:#a6e22e">message</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (Array.<span style="color:#a6e22e">isArray</span>(<span style="color:#a6e22e">thing</span>.<span style="color:#a6e22e">parts</span>)) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">thing</span>.<span style="color:#a6e22e">parts</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">thing</span>.<span style="color:#a6e22e">parts</span>[<span style="color:#ae81ff">0</span>]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="down-the-rabbit-hole">Down the Rabbit Hole</h2>
<p>Tracing back through the system to figure out where the message came from lead me back to a system which parses an XML document and, after doing some work on the result, emits the json message we handle.  The XML itself has a pretty reasonable structure (and far larger than I am showing here, with tens, if not hundreds of nodes):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;Thing&gt;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">&lt;Parts&gt;</span>
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">&lt;Part</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;one&#34;</span> <span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">&lt;Part</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;two&#34;</span> <span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">&lt;/Parts&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/Thing&gt;</span>
</span></span></code></pre></div><p>Which it mangles into that weird json structure.  It does, however, do some sanitisation to the <code>Thing</code> before writing it out, and I found one for dealing with the <code>Parts</code> property:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ts" data-lang="ts"><span style="display:flex;"><span><span style="color:#75715e">// if there is only one part, the parser doesn&#39;t emit an array, so force an array.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>Array.<span style="color:#a6e22e">isArray</span>(<span style="color:#a6e22e">thing</span>.<span style="color:#a6e22e">parts</span>.<span style="color:#a6e22e">part</span>)) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">thing</span>.<span style="color:#a6e22e">parts</span>.<span style="color:#a6e22e">part</span> <span style="color:#f92672">=</span> [ <span style="color:#a6e22e">part</span> ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Interesting!  but this is a different bug to the one we&rsquo;ve just seen; in our case the <code>Parts</code> became an array&hellip;</p>
<p>Checking the original XML file which was processed, it looked entirely normal until I noticed that it has two <code>Parts</code> nodes:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;Thing&gt;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">&lt;Parts&gt;</span>
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">&lt;Part</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;one&#34;</span> <span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">&lt;Part</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;two&#34;</span> <span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">&lt;/Parts&gt;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">&lt;!-- many nodes later --&gt;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">&lt;Parts&gt;</span>
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">&lt;Part</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;three&#34;</span> <span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">&lt;Part</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;four&#34;</span> <span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">&lt;/Parts&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/Thing&gt;</span>
</span></span></code></pre></div><p>So the fix is to add another sanitisation to our parser:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ts" data-lang="ts"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (Array.<span style="color:#a6e22e">isArray</span>(<span style="color:#a6e22e">thing</span>.<span style="color:#a6e22e">parts</span>)) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">thing</span>.<span style="color:#a6e22e">parts</span> <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">part</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">flatMap</span>(<span style="color:#a6e22e">thing</span>.<span style="color:#a6e22e">parts</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This fixes the data as soon as it appears in our system; however, searching our codebase revealed that, up until this fix, many places had been missing data, or incorrectly handling the data.</p>
<p>While the TypeScript types written for the <code>Thing</code> are correct, that doesn&rsquo;t help when the data is supplied at runtime and apparently can have varying shapes.</p>
<h2 id="the-tradeoff">The Tradeoff</h2>
<p>The tradeoff between typescript/javascript and Go feels like this to me:</p>
<p>Go causes me to notice when something isn&rsquo;t working, as errors start being returned about data not matching the shape it was expected to be in.  Fixing the issues in general, require more code than the same fix in typescript would.</p>
<p>Typescript has short code, but as its only a compile-time type checking system, when weird data starts arriving, you don&rsquo;t get any errors (directly, things later on can break however.)</p>
<p>For me, I would rather have slightly longer code which is more explicit, and tells me when something goes wrong, rather than silently continuing.  The likelihood of a silent error in serialisation leading to data loss or corruption is just too high.</p>
]]></content:encoded></item><item><title>Debugging GDI Handle Leaks</title><link>https://andydote.co.uk/2025/01/11/debugging-gdi-handles/</link><pubDate>Sat, 11 Jan 2025 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2025/01/11/debugging-gdi-handles/</guid><description>Many years ago, I was working on a dotnet Windows Forms application. The application had many issues overall: memory leaks, random crashes, data loss, and in this case, the &amp;ldquo;red x&amp;rdquo; problem.
The problem showed up at random, and instead of a window, dialogue, or control being rendered, it would be replaced with a white box with a red outline and red diagonal cross, and I think some error text in one corner, saying something about GDI handles.</description><content:encoded><![CDATA[<p>Many years ago, I was working on a dotnet Windows Forms application.  The application had many issues overall: memory leaks, random crashes, data loss, and in this case, the &ldquo;red x&rdquo; problem.</p>
<p>The problem showed up at random, and instead of a window, dialogue, or control being rendered, it would be replaced with a white box with a red outline and red diagonal cross, and I <em>think</em> some error text in one corner, saying something about GDI handles.  The issue itself didn&rsquo;t seem to be related to either time or memory usage; when the app crashed, we got an error report (usually), and that never suggested that the application had been open particularly long or that it was using an excessive amount of memory.</p>
<p>I had been given the job of fixing this problem (and others), so armed with a memory profiler (RedGate&rsquo;s, if I recall correctly), I went to work.  With no given reproduction, it was hard.  Some searching had shown that GDI handles were created when doing custom control painting; usually, this would be a fairly strong indicator of where to look, but in the case of this application, nearly all controls were custom-drawn, and there were many.</p>
<p>After days of taking memory snapshots and running comparisons, the only thing I was really noticing was that the number of font instances in use seemed high and got higher whenever I opened dialogues; it never went down again.</p>
<p>So, something to do with fonts.  Reading through our common control base code, I noticed this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c#" data-lang="c#"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ControlBase</span> : Control
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">private</span> Font _normal = <span style="color:#66d9ef">new</span> Font(<span style="color:#e6db74">&#34;some-font&#34;</span>, <span style="color:#ae81ff">12</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">private</span> Font _bold = <span style="color:#66d9ef">new</span> Font(<span style="color:#e6db74">&#34;some-font&#34;</span>, <span style="color:#ae81ff">12</span>, Options.Bold);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">private</span> Font _italic = <span style="color:#66d9ef">new</span> Font(<span style="color:#e6db74">&#34;some-font&#34;</span>, <span style="color:#ae81ff">12</span>, Options.Italic);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// ...</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This snippet means that every single control had 3 instances of a <code>Font</code>, which was never disposed (no <code>_normal.Dispose()</code> in the <code>ControlBase.Dispose()</code> function.)  My first reaction was to add the three <code>.Dispose()</code> calls, but realising the fonts were never modified after creation led me to make them <code>static</code> so that all control instances shared the same font instances.</p>
<p>A week or two of work, and the only output was adding 3x <code>static</code> words to the codebase - but the effect was that our application went from using 1000s of font instances to 3.  Quite the saving - and we never had the red X problem again!</p>
<p>The first lesson I took from this was that memory profiling is hard - running the app, taking a snapshot, running a bit more, taking a snapshot, etc. was not a fun feedback loop, especially as running with the profile slowed everything down massively.</p>
<p>The second, and probably more important, lesson was that the number of lines changed doesn&rsquo;t reflect the amount of effort that went into changing those lines.</p>
]]></content:encoded></item><item><title>Telemetry and Cancelled Contexts</title><link>https://andydote.co.uk/2024/12/26/opentelemetry-cancelled-contexts/</link><pubDate>Thu, 26 Dec 2024 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2024/12/26/opentelemetry-cancelled-contexts/</guid><description>I use opentelemetry extensively to trace my applications, and one thing I keep running into is when writing a long running process, I want to handle OS signals and still send the telemetry on shutdown.
Typically, my application startup looks something like this:
func main() { ctx, cancel := context.WithCancel(context.Background()) handleSignals(cancel) tracerProvider := configureTelemetry(ctx) defer tracerProvider.Shutdown(ctx) tr = traceProvider.Tracer(&amp;#34;cli&amp;#34;) if err := runMain(ctx, os.Args[:]); err != nil { fmt.Fprintf(os.Stderr, err.Error()) tracerProvider.</description><content:encoded><![CDATA[<p>I use opentelemetry extensively to trace my applications, and one thing I keep running into is when writing a long running process, I want to handle OS signals and still send the telemetry on shutdown.</p>
<p>Typically, my application startup looks something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">cancel</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">WithCancel</span>(<span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Background</span>())
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">handleSignals</span>(<span style="color:#a6e22e">cancel</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">tracerProvider</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">configureTelemetry</span>(<span style="color:#a6e22e">ctx</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">tracerProvider</span>.<span style="color:#a6e22e">Shutdown</span>(<span style="color:#a6e22e">ctx</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">tr</span> = <span style="color:#a6e22e">traceProvider</span>.<span style="color:#a6e22e">Tracer</span>(<span style="color:#e6db74">&#34;cli&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">runMain</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Args</span>[:]); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Fprintf</span>(<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Stderr</span>, <span style="color:#a6e22e">err</span>.<span style="color:#a6e22e">Error</span>())
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">tracerProvider</span>.<span style="color:#a6e22e">Shutdown</span>(<span style="color:#a6e22e">ctx</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Exit</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">runMain</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">args</span> []<span style="color:#66d9ef">string</span>) <span style="color:#66d9ef">error</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">span</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">tr</span>.<span style="color:#a6e22e">Start</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;main&#34;</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">End</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// some kind of loop
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">message</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">someProcess</span>(<span style="color:#a6e22e">ctx</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">select</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">case</span> <span style="color:#f92672">&lt;-</span><span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">Done</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">Err</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">default</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">doMessageThings</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">message</span>)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>handleSignals</code> method listens to things like <code>sigint</code>, and calls the <code>cancel()</code> function, and the app stops processing messages and exits gracefully.</p>
<p>When the application exited due to errors, I would see the whole trace from the application, but if the application stopped due to <code>sigint</code> or similar, the <code>main</code> span would never come through.</p>
<p>After a bit of reading, I realised the bug is here:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span>ctx, cancel := context.WithCancel(context.Background())
</span></span><span style="display:flex;"><span>handleSignals(cancel)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>tracerProvider := configureTelemetry(ctx)
</span></span><span style="display:flex;"><span><span style="color:#f92672">- defer tracerProvider.Shutdown(ctx)
</span></span></span><span style="display:flex;"><span><span style="color:#f92672"></span><span style="color:#a6e22e">+ defer tracerProvider.Shutdown(context.Background())
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>
</span></span><span style="display:flex;"><span>  tr = traceProvider.Tracer(&#34;cli&#34;)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  if err := runMain(ctx, os.Args[:]); err != nil {
</span></span><span style="display:flex;"><span>    fmt.Fprintf(os.Stderr, err.Error())
</span></span><span style="display:flex;"><span><span style="color:#f92672">-    tracerProvider.Shutdown(ctx)
</span></span></span><span style="display:flex;"><span><span style="color:#f92672"></span><span style="color:#a6e22e">+    tracerProvider.Shutdown(context.Background())
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>    os.Exit(1)
</span></span></code></pre></div><p>The problem is that when the context has been cancelled, the tracerProvider skips doing any work, so never sends through the last spans!</p>
<p>This issue would have been more noticable if:</p>
<ul>
<li>I checked the <code>err</code> value from <code>Shutdown()</code>, which is easily missed in a <code>defer</code> call</li>
<li>Setting <code>OTEL_LOG_LEVEL</code> to <code>debug</code> printed something useful!</li>
</ul>
<p>Hopefully by writing this down I will remember or at least find the answer next time I manage to do this again!</p>
]]></content:encoded></item><item><title>Outside In Design</title><link>https://andydote.co.uk/2024/12/12/system-design-outside-in/</link><pubDate>Thu, 12 Dec 2024 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2024/12/12/system-design-outside-in/</guid><description>Following on from my previous post about not having too much configuration, I want to talk about how I design software.
I try and follow what I call &amp;ldquo;outside in design&amp;rdquo;; I try and make something that requires the bare minimum amount of configuration to cover the most common of use-cases. Once this functionality is working, further configuration can be added to cover the next most common use cases.
API Reduction As A Feature The first example I want to go through is how I removed options from an HTTP rate limiter we use.</description><content:encoded><![CDATA[<p>Following on from my previous post about not having <a href="/2024/10/31/too-much-configuration/">too much configuration</a>, I want to talk about how I design software.</p>
<p>I try and follow what I call &ldquo;outside in design&rdquo;; I try and make something that requires the bare minimum amount of configuration to cover the most common of use-cases.  Once this functionality is working, further configuration can be added to cover the next most common use cases.</p>
<h2 id="api-reduction-as-a-feature">API Reduction As A Feature</h2>
<p>The first example I want to go through is how I removed options from an HTTP rate limiter we use.  There are many teams using rate limiters, and we have noticed that there are often similar mistakes made in how they work and duplication of domain-specific functionality.</p>
<p>In order to make life easier for <em>most</em> users, a new rate limiter was made which reduced the API surface area, only exposing the bare minimum options.</p>
<p><strong>Algorithm.</strong> Instead of offering many different types of algorithm (for example <code>Token Bucket</code>, <code>Leaky Bucket</code>, <code>Fixed Window Counter</code>, and <code>Sliding Window</code>), the rate limiter only uses <code>Sliding Window</code>.</p>
<p><strong>Sizes.</strong>: By forcing the use of a specific algorithm, we eliminate a lot of algorithm specific options, such as bucket capacity, refill/drain rate, and window overlap.  We expose a single option of <code>WindowSeconds</code> with a default vault of <code>60</code>.</p>
<p><strong>Penalties.</strong> We also decided to not expose how long a ban is, and instead make it a multiple of the <code>WindowSeconds</code> option, in our case <code>WindowSeconds * 3</code>.</p>
<p><strong>Selection Criteria.</strong> Rate limiters we observed could filter by many different properties, such as IP Address, Headers, Cookies, Path, Query, Status Code, etc.  Our rate limiter has the following rules:</p>
<ul>
<li>Account and Path</li>
<li>Account and (bad) Status</li>
<li>IP Address and Path</li>
<li>IP Address and (bad) Status</li>
<li>Anonymous IP</li>
</ul>
<p>The way the account is detected is the same for all services in our domain, so we can centralise the checking code to be identical in all instances.</p>
<p><strong>Triggering.</strong> For triggering, we went with the simplest thing possible: if any counter&rsquo;s value goes over a threshold, then a ban is issued for the Account or IP address triggering the ban.  The threshold value is exposed as <code>MaxRequests</code> with a default value of <code>100</code></p>
<p>Finally, we expose one additional configuration: <code>Storage</code>.  This is an optional field which you can set to a Valkey or Redis-compatible client so that if you have many instances of your application, the rate-limiting is shared amongst all instances.</p>
<p>For most of our teams, using a rate limiter is now this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">limiter</span> <span style="color:#f92672">:=</span> <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">org</span>.<span style="color:#a6e22e">NewRateLimiter</span>(
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">org</span>.<span style="color:#a6e22e">WithStorage</span>(<span style="color:#a6e22e">valkey</span>),
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">org</span>.<span style="color:#a6e22e">WithMaxRequests</span>(<span style="color:#ae81ff">80</span>),
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">mux</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">NewServeMux</span>()
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">mux</span>.<span style="color:#a6e22e">Handle</span>(<span style="color:#e6db74">&#34;/&#34;</span>, <span style="color:#a6e22e">limiter</span>(<span style="color:#a6e22e">apiRootHandler</span>))
</span></span></code></pre></div><p>For teams that need more customisation, we recommend they reach out to us to see what their needs are; the outcome would usually be embedding and customising the rate-limiter, forking the library, or using an off-the-shelf library directly.  So far very few teams have needed extra customisation.</p>
<p>The downside to this approach is if we want to change some detail about how the rate limiter works; we now have to find all the teams using it to make sure we don&rsquo;t break their workflow.  For Go projects, we typically bump the major version of the library, and have explicit messaging about the differences in the readme.</p>
<h2 id="organisation-conventions">Organisation Conventions</h2>
<p>The next example is trying to show off what we can achive when using conventions;  some of these conventions were in place before we wrote this code, and some have become conventions since.</p>
<p>When it comes to building docker containers, there are a few things that people, in general, want:</p>
<ul>
<li>the container to be built</li>
<li>tests to be run, preventing publishing broken containers</li>
<li>the (working) container to be published somewhere so it can be used</li>
<li>extra artifacts from the build to be collected (test reports, coverage, etc.)</li>
<li>it to be fast</li>
</ul>
<p>The problem with all these things is in the details; building itself is fairly straightforward, but publishing requires knowing where to publish, any credentials required, and how to name and version the container.  Likewise, artifact collection requires knowing where the artifacts are to be collected from, and where to publish them to (along with authentication etc.)</p>
<p>The even bigger issue is &ldquo;to be fast&rdquo;; people don&rsquo;t care about how its fast, they just want fast.  This means not only making a cacheable dockerfile but doing that caching somehow; with ephemeral build agents, that caching becomes harder.</p>
<p>We can go through our requirements and see what ones we know the answers to already and what we need to get from users:</p>
<p><strong>Docker Registry.</strong> The internal Secret Management Service (SMS) has a convention for where your docker registry is, and what the credentials are: read from <code>/teams/$team_name/docker/registry</code>.</p>
<p><strong>Container Path.</strong> We always publish to <code>$registry/$team_name/$repo_name/$container_name</code>.</p>
<p><strong>Container Name.</strong> A repository can have multiple containers, or the name of the container can differ from the repository.  So for this property, we need the users to supply something.</p>
<p><strong>Container Version.</strong> We decided that a short git SHA is enough for versioning.</p>
<p><strong>Caching.</strong> The registry has a second path convention for storing cache contents: <code>$registry/cache/$team_name/$repo_name/$container_name</code>.</p>
<p><strong>Artifacts.</strong> Artifacts are published to the Github Actions artifacts, so no extra authentication or settings are needed.  We decided that if the <code>.artifacts</code> folder exists and has contents, that is what will get stored.</p>
<p>Given the above analysis, we decided on 4 configuration options:</p>
<ol>
<li><code>team_name</code>: no default.  We will use this value to find the registry information and build container and cache paths.</li>
<li><code>container_name</code>: no default.  You need to tell us what the name of your container should be.</li>
<li><code>build_args</code>: default empty.  Supply extra arguments to the <code>docker build</code> command.  Some teams need to inject extra information from the host.</li>
<li><code>dockerfile</code>: default <code>./Dockerfile</code>.  Some teams have multiple dockerfiles in their repository, or keep the files in subfolders.</li>
</ol>
<p>By relying on the <code>team_name</code> parameter, so many other options can be eliminated, and it turns out most people don&rsquo;t care what exact path their containers are uploaded to, as long as they are accessible when it comes to being used in a deployment environment.  This is foreshadowing!</p>
<p>For most teams, their build workflow becomes just two steps: checkout sourcecode, and build the container:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">steps</span>:
</span></span><span style="display:flex;"><span>- <span style="color:#f92672">uses</span>: <span style="color:#ae81ff">actions/checkout@v4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>- <span style="color:#f92672">uses</span>: <span style="color:#ae81ff">org/docker-build@v1</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">with</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">team_name</span>: <span style="color:#e6db74">&#34;team-one&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">api</span>
</span></span></code></pre></div><h2 id="organisation-conventions-two">Organisation Conventions Two</h2>
<p>Now that we have a shared way to build docker containers with low configuration, the next logical step was figuring out if we could do the same for deployment.  It turns out a lot of the conventions used to build the container can be applied to deployment: docker registry, container path, container name, and container version are all the same between the two.  In addition, we need to add a few more: the name of the environment being deployed to and the path to your deployment definition file (for example, a Nomad job).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">steps</span>:
</span></span><span style="display:flex;"><span>- <span style="color:#f92672">uses</span>: <span style="color:#ae81ff">org/nomad-docker@v1</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">with</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">team_name</span>: <span style="color:#e6db74">&#34;team-one&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">api</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">environment</span>: <span style="color:#ae81ff">live</span>
</span></span></code></pre></div><h2 id="the-pit-of-success">The Pit of Success</h2>
<p>We also like to leverage The Pit of Success, which seems to originate from <a href="https://learn.microsoft.com/en-us/archive/blogs/brada/the-pit-of-success">Rico Mariani</a>; we want to make doing the easiest thing to be the correct thing.</p>
<p>To that end, we provide a library to populate an app&rsquo;s secrets.  This library handles multiple forms of authentication for different runtime locations (developer machine, nomad cluster, lambda, etc.), and handles where the secrets themselves are located.</p>
<p>The library&rsquo;s usage boils down to two things.  A single <code>struct</code> to represent their secrets:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">Secrets</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ClientID</span> <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ClientSecret</span> <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ApiToken</span> <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// etc
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><p>And a single function call to populate it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">org</span>.<span style="color:#a6e22e">ReadSecrets</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;management-api&#34;</span>, <span style="color:#a6e22e">secrets</span>)
</span></span></code></pre></div><p>This function call does a lot behind the scenes:</p>
<p><strong>Authentication.</strong> This varies based on where the app is running: on a developer machine, it uses the local cached secret manager credentials and triggers authentication flows if needed.  When deployed, it uses the relevant secret authentication system for that environment (e.g. Nomad&rsquo;s Vault integration or AWS Secret Manager in Lambda).</p>
<p><strong>Secret Location.</strong> It reads all the secrets for from a conventional path: <code>/teams/$team_name/apps/$app_name/$env/*</code>, where the values come from different places:</p>
<ul>
<li><code>team_name</code> comes from a common environment variable, and <code>ReadSecrets</code> errors if its not populated</li>
<li><code>env</code> comes from either an environment variable when the app is deployed somewhere or is set to <code>local</code> on a developer&rsquo;s machine.</li>
<li><code>app_name</code> is supplied in code (<code>management-api</code> in this case)</li>
</ul>
<p>While teams can roll their own secret management integration, our library is so easy to use that almost no teams choose to do anything different.</p>
<h2 id="the-golden-path">The Golden Path</h2>
<p>Our tools form what we call our Golden Path, a term which seems to originate from <a href="https://engineering.atspotify.com/2020/08/how-we-use-golden-paths-to-solve-fragmentation-in-our-software-ecosystem/#:~:text=The%20Golden%20Path%20%E2%80%94%20as%20we,this%20opinionated%20and%20supported%20path.">spotify</a>.  We use it to define a way to develop and deploy software in a tried and tested manner.  Teams are always free to choose their own path by changing what parts of the system they see fit.</p>
<p>The trade off teams are making is between maintenance burden and configuration;  choose our tools, and you don&rsquo;t need to worry about them working, but you need to follow our conventions and opinions.</p>
<h2 id="how-do-you-design-software">How Do You Design Software?</h2>
<p>While this is working really well for me and my teams, there has to be other opinions too; I&rsquo;d be interested in hearing how people do this for their teams and projects.</p>
]]></content:encoded></item><item><title>Print debugging: a tool among other tools</title><link>https://andydote.co.uk/2024/11/24/print-debugging-tracing/</link><pubDate>Sun, 24 Nov 2024 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2024/11/24/print-debugging-tracing/</guid><description>This is my thoughts after reading Don&amp;rsquo;t Look Down on Print Debugging.
TLDR Print debugging is a tool, and it has its uses - however, if there are better tools available, maybe use those instead. For me, a better tool is OpenTelemetry tracing; it gives me high granularity, parent-child relationships between operations, timings, and is filterable and searchable. I can also use it to debug remote issues, as long as the user can send me a file.</description><content:encoded><![CDATA[<p>This is my thoughts after reading <a href="https://blog.startifact.com/posts/print-debugging/">Don&rsquo;t Look Down on Print Debugging</a>.</p>
<h2 id="tldr">TLDR</h2>
<p>Print debugging is a tool, and it has its uses - however, if there are better tools available, maybe use those instead.  For me, a better tool is OpenTelemetry <a href="https://opentelemetry.io/docs/concepts/signals/traces/">tracing</a>; it gives me high granularity, parent-child relationships between operations, timings, and is filterable and searchable.  I can also use it to debug <a href="#tracing-for-remote-debugging">remote issues</a>, as long as the user can send me a file.</p>
<h2 id="print-debugging">Print Debugging</h2>
<p>The good thing about print debugging is that it is always available; it is very rare a process doesn&rsquo;t have a stdout (or stderr) available, or some kind of logging system.  The downside with print debugging is that it is very basic; anything more you want to do with it, such as timing data, has to be implemented.</p>
<p>One of the comments I read was, in essence:</p>
<blockquote>
<p>one place print debugging is best is dealing with threading/timing bugs, it lets you see what is happening when</p>
</blockquote>
<p>I can understand this, but often print statements are buffered before hitting the terminal, so you might lose some order; you can solve that with a timestamp (assuming it&rsquo;s accurate enough), but as I mentioned earlier, you need to do that yourself.</p>
<h2 id="use-a-debugger">Use a Debugger?</h2>
<p>The first debugger I used was in Visual Studio, and it was amazing.  I learned how to use a lot of features in it, such as automatic break-on-exception, conditional breakpoints, automatic counters (&ldquo;break after hitting this line x times&rdquo;), watches, and computed values.  This was at the beginning of my career, and neither I, nor the codebase, knew anything of automated testing.</p>
<p>Once I learned about automated testing, and then started writing tests, the amount of time I used the debugger reduced.  It was still a great tool, but tests were sometimes the quicker way to verify some behaviour.  Often times, once I had investigated a problem with the debugger, I would write a test to cover that situation - now the repeated debugger usage to know if the fix worked wasn&rsquo;t needed.</p>
<p>I don&rsquo;t often use a debugger these days.  It still has it&rsquo;s place in my toolkit, but in general, I lean more on OpenTelemetry and tracing in general.</p>
<h2 id="tracing">Tracing</h2>
<p>My current go-to tool for debugging and application development is OpenTelemetry tracing.  I&rsquo;ve written about why I <a href="/2023/09/19/tracing-is-better/">prefer tracing to Structured Logging</a> before, but this is a bit different.</p>
<p>By default, tracing lets me see the relationships between function calls, the timing durations of each span (a span is a unit of execution; it could be a function call or a call into a library), and many structured attributes (both automatic and manually added.)</p>
<p>The downside is that you need some way to view that tracing data; using the stdout trace exporter is generally not useful - its far too noisy.  For local development I use <a href="https://hub.docker.com/r/grafana/otel-lgtm">Grafana Tempo all-in-one</a>, or <a href="https://github.com/ymtdzzz/otel-tui">Otel-TUI</a>.  For deployed environments, I still think <a href="https://honeycomb.io">honeycomb</a> is the best placec for traces.</p>
<p>Most projects I interact with have a docker-compose file for all their local dependencies; adding a tracing viewer to that compose file is pretty trival, so the barrier to entry is really not that high:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">grafana</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">image</span>: <span style="color:#ae81ff">grafana/otel-lgtm</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>  - <span style="color:#e6db74">&#34;3000:3000&#34;</span>
</span></span><span style="display:flex;"><span>  - <span style="color:#e6db74">&#34;4317:4317&#34;</span>
</span></span></code></pre></div><h2 id="tracing-for-remote-debugging">Tracing for Remote Debugging</h2>
<p>I maintain some internal CLI applications, which make extensive use of tracing.  When a user has a problem, they can add a <code>--store-traces</code> flag to the CLI, and it will write all the tracing data for their run to a file on disk.  They can then send me that file, I can load it into a trace viewer, and use all the high-cardinality attributes and timing data to figure out where their problem is exactly.</p>
<h2 id="do-you-ever-use-print-debugging">Do you ever use print debugging?</h2>
<p>Not often, but it does happen sometimes.  As I said at the outset; its just a tool, and I can and do use it.  I just happen to prefer a different tool.</p>
]]></content:encoded></item><item><title>Too Much Configuration</title><link>https://andydote.co.uk/2024/10/31/too-much-configuration/</link><pubDate>Thu, 31 Oct 2024 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2024/10/31/too-much-configuration/</guid><description>When writing software, you will come across many questions which don&amp;rsquo;t always have a clear answer, and its tempting to not answer the question, and provide it as a configuration option to the user of your software. You might go as far as setting a default value though. This seems good for everyone; you don&amp;rsquo;t have to make a decision, users can change their minds whenever they want.
However, too much configuration is a bad thing in general.</description><content:encoded><![CDATA[<p>When writing software, you will come across many questions which don&rsquo;t always have a clear answer, and its tempting to not answer the question, and provide it as a configuration option to the user of your software.  You might go as far as setting a default value though.  This seems good for everyone; you don&rsquo;t have to make a decision, users can change their minds whenever they want.</p>
<p>However, too much configuration is a bad thing in general.  There are two ways I want to view configuration: internally, from the developer of the software&rsquo;s perspective, and externally, from the user of the software&rsquo;s persepective (who might also be writing software.)</p>
<p>Most of the categories I will cover exist in both internal and external sections, as the effects they have are bi-directional.</p>
<h2 id="internal-issues">Internal Issues</h2>
<p>While internal issues will be more felt by you, the developer of software, I think that they are actually less important than the external issues.  How a user experiences your software is siginficantly important, and in general I would rather take on a little burden to allow my users to have a better experience - to a point though.</p>
<h3 id="cognitive-load">Cognitive Load</h3>
<p>One of the most underlooked aspect of configuration is the cognative load it puts on developers.  Every configuration value brings in additional questions, some of which we will touch on later.  For now I want to look at how a value is actually used.  Every piece of indirection in a codebase adds up over time - some indirection is useful and needed for sure, but having too much makes it harder to follow flow of the program.</p>
<p>Often times, configuration values interact with eachother in unexpected ways; a retry-count and a backoff-strategy when configured together can cause your program to retry forever very fast, or retry forever with days between attempts.</p>
<h3 id="changing-values">Changing Values</h3>
<p>A configuration value is part of your API contract; changing anyhthing about it can break your users, and might keep you from making needed changes.  For example, if a configuration has a default value, and you want to change that default, how do you handle all the usages of your software which are expecting the default to remain the same?  will it impact their usage?  The same goes for removing a default value, renaming a configuration setting, or changing its type.</p>
<h3 id="validation">Validation</h3>
<p>Configuration values need validating, and not just checking they are the expected type (type validation) - they also need semantic validation; checking wether a value makes sense in the given context.  For example, setting an HTTP timeout to 3 days is probably not a useful thing to do.</p>
<p>This adds to the complexity of your software: constants (or even magic values) don&rsquo;t need this extra validation and the more code you have to maintain, the higher the burden of maintenance.</p>
<h3 id="complexity">Complexity</h3>
<p>This area in general applies to applications over libraries, but does apply to both, especially when libraries can read configuration from multiple places.</p>
<p>First off, how many configuration sources does your software have?  For a CLI, there are usually at least three sources: Command arguments and flags, environment variables, and configuration files.  These sources need to have their values merged somehow, and even if that strategy is just &ldquo;cli arguments win&rdquo;, you still have to implement a hierarchy and all the complexities that come with that.  Boolean configurations are fairly straightforward, but how do arrays or nested objects work?  Do you merge the array values?  Do you replace the entire array?  And is the answer the same for all arrays in your configuration, or does it differ?</p>
<p>If you are lucky, all the complexity is encapsulated into one place, such that the rest of you software sees a single <code>Configuration</code> object of some form, and doesn&rsquo;t need to worry about how the values got into that structure.</p>
<p>However, even libraries end up doing things with the environment.  For example, the OpenTelemetry libraries will read the environment for default values; this is nice to start with as you have to write less code to get things up and running, and (at least for OpenTelemetry) the environment variables are documented, and the same across languages and versions.  It does mean, though, that the configuration for your OpenTelemetry setup is separate from the rest of your application.  What if you also need to do something that depends on a value that is used for OpenTelemetry?</p>
<p>The final complexity to talk about is the extra code paths introduced by each configuration value.  This applies to things like which storage method to use in the application, rather than only supporting one, or which transports to use.  I have had experience with a vendor whose product supported multiple central logging backends, but it turned out they primarily used Firebase, and all other backends weren&rsquo;t tested so thoroughly.  We saw so many performance problems with the other &ldquo;supported&rdquo; backends.  Which leads us nicely to Testing.</p>
<h3 id="testing">Testing</h3>
<p>Testing configuration is tricky; generally its not really done, which leaves you open to problems like &ldquo;did this value here really used to work?&rdquo;</p>
<p>Frequently when developing software, I have multiple implementations of a cache in my programs:  there is the real implementation (such as Redis or a filesystem), a testing cache (in memory), and a bunch of decorators (statistics about the cache, tracing of what is happening etc.)  When testing most of my applications, I use the <code>InMemoryCache</code> as it is the fastest and eliminates shared state from my tests (or even between test runs), but I have to make sure there are also sufficient integration tests for the application using the real cache - not just testing its implementation.</p>
<h3 id="documentation">Documentation</h3>
<p>Configuration values need documenting: what each value does, whether it is required or not, what it&rsquo;s default value is, and any interactions it has (i.e. configuration it cannot work with or requires to also be set.)  Documentation is generally not the strongest of points for developers, and keeping that documentation up to date and accurate again adds to the maintenance burden.</p>
<h2 id="external-issues">External Issues</h2>
<p>The issues we face internally are also faced externally by the users of our software.  Not all of them are exactly the same, and the problems can be easier or harder than the internal problems.</p>
<h3 id="cognative-load">Cognative Load</h3>
<p>When you encounter a piece of software which has <em>so many</em> options, how do you go about figuring out what settings you need for your usage, and what properties need to be set?  If you are lucky, the <a href="#documentation">Documentation</a> is up to date and easily discoverable.</p>
<p>One interesting problem occurs with default values; I have seen software where not specifying a property means something very different from specifying it as null/empty/etc.</p>
<p>The interaction of different properties can also be hard to follow; properties which only work when other properties are set (or not set) is one issue, and the other is how the values you specify interact with each other, such as with timeouts and retries.</p>
<p>If there are many configuration properties, trying to discern the right one to change is also a burden, and this gets even worse when there are many sources of configuration:  where is the appropriate place to set the value?  is something else overriding it?  do you even know where all possible places the configuration can come from are?</p>
<h3 id="changing-values-1">Changing Values</h3>
<p>This is pretty much the same as the Internal Issues Changing Values section; if I have configured something and it is working, but then at some point the default values of <em>something</em> change, and it stops working, I now have to spend a lot of effort figuring out which value change was the culprit, and possibly try and work out what the old value was so that I can put it back to how it was.</p>
<p>This can be especially difficult if the changelog only says &ldquo;changed the default value of $thingy to 17&rdquo; - what it was before is a mystery, but maybe you can figure it out by looking through the commits.  Assuming its opensource (or source available.)</p>
<p>What happens when a new feature is added?  Should it be disabled by default or enabled by default?  What if it suddenly starts doing something you don&rsquo;t want, or its configuration starts affecting your existing configuration?</p>
<h3 id="validation-1">Validation</h3>
<p>Like the previous validation section, we are trying to think of not only what values can go here but also what format they should be in.  Is the value specified in seconds?  Milliseconds?  Epoch?  or is it a string of &ldquo;3m20s&rdquo;?  Hopefully, the software will tell you the value is invalid, but it might just ignore invalid values, making you think you&rsquo;re setting something, but nothing is actually happening.</p>
<p>An experience I had somewhat recently with the <a href="https://kubernetes-sigs.github.io/aws-load-balancer-controller/">ALB Controller</a> was related to a configuration value.  We had the following set in an annotation, which worked fine:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">alb.ingress.kubernetes.io/success-codes</span>: <span style="color:#ae81ff">200</span>, <span style="color:#ae81ff">204</span>
</span></span></code></pre></div><p>But someone decided that <code>204</code> was no longer a valid success-code, so removed the <code>, 204</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">alb.ingress.kubernetes.io/success-codes</span>: <span style="color:#ae81ff">200</span>
</span></span></code></pre></div><p>&hellip;which broke silently when deployed - the problem was that the ALB controller is expecting a string here, when the value changed it suddenly parsed as an integer.  What made this harder to pick up is that the deployment itself worked, but the ALB controller started throwing errors, and that wasn&rsquo;t noticed for a while.  The fix, by the way, was to add quotes around the value.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">alb.ingress.kubernetes.io/success-codes</span>: <span style="color:#e6db74">&#34;200&#34;</span>
</span></span></code></pre></div><h3 id="testing-1">Testing</h3>
<p>How often do you test that configuration of software is correct?  I would hazzard a guess at &ldquo;not often&rdquo; - and when it is done, it tends to be just testing of the configuration values themselves; checking a timeout is set or not set for example.</p>
<p>What is harder to manage is to test the the given configuration has the desired effect on the software itself.  How do you go about testing that timeouts and retries work as expected?  or authentication parameters are having the desired effect?</p>
<p>This kind of testing is important too, especially when updating software; minor, or even patch versions of software can have breaking changes, and if you&rsquo;re not testing it still does what you want, how will you know that everything is configured correctly?</p>
<h2 id="suggestions-for-better-configuration">Suggestions for better configuration</h2>
<ol>
<li>Don&rsquo;t make something configurable unless it needs to be</li>
<li>Clearly specify what the default values are, what format values are in, and what the property actually does</li>
<li>Ideally, use a system that keeps the documentation for the property with the property in code.  It might stay in sync then.</li>
<li>If there are conventions, follow them.  This applies to all aspects: source of configuration, format, property names, and values.</li>
</ol>
<h2 id="wrapping-up">Wrapping Up</h2>
<p>We haven&rsquo;t even gotten into the debate about the right configuration file language!</p>
<p>In a future post, I want to go over how these thoughts have affected how I design software, and the configuration for it, but this post is quite long enough already so I will wait for another time.</p>
]]></content:encoded></item><item><title>Multiple errors in an OTEL Span</title><link>https://andydote.co.uk/2024/07/20/otel-errors/</link><pubDate>Sat, 20 Jul 2024 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2024/07/20/otel-errors/</guid><description>A question at work came up recently about how to handle multiple errors in a single span. My reaction is that having multiple errors in a span is a design smell, but I had no particular data or spec to back this up, just a gut feeling. I&amp;rsquo;ve since thought about this more and think that in general, you should only have one error per span, but there are circumstances where multiple indeed makes sense.</description><content:encoded><![CDATA[<p>A question at work came up recently about how to handle multiple errors in a single span.  My reaction is that having multiple errors in a span is a design smell, but I had no particular data or spec to back this up, just a gut feeling.  I&rsquo;ve since thought about this more and think that in general, you should only have one error per span, but there are circumstances where multiple indeed makes sense.  So, let&rsquo;s dig into them.</p>
<h2 id="can-i-have-multiple-errors-in-a-span">Can I have multiple errors in a Span?</h2>
<p>Yes!  An error is stored as an <code>event</code> attached to the <code>span</code>, so calling <code>span.recordError(err)</code> can be called multiple times.  However, a span can only have one status: either <code>Unset</code>, <code>Ok</code>, or <code>Error</code>, so while many errors can be recorded, the status of the span can only be set to one value.</p>
<h2 id="multiple-unrelated-errors">Multiple unrelated errors</h2>
<p>The problem with wanting to store multiple errors in one trace is that while you can have multiple error events, if you are also using the span&rsquo;s attributes for the error details (i.e. setting <code>err.message</code> and <code>err.details</code> etc.) then whichever was your last error will overwrite previous values.</p>
<p>One solution offered is to combine all errors into one, and then record that in the attributes.  This feels like a bad idea to me due to how you consume the errors in your OTEL service of choice; generally, you filter by attributes without any kind of free text search or, at best, prefix matching.</p>
<p>This, however, means that you lose a lot of filtering ability.  Rather than being able to do direct matching on the <code>err.message</code> attribute, you need to do wildcard searching, which is slower, and some providers don&rsquo;t even support it.</p>
<p>Furthermore, you lose the ability to group by error type; you can no longer write <code>group by err.message</code> or <code>group by err.type</code> as they all have the same type (<code>composite</code>), or differing messages (especially if the order of the grouped errors is not deterministic.)  You also loose out on being able to track how often a specific kind of error is occurring, making alerting on changes in error rates much harder to implement.</p>
<p>For these reasons, I would recommend refactoring your code to have a span per operation (or function, whichever provides the granularity you need), such that the main method emits a single span with several child spans, which each can have their own error details, and the parent span can then contain an error, and the overall status of the operation.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">handleMessage</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">m</span> <span style="color:#a6e22e">Message</span>) <span style="color:#66d9ef">error</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">span</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">tr</span>.<span style="color:#a6e22e">StartSpan</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;handle_message&#34;</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">End</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">oneSuccess</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">childOperationOne</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">m</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">twoSuccess</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">childOperationTwo</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">m</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">threeSuccess</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">childOperationThree</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">m</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">childOperationFour</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">m</span>) <span style="color:#75715e">//optional
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">oneSuccess</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">twoSuccess</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">threeSuccess</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">SetStatus</span>(<span style="color:#a6e22e">codes</span>.<span style="color:#a6e22e">Ok</span>)
</span></span><span style="display:flex;"><span>  } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">SetStatus</span>(<span style="color:#a6e22e">codes</span>.<span style="color:#a6e22e">Error</span>, <span style="color:#e6db74">&#34;mandatory operations failed&#34;</span>)
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="multiple-related-errors">Multiple related errors</h2>
<p>A good use case for storing multiple errors is when the operation can emit multiple of the same error before succeeding.  For example, an HTTP request retry middleware might emit an error for each attempt it makes but only set the span status to error if there wasn&rsquo;t a successful call after several tries.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">Retry</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">req</span> <span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">Request</span>) (<span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">Response</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">span</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">tr</span>.<span style="color:#a6e22e">StartSpan</span>(<span style="color:#e6db74">&#34;retry&#34;</span>, <span style="color:#a6e22e">ctx</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">End</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">maxRetries</span> <span style="color:#f92672">:=</span> <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">SetAttributes</span>(<span style="color:#a6e22e">attribute</span>.<span style="color:#a6e22e">Int</span>(<span style="color:#e6db74">&#34;retries.max&#34;</span>, <span style="color:#a6e22e">maxRetries</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">maxRetries</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">SetAttributes</span>(<span style="color:#a6e22e">attribute</span>.<span style="color:#a6e22e">Int</span>(<span style="color:#e6db74">&#34;retries.current&#34;</span>, <span style="color:#a6e22e">i</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">res</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">client</span>.<span style="color:#a6e22e">Do</span>(<span style="color:#a6e22e">req</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">==</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">SetStatus</span>(<span style="color:#a6e22e">codes</span>.<span style="color:#a6e22e">Ok</span>, <span style="color:#e6db74">&#34;&#34;</span>)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">res</span>, <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">s</span>.<span style="color:#a6e22e">RecordError</span>(<span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">backOffSleep</span>(<span style="color:#a6e22e">i</span>)
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">retryError</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Errorf</span>(<span style="color:#e6db74">&#34;failed after %v tries&#34;</span>, <span style="color:#a6e22e">maxRetries</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">SetStatus</span>(<span style="color:#a6e22e">codes</span>.<span style="color:#a6e22e">Error</span>, <span style="color:#a6e22e">retryError</span>.<span style="color:#a6e22e">Error</span>())
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">retryError</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="tracing-providers">Tracing Providers</h2>
<p>A lot of how you deal with this is still going to come down to which tracing provider/software you use to actually ingest your traces.  While OpenTelemetry has a specification of the protocol and fields, it doesn&rsquo;t specify how a UI has to render that information, so it is possible that you have to adjust your usage to match your provider.</p>
<p>or example, if there are many child operations, then a span per operation with its own possibility of error would make sense; the parent span could then decide based on the child operations whether the whole operation was successful or not.  You could also add attributes such as <code>operation_count</code>, <code>operation_failures</code>, etc.</p>
<h2 id="next-steps">Next Steps</h2>
<p>For the codebase in question, based on what little I know of it, I think adding a few more Spans around the problem areas is the right thing to do;  but depending on how many places this occurs, it could be more hassle than its worth.</p>
<p>I&rsquo;d stick with the same approach for adding tracing to a codebase: add it where it hurts, as that&rsquo;s where you&rsquo;ll see the most value.</p>
]]></content:encoded></item><item><title>Hot Reload for ServerSide Rendering</title><link>https://andydote.co.uk/2023/11/15/hot-reload-for-serverside-rendering/</link><pubDate>Wed, 15 Nov 2023 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2023/11/15/hot-reload-for-serverside-rendering/</guid><description>In one of my too many side projects, I am using htmx and go templates to render a somewhat complicated web UI. I much prefer using htmx for this kind of thing rather than react, as react brings in so much more additional complexity than I need or want. However, there is one thing I miss from the React ecosystem, and that is hot reload.
Being able to save a file in my editor and see the changes instantly in a web browser is an amazing developer experience, and I want to recreate that for htmx.</description><content:encoded><![CDATA[<p>In one of my too many side projects, I am using <a href="https://htmx.org/">htmx</a> and go templates to render a somewhat complicated web UI.  I much prefer using htmx for this kind of thing rather than react, as react brings in so much more additional complexity than I need or want.  However, there is one thing I miss from the React ecosystem, and that is hot reload.</p>
<p>Being able to save a file in my editor and see the changes instantly in a web browser is an amazing developer experience, and I want to recreate that for htmx.  I realised the steps to build my own hot reload were actually pretty small.</p>
<p>On the server side:</p>
<ul>
<li>generate a guid on startup</li>
<li>expose this to the client somehow</li>
</ul>
<p>On the client side:</p>
<ul>
<li>fetch the guid</li>
<li>if the guid doesn&rsquo;t match what we have seen before, refresh the page</li>
</ul>
<p>Despite my preference for HTMX and html/template in Go, neither the Client nor Server implementations a framework specific.  The server utilises <a href="https://gofiber.io/">Fiber</a> as its host, but it is not a hard requirement.</p>
<h2 id="the-client">The Client</h2>
<p>I decided to use a websocket for the transport, as if I decide later to make the server notify the client of changes also.  For the client side, I have a single script that I include in the html template, which connects a websocket, and handles all messages received.  It also handles reconnection if the server disconnects, along with a simple backoff mechanism.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>(<span style="color:#66d9ef">function</span> () {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">lastUuid</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">timeout</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">resetBackoff</span> <span style="color:#f92672">=</span> () =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">timeout</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1000</span>;
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">backOff</span> <span style="color:#f92672">=</span> () =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">timeout</span> <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">10</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">1000</span>) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">timeout</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">timeout</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">2</span>;
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">hotReloadUrl</span> <span style="color:#f92672">=</span> () =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">hostAndPort</span> <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">location</span>.<span style="color:#a6e22e">hostname</span> <span style="color:#f92672">+</span> (<span style="color:#a6e22e">location</span>.<span style="color:#a6e22e">port</span> <span style="color:#f92672">?</span> <span style="color:#e6db74">&#34;:&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">location</span>.<span style="color:#a6e22e">port</span> <span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">location</span>.<span style="color:#a6e22e">protocol</span> <span style="color:#f92672">===</span> <span style="color:#e6db74">&#34;https:&#34;</span>) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;wss://&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">hostAndPort</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;/ws/hotreload&#34;</span>;
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">else</span> <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">location</span>.<span style="color:#a6e22e">protocol</span> <span style="color:#f92672">===</span> <span style="color:#e6db74">&#34;http:&#34;</span>) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;ws://&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">hostAndPort</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;/ws/hotreload&#34;</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">connectHotReload</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">socket</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">WebSocket</span>(<span style="color:#a6e22e">hotReloadUrl</span>());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">socket</span>.<span style="color:#a6e22e">onmessage</span> <span style="color:#f92672">=</span> (<span style="color:#a6e22e">event</span>) =&gt; {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">lastUuid</span> <span style="color:#f92672">===</span> <span style="color:#e6db74">&#34;&#34;</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">lastUuid</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">event</span>.<span style="color:#a6e22e">data</span>;
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">lastUuid</span> <span style="color:#f92672">!==</span> <span style="color:#a6e22e">event</span>.<span style="color:#a6e22e">data</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">&#34;[Hot Reloader] Server Changed, reloading&#34;</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">location</span>.<span style="color:#a6e22e">reload</span>();
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">socket</span>.<span style="color:#a6e22e">onopen</span> <span style="color:#f92672">=</span> () =&gt; {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">resetBackoff</span>();
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">socket</span>.<span style="color:#a6e22e">send</span>(<span style="color:#e6db74">&#34;Hello&#34;</span>);
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">socket</span>.<span style="color:#a6e22e">onclose</span> <span style="color:#f92672">=</span> () =&gt; {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">timeoutId</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">setTimeout</span>(<span style="color:#66d9ef">function</span> () {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">clearTimeout</span>(<span style="color:#a6e22e">timeoutId</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">backOff</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">connectHotReload</span>();
</span></span><span style="display:flex;"><span>      }, <span style="color:#a6e22e">timeout</span>);
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">resetBackoff</span>();
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">connectHotReload</span>();
</span></span><span style="display:flex;"><span>})();
</span></span></code></pre></div><p>Note this is a pretty dumb hot reload - it just refreshes the current page.</p>
<h2 id="the-server">The Server</h2>
<p>The entire implementation is about 20 lines of go, utilising the <code>websocket</code> package for <code>fiber</code>, my web server framework of choice.  There is not a lot to it; just create a UUID, and send that value to any client which connects to the websocket, and sends any message to us.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#f92672">import</span> (
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;github.com/gofiber/contrib/websocket&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;github.com/gofiber/fiber/v2&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;github.com/google/uuid&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">WithHotReload</span>(<span style="color:#a6e22e">app</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">fiber</span>.<span style="color:#a6e22e">App</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id</span> <span style="color:#f92672">:=</span> []byte(<span style="color:#a6e22e">uuid</span>.<span style="color:#a6e22e">New</span>().<span style="color:#a6e22e">String</span>())
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">app</span>.<span style="color:#a6e22e">Use</span>(<span style="color:#e6db74">&#34;/ws&#34;</span>, <span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">c</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">fiber</span>.<span style="color:#a6e22e">Ctx</span>) <span style="color:#66d9ef">error</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">websocket</span>.<span style="color:#a6e22e">IsWebSocketUpgrade</span>(<span style="color:#a6e22e">c</span>) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">Next</span>()
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">fiber</span>.<span style="color:#a6e22e">ErrUpgradeRequired</span>
</span></span><span style="display:flex;"><span>  })
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">app</span>.<span style="color:#a6e22e">Get</span>(<span style="color:#e6db74">&#34;/ws/hotreload&#34;</span>, <span style="color:#a6e22e">websocket</span>.<span style="color:#a6e22e">New</span>(<span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">c</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">websocket</span>.<span style="color:#a6e22e">Conn</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">ReadMessage</span>(); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">break</span>
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">WriteMessage</span>(<span style="color:#a6e22e">websocket</span>.<span style="color:#a6e22e">TextMessage</span>, <span style="color:#a6e22e">id</span>); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">break</span>
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="how-it-works">How it works</h2>
<p>I use the <a href="https://github.com/cortesi/modd/">modd</a> tool to restart my go applications when I am developing them: any time I save a file, the app restarts.</p>
<p>When the app restarts, all websocket connections are aborted.  The client then tries to reconnect, and when it does, it receives a new UUID from the server, causing the entire page to refresh.  As all my apps are serverside rendered, there is usually little, if any, state to keep, so a full page refresh is fine for my development needs.</p>
<p>In this implementation, the socket is not needed; it would be just as easy to poll an API every x seconds to see if the UUID has changed, but having the client react to the server breaking the connection on restart seems better; there is less random HTTP noise in the network tab too.</p>
<h2 id="future-modifications">Future modifications</h2>
<p>I think I could make htmx do the hard work of switching out the page dom when the socket indicates the page has changed, and while that would be cool, it does mean that the client part would become htmx specific, so I probably won&rsquo;t do this.</p>
]]></content:encoded></item><item><title>Tracing: structured logging, but better in every way</title><link>https://andydote.co.uk/2023/09/19/tracing-is-better/</link><pubDate>Tue, 19 Sep 2023 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2023/09/19/tracing-is-better/</guid><description>It is no secret that I am not a fan of logs; I&amp;rsquo;ve baited (rapala in work lingo. Rapala is a Finnish brand of fishing lure, and used to mean baiting in this context) discussion in our work chat with things like:
If you&amp;rsquo;re writing log statements, you&amp;rsquo;re doing it wrong.
This is a pretty incendiary statement, and while there has been some good discussion after, I figured it was time to write down why I think logs are bad, why tracing should be used instead, and how we get from one to the other.</description><content:encoded><![CDATA[<p>It is no secret that I am not a fan of logs; I&rsquo;ve baited (<code>rapala</code> in work lingo.  Rapala is a Finnish brand of fishing lure, and used to mean baiting in this context) discussion in our work chat with things like:</p>
<blockquote>
<p>If you&rsquo;re writing log statements, you&rsquo;re doing it wrong.</p>
</blockquote>
<p>This is a pretty incendiary statement, and while there has been some good discussion after, I figured it was time to write down why I think logs are bad, why tracing should be used instead, and how we get from one to the other.</p>
<p>Hopefully, with less clickbait.  Step 3 will shock you, though.</p>
<h2 id="logs-vs-traces">Logs vs Traces</h2>
<p>First, lets breakdown what I see as the key differences between logging and tracing code.  If you want the practical example and want to skip this wall of text, <a href="#evolving-logs">click here</a>.  There is also a short <a href="#questions--answers">Question and Answer</a> at the end.</p>
<h3 id="log-levels">Log Levels</h3>
<p>Log Levels are meaningless.  Is a log line <code>debug</code>, <code>info</code>, <code>warning</code>, <code>error</code>, <code>fatal</code>, or some other shade in between?</p>
<p>The only time I have seen this well managed was when we had 3 descriptions:</p>
<ul>
<li>Info (everything)</li>
<li>Create A Task for Later (e.g. this can wait for working hours)</li>
<li>Wake Someone Up (this is on fire).</li>
</ul>
<p>However, this has issues; a timeout once is &ldquo;for later&rdquo; or just <code>info</code>, but many timeouts might be &ldquo;wake up&rdquo;, how do you encode that logic somewhere?</p>
<p>There is no equivalent of this in a trace, so there&rsquo;s one less thing to worry about.</p>
<h3 id="messages">Messages</h3>
<p>Something like <code>found ${count} users in the cache</code> looks like a good log message.  It is clear and has the information you care about.  However, when you come to querying your log aggregation system, you need to do a free-text search on a substring of the message or use a wildcard search.  Both of these operations are slow, and worse still cannot help you with the negative version of the question &ldquo;find me operations where the cache wasn&rsquo;t checked&rdquo;.</p>
<p>Assuming structured logs are being used, we can at least add the <code>count</code> as a property to the log message so it can now be filtered on by the log aggregator.  At which point, why do you need the log message at all?  Why not just have <code>log({ users_in_cache: count })</code>?</p>
<p>The logging libraries also put more importance on the message than the properties by having it be the first (and only required) argument to the logging function.  From a querying and analysis perspective, this is wrong:  messages force you into free text searching and reduce the likelihood of fast queries on attributes.</p>
<p>Given this logline:</p>
<pre tabindex="0"><code>logger.info(&#34;found the user in the cache&#34;, userId);
</code></pre><p>You could reconstruct this as a statement that can be filtered on:</p>
<pre tabindex="0"><code>span.addAttributes({
  user_in_cache: true,
  user_id: userId,
})
</code></pre><h3 id="mixed-outputs--semantics">Mixed Outputs / Semantics</h3>
<p>Nowadays, people configure their HTTP server to write logs to <code>stdout</code> rather than to a log file.  This makes a great deal of sense, as now a separate piece of software can tail the logs and send them off to the aggregator.  Your application&rsquo;s output, however, will likely end up with mixed plaintext and structured logs, mostly down to libraries and frameworks doing their own thing with logging, which is probably not the same as what you are doing (or other libraries are doing.)</p>
<p>The second problem with writing logs to <code>stdout</code> is that it mixes the semantics of log lines with console output.  While both log messages and console output are (probably) just text, they do have different purposes.  A piece of feedback might be &ldquo;Server listening on port 3000.  Click here to open the browser&rdquo;.  This is useful to a local user running the app but isn&rsquo;t valuable in your logs.  Not to mention, its plaintext output on the console, rather than structured, so now your log tailer needs to figure out what to do with it.</p>
<p>With OpenTelemetry, you instead configure an <code>exporter</code> to handle all your traces (and logs and metrics, if you desire.)  This is typically sent as OTLP format either directly to a vendor or to an OTEL Collector instance, which can add/remove/modify data and send it to one or multiple places.</p>
<p>Now you are free to write whatever feedback you want to <code>stdout</code>.</p>
<h3 id="relationships">Relationships</h3>
<p>Loglines don&rsquo;t have a causal relationships.  At best, structured logs might have some kind of request identifier (such as <code>requestID</code> or <code>correlationID</code>) for all lines written during a request.  This allows you to find all the log lines for a given ID, but the log lines themselves don&rsquo;t have a fixed order.  Ordering in structured logging relies on the timestamp field, but this is limited to the accuracy and resolution of the time source.  It means that it is possible to get lines appearing at the same time when they happened at different times.</p>
<p>Traces come with automatic parent-child relationships, allowing us to see not only all spans in a single request, but what caused each span, and (as we&rsquo;ll get to in the next point) when they happened.</p>
<p>Tracing also takes these relationships another step further but having a standard set of formats to pass trace and span IDs along to other services, embedded in HTTP headers, message queue metadata, or other locations.  Assuming all your other services send their traces to the same system, you can start to visualise who calls your service and what the effects are of you calling other services.</p>
<p>Imagine opening a trace from your service and discovering another team in a downstream service has started tracing their stuff, and you suddenly can see even more information about the request.  You didn&rsquo;t even do anything!  You notice that the way your service is structured causes a lot of load on the downstream, and start a conversation to see if there is a way to make it faster/better.</p>
<h3 id="timings">Timings</h3>
<p>The only timing data you get on log lines automatically is the <code>timestamp</code> of when the log line was written.  When you want to see how long an operation took, you must start a timer, and then stop the timer, and log the elapsed duration yourself.  As this is a manual process, it is often not done, and when it is done, it tends to have inconsistencies across the application, namely timing source (and thus resolution), property name, and format.  Is it <code>elapsed</code>, <code>elapsed_ms</code>, <code>duration</code>, or <code>length</code>?  does it contain a number of seconds, milliseconds, nanoseconds, or a timestamp format?</p>
<p>By comparison, traces come with <code>startTime</code>, <code>finishTime</code>, and <code>duration</code> attributes, which are not only guaranteed to be there but are set from the same timing source and are always written in the same format.</p>
<p>Combine this with the <a href="#relationships">relationship</a> attributes, and you can now render timing graphs, allowing for easy visualisation of how long each part of a process takes, what can be parallelised, and what parts depend on other parts.</p>
<p>For example, this is a graph showing <a href="/2023/07/06/observability-driven-ci/">how long a CI job took to run</a>, showing all the different steps, their durations, and child steps:</p>
<p><img loading="lazy" src="trace-build.png" alt="a graph of a single build showing each task as a horizontal box denoting start and durations"  />
</p>
<h3 id="querying">Querying</h3>
<p>Querying can have wildly different performance characteristics depending on which log aggregation service you are using.  What unifies all these systems is their slowness, which is mostly down to vast amounts of data which needs indexing so that it can be free text searched.  Filtering logs by their structured properties is however pretty quick (usually.)</p>
<p>Where querying falls down is trying to find trends in data, and trying to find answers to negative queries.  For example, how would you search for &ldquo;all requests to x endpoint, where users were not found in the cache&rdquo;?  This requires you to group the logs by request ID, then find an entry with a particular url path, then see if it is missing a log line.  The same query in a tracing system would be <code>where path = &quot;/some/api&quot; &amp;&amp; !user_in_cache</code>, as the tracing system is already aware of all the spans in a trace, and does the grouping automagically.</p>
<p>Finally, visualising missing data is hard.  Take this small example; it is 4 parallel requests to a system, and one of them is missing a log line.  Which line is missing?</p>
<table>
<thead>
<tr>
<th>Timestamp</th>
<th>UserID</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<tr>
<td>12:51:27</td>
<td>3fcce385be9e</td>
<td>fetched 3rd party preferences</td>
</tr>
<tr>
<td>12:51:27</td>
<td>3fcce385be9e</td>
<td>found user in cache</td>
</tr>
<tr>
<td>12:51:27</td>
<td>915d273db25c</td>
<td>fetched 3rd party preferences</td>
</tr>
<tr>
<td>12:51:27</td>
<td>3fcce385be9e</td>
<td>saved successfully</td>
</tr>
<tr>
<td>12:51:27</td>
<td>8507d369d11c</td>
<td>fetched 3rd party preferences</td>
</tr>
<tr>
<td>12:51:27</td>
<td>c4e71b4a29f2</td>
<td>fetched 3rd party preferences</td>
</tr>
<tr>
<td>12:51:27</td>
<td>915d273db25c</td>
<td>saved successfully</td>
</tr>
<tr>
<td>12:51:27</td>
<td>c4e71b4a29f2</td>
<td>found user in cache</td>
</tr>
<tr>
<td>12:51:27</td>
<td>c4e71b4a29f2</td>
<td>saved successfully</td>
</tr>
<tr>
<td>12:51:27</td>
<td>8507d369d11c</td>
<td>found user in cache</td>
</tr>
<tr>
<td>12:51:27</td>
<td>8507d369d11c</td>
<td>saved successfully</td>
</tr>
</tbody>
</table>
<p>Is it easier to see the one that is different now?</p>
<table>
<thead>
<tr>
<th>Timestamp</th>
<th>UserID</th>
<th>Fetched</th>
<th>In Cache</th>
<th>Saved</th>
</tr>
</thead>
<tbody>
<tr>
<td>12:51:27</td>
<td>3fcce385be9e</td>
<td>true</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>12:51:27</td>
<td>915d273db25c</td>
<td>true</td>
<td>false</td>
<td>true</td>
</tr>
<tr>
<td>12:51:27</td>
<td>8507d369d11c</td>
<td>true</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>12:51:27</td>
<td>c4e71b4a29f2</td>
<td>true</td>
<td>true</td>
<td>true</td>
</tr>
</tbody>
</table>
<p>Not only is it easy to see at a glance that <code>915d273db25c</code> didn&rsquo;t find the user in the cache, but also how much less space this takes up (both visually and in terms of storage.)</p>
<p>We can also then use this to query further: show me all traces where <code>in_cache != true</code>, and see what&rsquo;s different about them.</p>
<h2 id="evolving-logs">Evolving logs</h2>
<p>So, with all that being said, let&rsquo;s look at a practical example of how to go about tracing an existing system and what that looks like.</p>
<p>Ripping all the log statements in an application in one go is not a feasible strategy, especially on a large codebase.  However, we can use logs as a decent starting place and evolve our system to something better.  Namely, to OpenTelemetry Tracing.</p>
<p>We&rsquo;ll start off with a real pair of functions from one of the codebases I work on.  Lots of information changed to protect the <del>guilty</del> innocent.  This is run as part of an api call to publish a container, but this part has no web specific code.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">PrepareContainer</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">container</span> <span style="color:#a6e22e">ContainerContext</span>, <span style="color:#a6e22e">locales</span> []<span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">dryRun</span> <span style="color:#66d9ef">bool</span>, <span style="color:#a6e22e">allLocalesRequired</span> <span style="color:#66d9ef">bool</span>) (<span style="color:#f92672">*</span><span style="color:#a6e22e">StatusResult</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">logger</span>.<span style="color:#a6e22e">Info</span>(<span style="color:#e6db74">`Filling home page template`</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">homePage</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">RenderPage</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">home</span>, <span style="color:#a6e22e">container</span>, <span style="color:#a6e22e">locales</span>, <span style="color:#a6e22e">allLocalesRequired</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">templateIds</span> <span style="color:#f92672">:=</span> []<span style="color:#66d9ef">string</span>{<span style="color:#a6e22e">homePage</span>.<span style="color:#a6e22e">ID</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">container</span>.<span style="color:#a6e22e">PageSlugs</span>.<span style="color:#a6e22e">FAQ</span> <span style="color:#f92672">!=</span> <span style="color:#e6db74">&#34;&#34;</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">faqPage</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">RenderPage</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">faq</span>, <span style="color:#a6e22e">container</span>, <span style="color:#a6e22e">locales</span>, <span style="color:#a6e22e">allLocalesRequired</span>)
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">templateIds</span> = append(<span style="color:#a6e22e">templateIds</span>, <span style="color:#a6e22e">faqPage</span>.<span style="color:#a6e22e">ID</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">dryRun</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">StatusResult</span>{<span style="color:#a6e22e">Status</span>: <span style="color:#a6e22e">StatusDryRun</span>}, <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">logger</span>.<span style="color:#a6e22e">Info</span>(<span style="color:#e6db74">`Marking page template(s) for usage`</span>, <span style="color:#e6db74">&#34;template_ids&#34;</span>, <span style="color:#a6e22e">templateIds</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">MarkReadyForUsage</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">container</span>, <span style="color:#a6e22e">templateIds</span>); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">StatusResult</span>{<span style="color:#a6e22e">Status</span>: <span style="color:#a6e22e">StatusComplete</span>}, <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">RenderPage</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">source</span> <span style="color:#a6e22e">Source</span>, <span style="color:#a6e22e">container</span> <span style="color:#a6e22e">ContainerContext</span>, <span style="color:#a6e22e">locales</span> []<span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">allLocalesRequired</span> <span style="color:#66d9ef">bool</span>) (<span style="color:#66d9ef">string</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">logger</span>.<span style="color:#a6e22e">Info</span>(<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Sprintf</span>(<span style="color:#e6db74">`Filling %s page template`</span>, <span style="color:#a6e22e">source</span>.<span style="color:#a6e22e">Name</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">template</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">FetchAndFillTemplate</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">source</span>, <span style="color:#a6e22e">container</span>, <span style="color:#a6e22e">locales</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">page</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">ConfigureFromTemplate</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">container</span>, <span style="color:#a6e22e">template</span>, <span style="color:#a6e22e">locales</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> len(<span style="color:#a6e22e">page</span>.<span style="color:#a6e22e">Locales</span>) <span style="color:#f92672">!=</span> len(<span style="color:#a6e22e">locales</span>) {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">message</span> = <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Sprintf</span>(<span style="color:#e6db74">`Failed to render %s page template for some locales`</span>, <span style="color:#a6e22e">source</span>.<span style="color:#a6e22e">Name</span>)
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">allLocalesRequired</span> {
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Errorf</span>(<span style="color:#a6e22e">message</span>)
</span></span><span style="display:flex;"><span>		} <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">logger</span>.<span style="color:#a6e22e">Warn</span>(<span style="color:#a6e22e">message</span>, <span style="color:#e6db74">&#34;locales&#34;</span>, <span style="color:#a6e22e">locales</span>, <span style="color:#e6db74">&#34;pages&#34;</span>, <span style="color:#a6e22e">page</span>.<span style="color:#a6e22e">Locales</span>)
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">page</span>, <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>
<h3 id="step-1-add-a-tracer">Step 1: Add a Tracer</h3>
<p>The first step is to import a tracer and start a span for each method.  As is somewhat common in Go, the methods already have a <code>ctx</code> parameter, so we just need to wrap it with the <code>tr.Start</code> call.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">tr</span> = <span style="color:#a6e22e">otel</span>.<span style="color:#a6e22e">Tracer</span>(<span style="color:#e6db74">&#34;container_api&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">PrepareContainer</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">container</span> <span style="color:#a6e22e">ContainerContext</span>, <span style="color:#a6e22e">locales</span> []<span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">dryRun</span> <span style="color:#66d9ef">bool</span>, <span style="color:#a6e22e">allLocalesRequired</span> <span style="color:#66d9ef">bool</span>) (<span style="color:#f92672">*</span><span style="color:#a6e22e">StatusResult</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">span</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">tr</span>.<span style="color:#a6e22e">Start</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;prepare_container&#34;</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">End</span>()</span></span></code></pre></div>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">RenderPage</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">source</span> <span style="color:#a6e22e">Source</span>, <span style="color:#a6e22e">container</span> <span style="color:#a6e22e">ContainerContext</span>, <span style="color:#a6e22e">locales</span> []<span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">allLocalesRequired</span> <span style="color:#66d9ef">bool</span>) (<span style="color:#66d9ef">string</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">span</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">tr</span>.<span style="color:#a6e22e">Start</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;render_page&#34;</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">End</span>()</span></span></code></pre></div>
<p>Just this step alone already gives us value over logging:  As mentioned above, the spans automatically come with <a href="#timings">timing data</a> and <a href="#relationships">parent-child relationships</a>.</p>
<p><img loading="lazy" src="trace-add-spans.png" alt="small trace burndown graph, showing the methods from the previous code example"  />
</p>
<h3 id="step-2-wrap-the-errors">Step 2: Wrap the Errors</h3>
<p>OTEL Spans support a <code>status</code> attribute, along with a status message which is used when there is a non-success status.  By creating a small wrapper function like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">Error</span>(<span style="color:#a6e22e">s</span> <span style="color:#a6e22e">trace</span>.<span style="color:#a6e22e">Span</span>, <span style="color:#a6e22e">err</span> <span style="color:#66d9ef">error</span>) <span style="color:#66d9ef">error</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">s</span>.<span style="color:#a6e22e">RecordError</span>(<span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">s</span>.<span style="color:#a6e22e">SetStatus</span>(<span style="color:#a6e22e">codes</span>.<span style="color:#a6e22e">Error</span>, <span style="color:#a6e22e">err</span>.<span style="color:#a6e22e">Error</span>())
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We can wrap all error returns so that we capture the error itself (<code>SetStatus</code>) and there is an error event recorded on the trace too (<code>RecordError</code>):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span>if err := MarkReadyForUsage(ctx, container, templateIds); err != nil {
</span></span><span style="display:flex;"><span><span style="color:#f92672">- return nil, err
</span></span></span><span style="display:flex;"><span><span style="color:#f92672"></span><span style="color:#a6e22e">+ return nil, tracing.Error(span, err)
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>}
</span></span></code></pre></div><h3 id="step-3-add-attributes-and-replace-messages">Step 3: Add Attributes and Replace Messages</h3>
<p>The next steps is to replace any <code>logger</code> messages with attributes by turning them into statements that can be filtered on.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span><span style="color:#f92672">- logger.Info(fmt.Sprintf(`Filling %s page template`, source.Name))
</span></span></span><span style="display:flex;"><span><span style="color:#f92672"></span><span style="color:#a6e22e">+ tracing.String(span, &#34;source_name&#34;, source.Name)
</span></span></span></code></pre></div><p>We also want to add attributes for any parameters we might want to filter on later.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;"><code class="language-go" data-lang="go"><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">span</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">tr</span>.<span style="color:#a6e22e">Start</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;prepare_container&#34;</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">End</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">StringSlice</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;locales&#34;</span>, <span style="color:#a6e22e">locales</span>)
</span></span><span style="display:flex; background-color:#3c3d38"><span>	<span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">Bool</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;dry_run&#34;</span>, <span style="color:#a6e22e">dryRun</span>)
</span></span><span style="display:flex; background-color:#3c3d38"><span>	<span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">Bool</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;locales_mandatory&#34;</span>, <span style="color:#a6e22e">allLocalesRequired</span>)
</span></span></code></pre></div>
<p>Finally , we can simplify a code block: there is no point in the <code>logger.Warning</code> call here, as we can have all the required information as filterable properties:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span><span style="color:#a6e22e">+ allLocalesRendered := len(page.Locales) == len(locales)
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ tracing.Bool(span, &#34;all_locales_rendered&#34;, allLocalesRendered)
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ tracing.StringSlice(span, &#34;locales_rendered&#34;, page.Locales)
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">- if len(page.Locales) != len(locales) {
</span></span></span><span style="display:flex;"><span><span style="color:#f92672"></span><span style="color:#a6e22e">+ if !allLocalesRendered &amp;&amp; allLocalesRequired {
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+   return nil, tracing.Errorf(`Failed to render %s page template for some locales`, source.Name)
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span><span style="color:#f92672">- const message = fmt.Sprintf(`Failed to render %s page template for some locales`, source.Name)
</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- if allLocalesRequired {
</span></span></span><span style="display:flex;"><span><span style="color:#f92672">-   return nil, tracing.Errorf(message)
</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- } else {
</span></span></span><span style="display:flex;"><span><span style="color:#f92672">-   logger.Warn(message, &#34;locales&#34;, locales, &#34;pages&#34;, page.Locales)
</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- }
</span></span></span><span style="display:flex;"><span><span style="color:#f92672"></span>}
</span></span></code></pre></div><h3 id="the-result">The Result</h3>
<p>The diff between the two functions shows that the tracing version is longer - by 9 lines.  However, the traced version contains so much more information than the logged version.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">tr</span> = <span style="color:#a6e22e">otel</span>.<span style="color:#a6e22e">Tracer</span>(<span style="color:#e6db74">&#34;container_api&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">PrepareContainer</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">container</span> <span style="color:#a6e22e">ContainerContext</span>, <span style="color:#a6e22e">locales</span> []<span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">dryRun</span> <span style="color:#66d9ef">bool</span>, <span style="color:#a6e22e">allLocalesRequired</span> <span style="color:#66d9ef">bool</span>) (<span style="color:#f92672">*</span><span style="color:#a6e22e">StatusResult</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">span</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">tr</span>.<span style="color:#a6e22e">Start</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;prepare_container&#34;</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">End</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">StringSlice</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;locales&#34;</span>, <span style="color:#a6e22e">locales</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">Bool</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;dry_run&#34;</span>, <span style="color:#a6e22e">dryRun</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">Bool</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;locales_mandatory&#34;</span>, <span style="color:#a6e22e">allLocalesRequired</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">homePage</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">RenderPage</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">home</span>, <span style="color:#a6e22e">container</span>, <span style="color:#a6e22e">locales</span>, <span style="color:#a6e22e">allLocalesRequired</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">Error</span>(<span style="color:#a6e22e">span</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">templateIds</span> <span style="color:#f92672">:=</span> []<span style="color:#66d9ef">string</span>{<span style="color:#a6e22e">homePage</span>.<span style="color:#a6e22e">ID</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">hasFaq</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">container</span>.<span style="color:#a6e22e">PageSlugs</span>.<span style="color:#a6e22e">FAQ</span> <span style="color:#f92672">!=</span> <span style="color:#e6db74">&#34;&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">Bool</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;has_faq&#34;</span>, <span style="color:#a6e22e">hasFaq</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">hasFaq</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">faqPage</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">RenderPage</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">faq</span>, <span style="color:#a6e22e">container</span>, <span style="color:#a6e22e">locales</span>, <span style="color:#a6e22e">allLocalesRequired</span>)
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">Error</span>(<span style="color:#a6e22e">span</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">templateIds</span> = append(<span style="color:#a6e22e">templateIds</span>, <span style="color:#a6e22e">faqPage</span>.<span style="color:#a6e22e">ID</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">StringSlice</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;template_ids&#34;</span>, <span style="color:#a6e22e">templateIds</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">dryRun</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">StatusResult</span>{<span style="color:#a6e22e">Status</span>: <span style="color:#a6e22e">StatusDryRun</span>}, <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">MarkReadyForUsage</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">container</span>, <span style="color:#a6e22e">templateIds</span>); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">Error</span>(<span style="color:#a6e22e">span</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">StatusResult</span>{<span style="color:#a6e22e">Status</span>: <span style="color:#a6e22e">StatusComplete</span>}, <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">RenderPage</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">source</span> <span style="color:#a6e22e">Source</span>, <span style="color:#a6e22e">container</span> <span style="color:#a6e22e">ContainerContext</span>, <span style="color:#a6e22e">locales</span> []<span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">allLocalesRequired</span> <span style="color:#66d9ef">bool</span>) (<span style="color:#66d9ef">string</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">span</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">tr</span>.<span style="color:#a6e22e">Start</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;render_page&#34;</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">End</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">String</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;source_name&#34;</span>, <span style="color:#a6e22e">source</span>.<span style="color:#a6e22e">Name</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">template</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">FetchAndFillTemplate</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">source</span>, <span style="color:#a6e22e">container</span>, <span style="color:#a6e22e">locales</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">Error</span>(<span style="color:#a6e22e">span</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">page</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">ConfigureFromTemplate</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">container</span>, <span style="color:#a6e22e">template</span>, <span style="color:#a6e22e">locales</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">Error</span>(<span style="color:#a6e22e">span</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">allLocalesRendered</span> <span style="color:#f92672">:=</span> len(<span style="color:#a6e22e">page</span>.<span style="color:#a6e22e">Locales</span>) <span style="color:#f92672">==</span> len(<span style="color:#a6e22e">locales</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">Bool</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;all_locales_rendered&#34;</span>, <span style="color:#a6e22e">allLocalesRendered</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">StringSlice</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;locales_rendered&#34;</span>, <span style="color:#a6e22e">page</span>.<span style="color:#a6e22e">Locales</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> !<span style="color:#a6e22e">allLocalesRendered</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">required</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">Errorf</span>(<span style="color:#e6db74">`Failed to render %s page template for some locales`</span>, <span style="color:#a6e22e">source</span>.<span style="color:#a6e22e">Name</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">page</span>, <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>
<p>If you wish to view the files as individual steps: <a href="example-api-0.go">initial</a>, <a href="example-api-1.go">step 1</a>, <a href="example-api-2.go">step 2</a>, <a href="example-api-3.go">step 3</a>, <a href="example-api-4.go">final</a></p>
<h2 id="questions--answers">Questions &amp; Answers</h2>
<p>Some questions I have seen come up when talking about doing this.</p>
<h3 id="how-do-i-use-this">How do I use this?</h3>
<p>If you&rsquo;re debugging some error, taking the span name from your UI, and searching the codebase is a good start.  Use the attributes named in code to search your UI for things that match/don&rsquo;t match.</p>
<p>Also, try <a href="/presentations/index.html?odd">Observability Driven Development</a>.  It involves using your trace data before, during, and after a change so you know if its actually behaving as you expect.</p>
<h3 id="what-do-you-recommend-to-view-traces">What do you recommend to view traces?</h3>
<p><a href="https://honeycomb.io">Honeycomb</a> is the best, no question.  <a href="https://lightstep.com">Lightstep</a> is a close second.</p>
<h3 id="i-think-this-is-ugly">I think this is ugly!</h3>
<p>That is not a question.  It is also a matter of opinion - I happen to think traced code looks better than logged code.  It also could be that it takes some getting used to when you first start seeing it!  Remember how unit testing felt weird to start with?</p>
<h3 id="i-need-a-log-message">I need a log message&hellip;</h3>
<p>I try to turn log messages into statements.  Like in the example above:</p>
<ul>
<li><code>found user in cache</code> =&gt; <code>user_in_cache: true</code></li>
<li><code>loading template ${name}</code> =&gt; <code>template_loading: true, template_name: name</code></li>
</ul>
<p>When I need to mark that code execution has gotten to a particular point in a method:</p>
<ul>
<li>add an attribute, like <code>initial_processing_complete: true</code></li>
<li>contemplate if the method should be split, and thus have its own span</li>
</ul>
<h3 id="i-have-a-loop-i-am-overwriting-attributes-on-each-iteration">I have a loop, I am overwriting attributes on each iteration</h3>
<p>Similar to above: either move the loop body into its own method, use a closure to create a new span in the loop, or don&rsquo;t have a span per iteration.</p>
<p>You can always add summary information after a loop:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">foos</span> <span style="color:#f92672">:=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bars</span> <span style="color:#f92672">:=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> <span style="color:#a6e22e">i</span>, <span style="color:#a6e22e">thing</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">things</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// ...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">thing</span>.<span style="color:#a6e22e">prop</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;foo&#34;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">foos</span><span style="color:#f92672">++</span>
</span></span><span style="display:flex;"><span>  } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">bars</span><span style="color:#f92672">++</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">SetAttribute</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;foos&#34;</span>, <span style="color:#a6e22e">foos</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">tracing</span>.<span style="color:#a6e22e">SetAttribute</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;bars&#34;</span>, <span style="color:#a6e22e">bars</span>)
</span></span></code></pre></div><h2 id="thanks">Thanks</h2>
<p>Thanks to <a href="https://fi.linkedin.com/in/aki-foudila-339222200">Aki</a> for some of the questions and some discussions which expanded a few of the sections here.</p>
<p>Thanks to <a href="https://www.tuomistolari.net/">Lari</a> for prompting this blog post initially!</p>
<p>Thanks to you, for making it to the end.</p>
]]></content:encoded></item><item><title>Architecture Testing</title><link>https://andydote.co.uk/2023/07/23/architecture-testing/</link><pubDate>Sun, 23 Jul 2023 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2023/07/23/architecture-testing/</guid><description>One of the many reasons given for using microservices rather than a mono repository is that it enforces boundaries between services/modules. However, there are ways to achieve strong boundaries between modules/services in one repository, using tools which are already available: test runners.
Given a repository with the following structure:
. ├── libraries │ ├── core │ ├── events │ └── ui ├── services │ ├── catalogue │ ├── billing │ └── shipping └── tools └── admin-cli There are a few rules we should enforce:</description><content:encoded><![CDATA[<p>One of the many reasons given for using microservices rather than a mono repository is that it enforces boundaries between services/modules.  However, there are ways to achieve strong boundaries between modules/services in one repository, using tools which are already available: test runners.</p>
<p>Given a repository with the following structure:</p>
<pre tabindex="0"><code>.
├── libraries
│   ├── core
│   ├── events
│   └── ui
├── services
│   ├── catalogue
│   ├── billing
│   └── shipping
└── tools
    └── admin-cli
</code></pre><p>There are a few rules we should enforce:</p>
<ul>
<li>Services cannot reference each other</li>
<li>tools cannot reference each other</li>
<li>Services cannot reference tools</li>
<li>Libraries can only reference other libraries</li>
<li>Libraries cannot have circular dependencies</li>
</ul>
<p>There are also the conventions that we want to enforce:</p>
<ul>
<li>Feature folders should be used, not <code>models</code>, <code>views</code> and <code>controllers</code></li>
<li>Specific libraries should not be used</li>
<li>all services should expose a <code>/api/stats</code> endpoint</li>
</ul>
<p>How to write these tests will vary greatly depending on what programming languages and tools you use, but I know for sure they can be written in Go, C#, and TypeScript.  Not only that, but the tests can be written in a different language than the applications; in this example, our applications are written in a mix of NodeJS and Go, and the architectural tests are written in Go.</p>
<h2 id="testing-for-a-convention">Testing for a Convention</h2>
<p>The convention we will test for is that we strongly prefer folder-by-feature over folder-by-type.</p>
<p>The test itself uses a couple of helper methods: <code>repositoryFolders</code> returns a slice of every folder recursively in the project, with information such as all child folders and all child files, along with names, paths, etc., populated.</p>
<p>The <code>hasLayers</code> function itself is just checking if the direct children of a folder contain &ldquo;models&rdquo;, &ldquo;views&rdquo; and &ldquo;controllers&rdquo; or &ldquo;models&rdquo;, &ldquo;views&rdquo; and &ldquo;presenters&rdquo;.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">TestFolderByFeature</span>(<span style="color:#a6e22e">t</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">testing</span>.<span style="color:#a6e22e">T</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">folders</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">repositoryFolders</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">folder</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">folders</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">hasLayers</span>(<span style="color:#a6e22e">folder</span>) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">assert</span>.<span style="color:#a6e22e">Failf</span>(<span style="color:#a6e22e">t</span>, <span style="color:#e6db74">&#34;found type folders, not slices&#34;</span>, <span style="color:#a6e22e">wrap80</span>(<span style="color:#e6db74">`
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">It looks like &#39;%s&#39; is using this folder structure, known as &#34;folder-by-type&#34;, which is discouraged:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">%s
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Instead, you should use folders-by-feature:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">%s
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">For more information, see this ADR: ./docs/arch/005-folder-layout.md
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">If this test failure is a false positive, please let us know, or you can either improve the test or add your folder path to the &#39;.architecture-ignore&#39; file.  Here is the fragment that can be added:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">%s
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      `</span>, <span style="color:#a6e22e">folder</span>.<span style="color:#a6e22e">Path</span>, <span style="color:#a6e22e">layers</span>(<span style="color:#a6e22e">folder</span>), <span style="color:#a6e22e">slices</span>(<span style="color:#a6e22e">folder</span>), <span style="color:#a6e22e">folderByTypeArchitectureIgnore</span>(<span style="color:#a6e22e">folder</span>)))
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The error message in this kind of test is very important; it needs to cover:</p>
<ul>
<li>What was wrong</li>
<li>Where the failure was (i.e. the path)</li>
<li>Why this is considered wrong (with links to more information if needed)</li>
<li>How to fix it</li>
<li>How to add an exception to the rules (if desired)</li>
<li>How to handle false positives</li>
</ul>
<p>For example, this is what the rendered output of the test above looks like, showing the folder that was detected to have folder-by-type, showing an example of how it should look, and linking to the <a href="/tags/adr/">adr</a>, which documents why this was chosen.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>It looks like &#39;services/catalogue/src&#39; is using this folder structure, known as
</span></span><span style="display:flex;"><span>&#34;folder-by-type&#34;, which is discouraged:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>services/catalogue/src
</span></span><span style="display:flex;"><span>├── controllers
</span></span><span style="display:flex;"><span>├── models
</span></span><span style="display:flex;"><span>└── views
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Instead, you should use folder-by-feature:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>services/catalogue/src
</span></span><span style="display:flex;"><span>├── details
</span></span><span style="display:flex;"><span>│   ├── controller.ts
</span></span><span style="display:flex;"><span>│   ├── model.ts
</span></span><span style="display:flex;"><span>│   └── view.ts
</span></span><span style="display:flex;"><span>├── indexing
</span></span><span style="display:flex;"><span>└── search
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>For more information, see this ADR: ./docs/arch/005-folder-layout.md
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>If this test failure is a false positive, please let us know, or you can either
</span></span><span style="display:flex;"><span>improve the test or add your folder path to the &#39;.architecture-ignore&#39; file.
</span></span><span style="display:flex;"><span>Here is the fragment that can be added:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>```toml
</span></span><span style="display:flex;"><span>[[services]]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[service.catalogue]
</span></span><span style="display:flex;"><span>allowFolderByType = true
</span></span><span style="display:flex;"><span>```.
</span></span></code></pre></div><p>There is also the text on how to skip a test if there is a good reason to or the test failure is a false negative.  Adding to the <code>.architecture-ignore</code> file notifies the core team about an addition, but <strong>does not block the PR</strong>, as teams are all trusted; we just want to verify if something is happening a lot or if there is some case the tests are not handling.</p>
<p>An example of a good reason for ignoring this test is when a team is taking ownership of a service and adding it to the repository: they want to pull its source in and make as few changes as possible until it is under their control; refactoring can then happen later.</p>
<h2 id="testing-a-project-rule">Testing a Project Rule</h2>
<p>Now let&rsquo;s look at how we verify that our services don&rsquo;t reference other services.  The test is similar to the previous one other than the <code>repositoryServices()</code> function returns a map of service names and Services.  The <code>Service</code> struct is an abstraction which allows us to handle both NodeJS projects and Go projects with the same test.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">TestServicesCannotReferenceOtherServices</span>(<span style="color:#a6e22e">t</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">testing</span>.<span style="color:#a6e22e">T</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">allServices</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">repositoryServices</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">service</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">allServices</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">reference</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">service</span>.<span style="color:#a6e22e">References</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">other</span>, <span style="color:#a6e22e">found</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">allServices</span>[<span style="color:#a6e22e">reference</span>.<span style="color:#a6e22e">Name</span>]; <span style="color:#a6e22e">found</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         <span style="color:#a6e22e">assert</span>.<span style="color:#a6e22e">Failf</span>(<span style="color:#a6e22e">t</span>, <span style="color:#e6db74">&#34;service references another service&#34;</span>, <span style="color:#a6e22e">wrap80</span>(<span style="color:#e6db74">`
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">It looks like the &#39;%s&#39; service is referencing the &#39;%s&#39; service.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">1.  Service Boundary
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Needing data from another service is often an indication of non-optimal service boundary, which could mean we need to refactor our design a bit.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">1.  Distributed Ball of Mud
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Having many service to service dependencies make all our services more tightly coupled, making refactoring and deployment harder.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Sometimes a service to service reference is fine however!  You can add your service to service definition to the &#39;.architecture-ignore&#39; file if this is the case.  Here is the fragment that can be added:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">%s
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">         `</span>, <span style="color:#a6e22e">service</span>.<span style="color:#a6e22e">Name</span>, <span style="color:#a6e22e">other</span>.<span style="color:#a6e22e">Name</span>, <span style="color:#a6e22e">serviceToServiceArchitectureIgnore</span>(<span style="color:#a6e22e">service</span>, <span style="color:#a6e22e">other</span>)))
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span></code></pre></div><p>The error message when rendered looks like this, again adding as much detail as we can along with how to add the exception if needed:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-md" data-lang="md"><span style="display:flex;"><span>It looks like the catalogue &#39;service&#39; is referencing the &#39;offers&#39; service.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Service to Service references are discouraged for two main reasons:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">1.</span>  Service Boundary
</span></span><span style="display:flex;"><span>Needing data from another service is often an indication of non-optimal service
</span></span><span style="display:flex;"><span>boundary, which could mean we need to refactor our design a bit.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">2.</span>  Distributed Ball of Mud
</span></span><span style="display:flex;"><span>Having many service to service dependencies make all our services more tightly
</span></span><span style="display:flex;"><span>coupled, making refactoring and deployment harder.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Sometimes a service to service reference is fine however!  You can add your
</span></span><span style="display:flex;"><span>service to service definition to the &#39;.architecture-ignore&#39; file if this is the
</span></span><span style="display:flex;"><span>case.  Here is the fragment that can be added:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>```toml
</span></span><span style="display:flex;"><span>[[services]]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[services.catalogue]
</span></span><span style="display:flex;"><span>references = [
</span></span><span style="display:flex;"><span>    &#34;offers&#34;
</span></span><span style="display:flex;"><span>]
</span></span><span style="display:flex;"><span>```.
</span></span></code></pre></div><h2 id="further-work">Further Work</h2>
<p>Using tests like this also allows you to build extra things on top of them; for migrating from one library to another, you can add tests that specify that the number of usages can only go down over time, never up.</p>
<p>You can also use <code>codeowners</code> (or equivalent) to keep an eye on what is being added to the <code>.architecture-ignore</code> file, allowing you to react to emerging patterns and either guide teams towards the pattern or away from it.</p>
<p>The key with this is that you trust your teams; this is all &ldquo;trust but verify&rdquo; with the ignore file.  You should (almost) never be blocking a team from working.</p>
]]></content:encoded></item><item><title>Observability Driven CI</title><link>https://andydote.co.uk/2023/07/06/observability-driven-ci/</link><pubDate>Thu, 06 Jul 2023 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2023/07/06/observability-driven-ci/</guid><description>Tracking where the time goes in your CI pipeline is an important step towards being able to make it go even faster. Up until somewhat recently, the only way of tracking how long tasks took in CI was either hoping people had wrapped all their commands in time ..., or by reading a timestamped build log and calculating the difference between numbers. Which isn&amp;rsquo;t great or fun, if we&amp;rsquo;re being honest.</description><content:encoded><![CDATA[<p>Tracking where the time goes in your CI pipeline is an important step towards being able to make it go even faster.  Up until somewhat recently, the only way of tracking how long tasks took in CI was either hoping people had wrapped all their commands in <code>time ...</code>, or by reading a timestamped build log and calculating the difference between numbers.  Which isn&rsquo;t great or fun, if we&rsquo;re being honest.</p>
<p>What if we could create graphs of what parts of the build took time?  Something like this?</p>
<p><img loading="lazy" src="trace-build.png" alt="a graph of a single build showing each task as a horizontal box denoting start and durations"  />
</p>
<p>Being someone who cares about build pipelines and speed, I decided to add OpenTelemetry to our builds, and see what information we could get.  It turns out that there is far more useful information available than just timings.  For example:</p>
<ul>
<li><strong>number of main builds</strong>; are we merging often? is this speeding up or slowing down?</li>
<li><strong>number commits merged to <code>main</code> at once</strong>; is our batch size going up? why?</li>
<li><strong>deployments per day</strong>; are we still moving fast?  Are people scared to <a href="/2022/11/02/deploy-doesnt-mean-release/">deploy</a> on Friday?  why?</li>
<li><strong>pass and failure ratios</strong>; are failures becoming more often? why?</li>
<li><strong>runtime of failed builds</strong>; failing builds should be fast, so we re-ordered steps so that likely failures are hit first</li>
<li><strong>what fails most often?</strong>; a test suite testing too much? flaky tests?  a dependency not being locally cached (and thus unavailable sometimes)?</li>
</ul>
<h2 id="terminology">Terminology</h2>
<p>The <a href="https://opentelemetry.io/docs/concepts/glossary/">OTEL</a> website has details on what all the terminology means, but for a brief summary:</p>
<ul>
<li>span: the basic units which make up a trace.  They can be parented to other spans and can represent the entire build, a logical grouping of operations, or a single operation.</li>
<li>trace: a collection of spans with one &ldquo;root span&rdquo; which has no parent.</li>
<li>attributes: key-value pairs attached to spans to provide more context.</li>
<li>[Otel Collector][otel-collector] - a service which accepts traces in a variety of formats and can forward them to other places.  Generally, you run one of these locally and all applications send to it, and it is configured to batch, enrich, and forward to a tracing service, such as <a href="https://honeycomb.io/">Honeycomb</a> or <a href="https://www.jaegertracing.io/">Jaeger</a></li>
</ul>
<h2 id="tracing-builds">Tracing Builds</h2>
<p>The first step when tracing builds is to start with the overall picture: one span for the entire build.  Once this is in place, you can move on to adding details, focusing your efforts on figuring out what is the most likely place to find speed improvements.</p>
<p>To do this, I use the <a href="https://github.com/Pondidum/Trace/">trace</a> tool, which is an opinionated CLI that creates OTEL traces for your build pipeline.  If you need more flexibility or don&rsquo;t like its opinions, you can either open a PR/Issue on Github, or there is the <a href="https://github.com/equinix-labs/otel-cli">otel-cli</a> which is much more low-level.</p>
<p>The <code>trace</code> command will send spans to <code>localhost:4317</code> by default.  By setting the <code>OTEL_EXPORTER_OTLP_ENDPOINT</code> environment variable, our traces will instead go to our local [OTEL Collector][otel-collector] instance, which is configured to send our traces elsewhere:</p>
<p>Install the <code>trace</code> tool:</p>


<div class="tab-panel">
    <div class="tab-nav">
    
        <button
          data-tab-item="Github Actions"
          data-tab-group="default"
          class="tab-nav-button btn active"
          onclick="switchTab('default','Github Actions')"
         >Github Actions</button>
    
        <button
          data-tab-item="bash"
          data-tab-group="default"
          class="tab-nav-button btn "
          onclick="switchTab('default','bash')"
         >bash</button>
    
    </div>
    <div class="tab-content">
        
        <div data-tab-item="Github Actions" data-tab-group="default" class="tab-item active">
            <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">env</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">OTEL_EXPORTER_OTLP_ENDPOINT</span>: <span style="color:#ae81ff">https://otel.internal.xyz:443</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">jobs</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">build</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">runs-on</span>: <span style="color:#ae81ff">ubuntu-latest</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">steps</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Setup Trace</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">uses</span>: <span style="color:#ae81ff">pondidum/trace@main</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">with</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">version</span>: <span style="color:#e6db74">&#34;0.0.9&#34;</span>
</span></span></code></pre></div>
        </div>
        
        <div data-tab-item="bash" data-tab-group="default" class="tab-item ">
            <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export OTEL_EXPORTER_OTLP_ENDPOINT<span style="color:#f92672">=</span>https://otel.internal.xyz:443
</span></span><span style="display:flex;"><span>version<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;0.0.9&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>curl -sSL <span style="color:#e6db74">&#34;https://github.com/Pondidum/trace/releases/download/</span><span style="color:#e6db74">${</span>version<span style="color:#e6db74">}</span><span style="color:#e6db74">/trace&#34;</span> -o /usr/bin/trace
</span></span><span style="display:flex;"><span>chmod +x /usr/bin/trace
</span></span></code></pre></div>
        </div>
        
    </div>
</div>
<p>Now we can start the trace; by default this will be marked as starting when the <code>trace start</code> command is run; we can change this with the <code>--when</code> flag, which is being fed the <code>created_at</code> field from Github so that our trace shows when the build was started.</p>


<div class="tab-panel">
    <div class="tab-nav">
    
        <button
          data-tab-item="Github Actions"
          data-tab-group="default"
          class="tab-nav-button btn active"
          onclick="switchTab('default','Github Actions')"
         >Github Actions</button>
    
        <button
          data-tab-item="bash"
          data-tab-group="default"
          class="tab-nav-button btn "
          onclick="switchTab('default','bash')"
         >bash</button>
    
    </div>
    <div class="tab-content">
        
        <div data-tab-item="Github Actions" data-tab-group="default" class="tab-item active">
            <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Start Trace</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">uses</span>: <span style="color:#ae81ff">pondidum/trace/start@main</span>
</span></span></code></pre></div>
        </div>
        
        <div data-tab-item="bash" data-tab-group="default" class="tab-item ">
            <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>json<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>curl -sSL <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --url <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>GITHUB_API_URL<span style="color:#e6db74">}</span><span style="color:#e6db74">/repos/</span><span style="color:#e6db74">${</span>GITHUB_REPOSITORY<span style="color:#e6db74">}</span><span style="color:#e6db74">/actions/runs/</span><span style="color:#e6db74">${</span>GITHUB_RUN_ID<span style="color:#e6db74">}</span><span style="color:#e6db74">/attempts/</span><span style="color:#e6db74">${</span>GITHUB_RUN_ATTEMPT<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -H <span style="color:#e6db74">&#34;Accept: application/vnd.github+json&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -H <span style="color:#e6db74">&#34;Authorization: Bearer </span><span style="color:#e6db74">${</span>GITHUB_TOKEN<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -H <span style="color:#e6db74">&#34;X-GitHub-Api-Version: 2022-11-28&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>created_at<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>echo <span style="color:#e6db74">&#34;</span>$json<span style="color:#e6db74">&#34;</span> | sed -n <span style="color:#e6db74">&#39;s/.*&#34;created_at&#34;.*&#34;\(.*\)&#34;.*/\1/p&#39;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>trace_parent<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>trace start <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>GITHUB_REPOSITORY<span style="color:#e6db74">}</span><span style="color:#e6db74">/</span><span style="color:#e6db74">${</span>GITHUB_WORKFLOW<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> --when <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>created_at<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>export <span style="color:#e6db74">&#34;TRACEPARENT=</span><span style="color:#e6db74">${</span>trace_parent<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span></code></pre></div>
        </div>
        
    </div>
</div>
<p>So that we can capture the overhead of the build job starting and the first build command running, we also store the current time as an attribute:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>trace attr <span style="color:#e6db74">&#34;first_command&#34;</span> <span style="color:#66d9ef">$(</span>date +%s<span style="color:#66d9ef">)</span>
</span></span></code></pre></div><p>At the end of the build, we finish the trace - this needs to happen no matter how the build finishes, pass or failure.</p>


<div class="tab-panel">
    <div class="tab-nav">
    
        <button
          data-tab-item="Github Actions"
          data-tab-group="default"
          class="tab-nav-button btn active"
          onclick="switchTab('default','Github Actions')"
         >Github Actions</button>
    
        <button
          data-tab-item="bash"
          data-tab-group="default"
          class="tab-nav-button btn "
          onclick="switchTab('default','bash')"
         >bash</button>
    
    </div>
    <div class="tab-content">
        
        <div data-tab-item="Github Actions" data-tab-group="default" class="tab-item active">
            <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Finish Trace</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">if</span>: <span style="color:#ae81ff">always()</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">uses</span>: <span style="color:#ae81ff">pondidum/trace/finish@main</span>
</span></span></code></pre></div><p>By using <code>if: always()</code>, we make sure this step runs no matter if the workflow was <code>failed</code>, <code>cancelled</code> or <code>success</code>.</p>
<p>The action uses the <code>{{ job.status }}</code> context to add the <code>--error</code> flag and a message with the status in it, if the job doesn&rsquo;t pass.</p>

        </div>
        
        <div data-tab-item="bash" data-tab-group="default" class="tab-item ">
            <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>trap <span style="color:#e6db74">&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    rc=$?; # store the exit code
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    [ $rc = &#34;0&#34; ] &amp;&amp; echo trace finish ${TRACEPARENT}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    [ $rc != &#34;0&#34; ] &amp;&amp; echo trace finish --error=&#34;exit ${rc}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    trap - EXIT;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    exit
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  &#39;</span> EXIT INT HUP
</span></span></code></pre></div><p>By using a <code>trap</code>, we can make sure the <code>./trace finish</code> command always runs regardless of how the script was killed.  This needs to be written near the top of the script however!</p>

        </div>
        
    </div>
</div>
<h2 id="tracing-build-steps">Tracing Build Steps</h2>
<p>Now that there is a trace for the entire build, we can start adding more details.</p>
<p>For example, we might want to pull a few docker containers so that we have <a href="/2020/05/14/docker-layer-sharing/">warm caches</a>, and want to keep track of how long this takes:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>group<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>trace group start <span style="color:#e6db74">&#34;docker_pull&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  trace task -- docker pull app:builder <span style="color:#f92672">||</span> true
</span></span><span style="display:flex;"><span>  trace task -- docker pull app:latest <span style="color:#f92672">||</span> true
</span></span><span style="display:flex;"><span>  trace task -- docker pull alpine:3.18 <span style="color:#f92672">||</span> true
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>trace group finish <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>group<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span></code></pre></div><h2 id="tracing-and-feature-flags">Tracing and Feature Flags</h2>
<p>When you are using <a href="/2023/01/16/feature-flags-ci/">feature flags</a> in your CI system, adding their state to the trace is important; it allows us to filter traces by what flags were active on a given run, letting us see if a particular flag has an impact on success rate or time taken.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># flagon supports the `TRACEPARENT` environment variable, so you</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># also get spans for it querying your flag service too!</span>
</span></span><span style="display:flex;"><span>vitest<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>flagon state <span style="color:#e6db74">&#34;ci-enable-vitest&#34;</span> <span style="color:#e6db74">&#34;false&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --user <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>email<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --attr <span style="color:#e6db74">&#34;branch=</span><span style="color:#e6db74">${</span>branch<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --output <span style="color:#e6db74">&#34;template={{.Value}}&#34;</span> <span style="color:#f92672">||</span> true<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>trace attr <span style="color:#e6db74">&#34;enable_vitest=</span><span style="color:#e6db74">${</span>vitest<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># later</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>group<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>trace group start <span style="color:#e6db74">&#34;testing&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>vitest<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;true&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    pnpm run vitest
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>    pnpm run jest
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>trace group finish <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>group<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span></code></pre></div><p>This will give us a trace with the <code>enable-vitest</code> flag state, and we can group by this to see if <code>vitest</code> is faster than <code>jest</code> and what effect it had on test count etc.</p>
]]></content:encoded></item><item><title>Expand Contract for Databases and Services</title><link>https://andydote.co.uk/2023/05/18/expand-contract/</link><pubDate>Thu, 18 May 2023 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2023/05/18/expand-contract/</guid><description>I haven&amp;rsquo;t seen Expand-Contract written about in some years, and I think it is a great way of performing database schema migrations without the need for application downtime. I also realised that it also applies to microservices and service-to-service communication in general.
The Easy Example One of the two examples given is wanting to change how an address is stored in a database. The schema starts off looking like this:</description><content:encoded><![CDATA[<p>I haven&rsquo;t seen Expand-Contract written about in some years, and I think it is a great way of performing database schema migrations without the need for application downtime.  I also realised that it also applies to microservices and service-to-service communication in general.</p>
<h2 id="the-easy-example">The Easy Example</h2>
<p>One of the two examples given is wanting to change how an address is stored in a database.  The schema starts off looking like this:</p>
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Reaktor</td>
<td>Läntinen Rantakatu 15, 20100, Turku, Finland</td>
</tr>
</tbody>
</table>
<p>The requirement is that the schema is changed to look like this:</p>
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>street</th>
<th>postcode</th>
<th>town</th>
<th>country</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Reaktor</td>
<td>Läntinen Rantakatu 15</td>
<td>20100</td>
<td>Turku</td>
<td>Finland</td>
</tr>
</tbody>
</table>
<p>The way you would traditionally achieve this is with a migration:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">alter</span> <span style="color:#66d9ef">table</span> buildings
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">add</span> <span style="color:#66d9ef">column</span> street text,
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">add</span> <span style="color:#66d9ef">column</span> postcode text, <span style="color:#75715e">-- postcodes can start with a 0, so store them as text
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#66d9ef">add</span> <span style="color:#66d9ef">column</span> town text,
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">add</span> <span style="color:#66d9ef">column</span> country text
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">update</span> buildings <span style="color:#66d9ef">set</span>
</span></span><span style="display:flex;"><span>  street    <span style="color:#f92672">=</span> split_part(address, <span style="color:#e6db74">&#39;,&#39;</span>, <span style="color:#ae81ff">1</span>),
</span></span><span style="display:flex;"><span>  postcode  <span style="color:#f92672">=</span> split_part(address, <span style="color:#e6db74">&#39;,&#39;</span>, <span style="color:#ae81ff">2</span>),
</span></span><span style="display:flex;"><span>  town      <span style="color:#f92672">=</span> split_part(address, <span style="color:#e6db74">&#39;,&#39;</span>, <span style="color:#ae81ff">3</span>),
</span></span><span style="display:flex;"><span>  country   <span style="color:#f92672">=</span> split_part(address, <span style="color:#e6db74">&#39;,&#39;</span>, <span style="color:#ae81ff">4</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">where</span>
</span></span><span style="display:flex;"><span>  address <span style="color:#f92672">!=</span> <span style="color:#e6db74">&#34;&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">alter</span> <span style="color:#66d9ef">table</span> buildings
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">drop</span> <span style="color:#66d9ef">column</span> address
</span></span></code></pre></div><p>The problem with doing this is that the software using this table needs to be stopped while the update is happening; if the old version is running, the app will suddenly be trying to query a non-existing column.  If the new version is running, it will also be trying to query non-existing columns.</p>
<p>The process has to look like this:</p>
<ol>
<li>stop the old app</li>
<li>run the migration</li>
<li>start the new app</li>
</ol>
<p>Step 2 however can be long, especially if there is lots of data.  And what happens if you cannot have downtime for your service?</p>
<h2 id="the-expand-contract-way">The Expand Contract Way</h2>
<ol>
<li>add a new column to the table (nullable)</li>
<li>release new software
<ul>
<li>for reads, read both old and new columns; prefer data in new columns if it exists</li>
<li>for writes, write to new columns</li>
</ul>
</li>
<li>run a script to migrate any remaining data</li>
<li>release new software
<ul>
<li>only reads new columns</li>
<li>only writes new columns</li>
</ul>
</li>
<li>drop the old column</li>
</ol>
<p>This is more steps than the original method, but it means there is no downtime in your system.  Also, if you make step 2 write to both columns, the migration is easily reversible as no data is lost until the fourth step runs.
.</p>
<h2 id="what-about-apis--services">What about APIs?  Services?</h2>
<p>Expand Contract doesn&rsquo;t have to just be about services either.  For example, you have two services and have decided that part of service A should be migrated into service B, which has a similar system.  The process is broadly similar to the database example above but with service releases instead:</p>
<ol>
<li>Service B&rsquo;s data model is expanded</li>
<li>Service A is released:
<ul>
<li>for reads, read both it&rsquo;s own datastore and Service B.  Return result from B if available</li>
<li>for writes, write to it&rsquo;s own datastore and Service B</li>
</ul>
</li>
<li>Run a script/application to migrate the remaining data</li>
<li>Release Service A:
<ul>
<li>uses Service B for all operations</li>
</ul>
</li>
<li>Drop old data store tables</li>
</ol>
<p>As you can see, the process is broadly similar to when implementing a database change; the only difference is some coordination with the other service team.  The coordination is only to make sure their data model is ready; no need to release anything at the same time, and no downtime in either service is required.</p>
<h2 id="downsides">Downsides</h2>
<p>This may sound like a silver bullet, but as with all techniques, it has drawbacks.</p>
<p>The primary drawback is the extra steps required.  There are multiple releases, and data migrates lazily/on demand.  Then there is the extra step of migrating the remaining data, which is an additional effort.</p>
<p>The other drawback is a symptom of the first drawback: time.  It takes far longer to do expand-contract than to have a short downtime.  Depending on your application, short downtime might be the better choice to make.  For example, a queue processing service which doesn&rsquo;t have a synchronous API would probably be better choosing the downtime, assuming it can catch up with any messages which queue up during the downtime!</p>
]]></content:encoded></item><item><title>Feature Flags in a CI Pipeline</title><link>https://andydote.co.uk/2023/01/16/feature-flags-ci/</link><pubDate>Mon, 16 Jan 2023 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2023/01/16/feature-flags-ci/</guid><description>Feature flags are a great tool for helping software development; they provide controlled feature rollouts, facilitate A/B testing, and help decouple deployment from release. So when it comes to building our software, why do we treat the CI pipeline without the same level of engineering as the production code?
So, why not use feature flags in your CI pipeline?
TLDR Reduce the risk of breaking a CI pipeline for all of a project&amp;rsquo;s developers by using the flagon CLI to query Feature Flags, opting developers into and out of new CI features and processes by targeting groups of developers or branch naming patterns.</description><content:encoded><![CDATA[<p>Feature flags are a great tool for helping software development; they provide controlled feature rollouts, facilitate A/B testing, and help decouple <a href="/2022/11/02/deploy-doesnt-mean-release/">deployment from release</a>.  So when it comes to building our software, why do we treat the CI pipeline without the same level of engineering as the production code?</p>
<p>So, why not use feature flags in your CI pipeline?</p>
<h2 id="tldr">TLDR</h2>
<p>Reduce the risk of breaking a CI pipeline for all of a project&rsquo;s developers by using the <a href="https://github.com/pondidum/flagon">flagon</a> CLI to query Feature Flags, opting developers into and out of new CI features and processes by targeting groups of developers or branch naming patterns.</p>
<h2 id="what-would-we-use-them-for">What would we use them for?</h2>
<p>There are a few things that spring to mind that we could use feature flags for:</p>
<ul>
<li>Migrating CI system</li>
<li>Job migration</li>
<li>Replacing a step</li>
<li>Trying a new step</li>
</ul>
<h2 id="why-would-using-flags-for-this-help">Why would using flags for this help?</h2>
<p>The answer is risk reduction.  I don&rsquo;t want to break parts of the build and deployment process for everyone in the project when I make a mistake in the pipelines, and a way to help mitigate that risk is feature flags.</p>
<p>With a feature flag, I can quickly opt people into or out of changes to the CI system, meaning that if something goes wrong, the impact is minimal.  It also allows me to monitor the effects of new vs old by having the flag states stored in our OTEL traces.  This lets me ask and answer questions like: is it faster?  Is it more reliable?  Does it work?</p>
<p>One of the most significant risks is migrating from one CI system to another, which is exactly what I have been doing recently.  We are leaving <code>Truly Awful CI</code> and migrating to <code>Github Actions</code>.  Let&rsquo;s see how that goes.</p>
<h2 id="migrating-from-old-to-new-ci">Migrating From Old to New CI</h2>
<p>The CI process, on a high level, looks like this.  The three types of deployment are <code>ephemeral</code>, which are short-lived environments named after the branch which created them, <code>development</code>, which is the common development environment, and <code>production</code>, which is the live application.  The <code>production</code> and <code>development</code> environments are deployed to whenever something is merged to <code>main</code>, and <code>ephemeral</code> is for any other branch.</p>

<div class="mermaid" align="left">
graph LR

    clone --> build --> test --> publish-container

    publish-container --> |$BRANCH != 'main'| trigger-deploy-ephemeral
    publish-container --> |$BRANCH == 'main'| trigger-deploy-development
    publish-container --> |$BRANCH == 'main'| trigger-deploy-production
</div>
<p>To phase the changeover to GitHub Actions, I am using the <a href="https://github.com/pondidum/flagon">flagon</a> CLI to access our feature flags.  The query uses both the user id (committer email) and branch name so that I can target rollouts based on a group of users or perhaps with a branch name pattern.</p>
<p>First, I create a duplicate workflow in GitHub Actions.  The docker container is published to a different tag, and all deployments have a feature flag condition added to them:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">jobs</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">flags</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">outputs</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">enable_ephemeral</span>: <span style="color:#ae81ff">${{ steps.query.outputs.enable_ephemeral }}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">steps</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Query Flags</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">id</span>: <span style="color:#ae81ff">query</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">run</span>: |<span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        ephemeral=$(flagon state &#34;ci-enable-gha-deployment&#34; &#34;false&#34; \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          --user &#34;${email}&#34; \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          --attr &#34;branch=${branch}&#34; \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          --output &#34;template={{.Value}}&#34; || true)
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        echo &#34;enable_ephemeral=${ephemeral}&#34; &gt;&gt; &#34;${GITHUB_OUTPUT}&#34;</span>        
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># build, test, etc.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">deploy_ephemeral</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">uses</span>: <span style="color:#ae81ff">./.github/workflows/deploy.yaml</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">needs</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">flags</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">build</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">if</span>: <span style="color:#ae81ff">${{ github.ref_name != &#39;master&#39; &amp;&amp; needs.flags.outputs.enable_ephemeral == &#39;true&#39; }}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">with</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">target_env</span>: <span style="color:#ae81ff">ephemeral</span>
</span></span></code></pre></div><p>Then update the old CI pipeline to wrap the deployment trigger with a flag query:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> ! flagon <span style="color:#e6db74">&#34;ci-enable-gha-deploy&#34;</span> <span style="color:#e6db74">&#34;true&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --user <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>email<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --attr <span style="color:#e6db74">&#34;environment=ephemeral&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --attr <span style="color:#e6db74">&#34;BRANCH=</span><span style="color:#e6db74">${</span>branch<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  awful-ci trigger <span style="color:#e6db74">&#34;deploy - ephemeral&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --sha <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>commit<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --branch <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>branch<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span></code></pre></div><p>Note that the two CI systems are both querying the same flag, but the old system defaults to active, and the new system defaults to inactive.  This means that if the flagging service (LaunchDarkly in this case) cannot be reached, only one of the systems will be doing the deployment.</p>
<h2 id="rolling-out">Rolling out</h2>
<p>The plan for starting the switchover was as follows:</p>
<ol>
<li><code>ephemeral</code> for just me</li>
<li><code>ephemeral</code> environment for a small group of developers</li>
<li><code>ephemeral</code> for everyone</li>
<li><code>development</code> for everyone</li>
<li><code>production</code> for everyone</li>
<li>WAIT</li>
<li>Remove old implementation, remove flags</li>
</ol>
<p>During the rollout, the flag was switched on and off for various stages as small bugs were found.</p>
<p>For example, I discovered that the deployments only looked like they were working in GitHub Actions due to some artefacts still being uploaded to CDN by the old CI system.</p>
<h2 id="take-away">Take Away</h2>
<p>Based on my experience of using flags in this migration, it is a technique that I will be using more in the future when updating our CI pipelines.</p>
]]></content:encoded></item><item><title>Changelog Driven Versioning</title><link>https://andydote.co.uk/2022/11/22/changelogs/</link><pubDate>Tue, 22 Nov 2022 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2022/11/22/changelogs/</guid><description>Versioning is one of the many hard problems when it comes to writing software. There is no one correct way to do it, and all have various tradeoffs.
After reading keep a changelog, I was inspired to implement this into a couple of CLI tools that I am working on at the moment: Flagon (feature flags on the CLI, for CI usage), and Cas (Content Addressable Storage for Make), but I also wanted to solve my versioning and release process.</description><content:encoded><![CDATA[<p>Versioning is one of the many hard problems when it comes to writing software.  There is no one correct way to do it, and all have various tradeoffs.</p>
<p>After reading <a href="https://keepachangelog.com/en/1.0.0/">keep a changelog</a>, I was inspired to implement this into a couple of CLI tools that I am working on at the moment: <a href="https://github.com/pondidum/flagon">Flagon</a> (feature flags on the CLI, for CI usage), and <a href="https://github.com/pondidum/cas">Cas</a> (Content Addressable Storage for Make), but I also wanted to solve my versioning and release process.</p>
<h2 id="requirements">Requirements</h2>
<ul>
<li>Version number should be defined in only one place</li>
<li>A changelog should be associated with the version number</li>
<li>The binary should be able to print its version and changelog</li>
<li>The release (Github Release in this case) should also have the changelog and version</li>
<li>The commit released should be tagged with the version</li>
</ul>
<p>I came up with an idea: <strong>drive everything from the changelog.</strong></p>
<p>The changelog can be the source of truth: it contains the version number, date of release, and the actual changes within that version.  As the changelog is written in a standardised format it should be fairly easy to parse, and thus be handled by the binary itself.</p>
<h2 id="the-format">The Format</h2>
<p>I decided to follow the format from <a href="https://keepachangelog.com/en/1.0.0/">keep a changelog</a> as it is pretty minimal, in markdown, and easily parsable with a regex.  As an example, here is one of the versions lifted from <a href="https://github.com/Pondidum/Flagon/blob/main/changelog.md">flagon&rsquo;s changelog</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span># Changelog
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## [0.0.1] - 2022-11-14
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">### Added
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">-</span> Exit with code <span style="color:#e6db74">`0`</span> if a flag is <span style="color:#e6db74">`true`</span>, and <span style="color:#e6db74">`1`</span> otherwise
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">-</span> Add <span style="color:#e6db74">`--silent`</span> flag, to suppress console information
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">### Changed
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">-</span> Expand what information is written to traces
</span></span></code></pre></div><p>Each version entry follows the same format, which is parsable by a regex:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">sectionRegex</span> = <span style="color:#a6e22e">regexp</span>.<span style="color:#a6e22e">MustCompile</span>(<span style="color:#e6db74">`## \[(?P&lt;version&gt;.*)\]\s*-\s*(?P&lt;date&gt;.*)`</span>)</span></span></code></pre></div><footer style="margin: 10px auto;">
  <small><a href="https://github.com/Pondidum/flagon/blob/master/version/changelog.go">Source</a></small>
</footer>

<p>The parser itself is very short, and the result is an array of <code>ChangelogEntry</code>, giving the <code>version</code>, <code>date</code>, and text of the changes.</p>
<h2 id="using-the-changelog-from-the-application">Using the changelog from the application</h2>
<p>The changelog is embedded in the binary using the go <code>embed</code> package, and can then be exposed as CLI commands.  The application&rsquo;s <code>version</code> command exposes this information with several flags:</p>
<ul>
<li>
<p>no flags: print the version number and git short sha</p>
</li>
<li>
<p><code>--short</code>: only print the version number</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>./flagon version --short
</span></span><span style="display:flex;"><span>0.0.1
</span></span></code></pre></div></li>
<li>
<p><code>--changelog</code>: pretty print the current version&rsquo;s changelog entry</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>./flagon version --changelog
</span></span></code></pre></div><p><img loading="lazy" src="flagon-changelog.png" alt="flagon changelog as prettified markdown"  />
</p>
</li>
<li>
<p><code>--raw</code>: causes <code>--changelog</code> to print the markdown as written in the <code>changelog.md</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>./flagon version --changelog
</span></span><span style="display:flex;"><span>0.0.1 - local
</span></span><span style="display:flex;"><span><span style="color:#75715e">### Added</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>- Exit with code <span style="color:#e6db74">`</span>0<span style="color:#e6db74">`</span> <span style="color:#66d9ef">if</span> a flag is <span style="color:#e6db74">`</span>true<span style="color:#e6db74">`</span>, and <span style="color:#e6db74">`</span>1<span style="color:#e6db74">`</span> otherwise
</span></span><span style="display:flex;"><span>- Add <span style="color:#e6db74">`</span>--silent<span style="color:#e6db74">`</span> flag, to suppress console information
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">### Changed</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>- Expand what information is written to traces
</span></span></code></pre></div></li>
</ul>
<h2 id="using-the-changelog-for-releases">Using the changelog for Releases</h2>
<p>In github actions when building the <code>main</code> branch, I use this to generate a version number, and write the current changelog entry to a temporary file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>- <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Generate Release Notes</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">if</span>: <span style="color:#ae81ff">github.ref_name == &#39;main&#39;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">run</span>: |<span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    echo &#34;FLAGON_VERSION=$(./flagon version --short)&#34; &gt;&gt; &#34;${GITHUB_ENV}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ./flagon version --changelog --raw &gt; release-notes.md</span>    
</span></span></code></pre></div><p>Which are then passed to the <code>action-gh-release</code> step:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>- <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Release</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">if</span>: <span style="color:#ae81ff">github.ref_name == &#39;main&#39;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">uses</span>: <span style="color:#ae81ff">softprops/action-gh-release@v1</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">with</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">${{ env.FLAGON_VERSION }}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">tag_name</span>: <span style="color:#ae81ff">${{ env.FLAGON_VERSION }}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">body_path</span>: <span style="color:#ae81ff">release-notes.md</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">files</span>: <span style="color:#ae81ff">flagon</span>
</span></span></code></pre></div><p>Which makes my releases match the version number of the binary, and have the correct release notes.</p>
<h2 id="further-work">Further Work</h2>
<p>This system isn&rsquo;t perfect (yet), but it works well for my projects.  I&rsquo;ve considered extracting it into its own package, but so far with only two applications using it I haven&rsquo;t hit the <a href="https://en.wikipedia.org/wiki/Rule_of_three_(computer_programming)">rule of 3 yet</a>.</p>
]]></content:encoded></item><item><title>QA and Continuous Delivery</title><link>https://andydote.co.uk/2022/11/10/qa-and-continuous-delivery/</link><pubDate>Thu, 10 Nov 2022 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2022/11/10/qa-and-continuous-delivery/</guid><description>When migrating to a continuous delivery process, it is often the case that a QA team are worried about what their role is going to be, and how the changes will affect the quality of the software in question.
While doing continuous delivery does change the QA process, when done well, it improves everyone&amp;rsquo;s lives and makes the software better quality. Are silver bullets incoming? Not quite, but we don&amp;rsquo;t have to make someone&amp;rsquo;s life worse to improve other people&amp;rsquo;s lives.</description><content:encoded><![CDATA[<p>When migrating to a continuous delivery process, it is often the case that a QA team are worried about what their role is going to be, and how the changes will affect the quality of the software in question.</p>
<p>While doing continuous delivery does change the QA process, when done well, it improves everyone&rsquo;s lives and makes the software <em>better</em> quality.  Are silver bullets incoming?  Not quite, but we don&rsquo;t have to make someone&rsquo;s life worse to improve other people&rsquo;s lives.</p>
<p>This article is going to rely heavily on <a href="/tags/feature-flags/">Feature Flags</a>, so a passing familiarity is useful.  In summary, feature flags are the ability to switch features on and off at runtime of the application without requiring re-deployment.  Feature flags can also be used to switch on features for specific users or groups of users.</p>
<blockquote>
<p>Aside; this post is a bit different from my usual style.  This time I have written a story about a fictional dev team and QA team and how they move towards continuous delivery together.</p>
</blockquote>
<h2 id="tldr">TLDR</h2>
<p>Move your QA Engineers inside the dev teams; DevOps is a way of working in a cross-functional team; this should include everyone who can contribute.</p>
<p>Test things early.  Involve QA with features hidden behind flags.  De-couple your deployments from your releases.</p>
<h2 id="setting-the-scene">Setting The Scene</h2>
<p>A team has gotten to the point where they want to switch from deploying at the end of each sprint to deployments happening as often as needed, be that 5 minutes for a text change or a few days for a bigger feature.</p>
<p>When they happily announce this to the rest of their organisation, the QA Team reacts with dismay; how are they going to manage to do full testing before every deployment if the team is constantly deploying?  They object; this is ludicrous.</p>
<p>Being level-headed people, everyone decides to sit down and talk through their concerns and what to do next.  The key points are written down:</p>
<ul>
<li>The development team wants to ship faster</li>
<li>The QA team wants to test everything before it is deployed</li>
<li>The management team doesn&rsquo;t want to hire 10 more QAs to try and keep up</li>
</ul>
<p>So what to do?</p>
<h2 id="the-first-step">The first step</h2>
<p>It is important to realise that while we want quality, not all changes are created equal; some need much closer scrutiny than others.  For example, fixing some spelling mistakes probably needs no one else&rsquo;s input (other than a spell-checking tool, perhaps) other than the person doing it.</p>
<p>The teams agree on this; after some discussion, they write down the following:</p>
<ul>
<li>Small fixes can be released without a QA approval</li>
</ul>
<p>This raises a few further questions however:</p>
<ol>
<li>How big is small?</li>
<li>If a small fix can be deployed without QA, what about a small feature?</li>
<li>Why is QA the final authority on what can be released?</li>
</ol>
<h2 id="changing-perspective">Changing Perspective</h2>
<p>While we could try and answer these questions (and spend countless hours deciding how many lines of code &ldquo;small&rdquo; is.  Does it depend on line length too?), a better tactic is to investigate why the QA process is happening <em>so late in the process</em>.</p>
<p>We agree that features need QA testing, but what happens if features can be hidden?  What happens if we can move the testing from &ldquo;before deployment&rdquo; to &ldquo;before release&rdquo;?  Because as I have written before <a href="deploy-not-release"><code>deploy doesn't mean release</code></a>.</p>
<p>The team realises that they have a Feature Flagging tool available.  Currently, they are not really using it, but they have been meaning to for a while.  What if new features were developed behind flags?  It could be deployed to production without affecting anyone, and QA could test at their leisure by enabling the flag for just one tester or for the whole team.</p>
<p>The QA team thinks this could work in principle, but how do they know a change is <em>really</em> isolated behind a flag?  What happens if it escapes?</p>
<p>Let&rsquo;s look at the process they came up with, with an example.</p>
<h2 id="the-new-feature">The New Feature</h2>
<p>The current web application has a notification system.  It&rsquo;s nothing glamorous; it&rsquo;s an icon in the app which gets a small dot when there is a new notification.  Currently, only notifications from the system itself are supported, but there has been a request to have other parts of the system send notifications there too, along with feature requests for being able to remove read notifications and mark notifications to trigger again later.</p>
<p>This seems like the ideal candidate for a feature flag, so the development team writes down their next steps:</p>
<ol>
<li>create a flag <code>enable-rich-notifications</code></li>
<li>develop all the capabilities (API, UI)</li>
<li>deploy</li>
<li>QA can test it with the flag</li>
<li>release it to the world</li>
</ol>
<p>Someone points out that Step 2 looks like several weeks of work on its own, and that isn&rsquo;t very continuous.  They break down the tasks a bit further:</p>
<ol>
<li>create a flag <code>enable-rich-notifications</code></li>
<li>update the API with a new <code>/rich</code> endpoint, which can only be queried if you have the flag.</li>
<li>create some fake data for the <code>/rich</code> endpoint to return</li>
<li>create a new UI component which uses the new endpoint</li>
<li>update the application to use the new component if you have the flag and the old component otherwise</li>
</ol>
<p>With implicit &ldquo;Deploy&rdquo; steps after each step.  This seems reasonable to the development team, but the QA team still have questions: when should they test the UI?  once it is fully complete?  And how do they know it is working?</p>
<p>The development team also realises that the new notifications system will be using the same data model as the old system, and they need to make sure the old system continues to work correctly.  Come to think of it, QA involvement would be useful here too&hellip;</p>
<h2 id="moving-qa-earlier">Moving QA Earlier</h2>
<blockquote>
<p>As an aside, I find it much better to have a QA Engineer be part of the development team.  The whole DevOps thing is about working in one cross-functional team, and why should QA, Security, or anyone else be excluded from this?  Regrettably, this is a slow organisational change to make, so we come up with ways to make it work as best we can and iterate towards the embedded QA model.</p>
</blockquote>
<p>When the new notifications feature is being designed, the development team requests someone from QA be involved from the start; there are things which they should be aware of, and have useful input on.</p>
<ol>
<li>Update the data model in place with the new design</li>
<li>QA to test it in an isolated environment; no changes expected</li>
<li>Deploy</li>
</ol>
<p>The QA points out that as far as they are aware, there aren&rsquo;t any tests for the old notifications system; it was so barebones and unused that no one bothered.  The QA also points out that they have been evaluating switching to a more code-first UI automation tool, and this might be the ideal candidate to start with, and could they put the UI testing code in the repo alongside the feature?</p>
<p>This is well received by the dev team; this might help the regressions they keep causing when a selector is updated, and the UI tests break; if it&rsquo;s all in the same repository, <code>grep</code> can find all the instances at once!  It&rsquo;s win-win again.</p>
<p>The again updated list of actions is now:</p>
<ol>
<li>QA creates UI tests for the current system (and verifies against isolated environment)</li>
<li>Devs Update the data model</li>
<li>QA verifies nothing has changed in a staging environment</li>
<li>Deploy</li>
</ol>
<p>Note there are no flags involved yet!</p>
<p>The team goes ahead and makes all the discussed changes; however, when the new UI tests are run against the environment with the new data model, they break, and it isn&rsquo;t apparent why.  The QA and the developer sit down and dig around until they find the problem; the format of a field has changed slightly, and the UI tests are catching the problem.</p>
<p>They fix the issue, test again, and this time deploy into production.</p>
<h2 id="the-new-api-and-ui">The New API and UI</h2>
<p>Now that involving QA earlier has been tried and seems to work, the team decide to move forward with the API changes and the feature flag for the original version and the rich version of notifications.</p>
<p>The flag is created, the API is wrapped with a check for the flag, the developers test it works, and deployment is done.  No problems so far.</p>
<p>The UI is up next; as this is early on in the process, the dev team, designer, and QA engineer are all sitting together to figure out exactly how it will work.  As the QA is present, they can start writing outlines for UI testing.  As the code for tests is alongside the application code, the developers can help keep the tests working as they flesh out the UI, and they might even write a test themselves too.</p>
<p>The interesting realisation comes that with a feature flag, two QAs can be involved at once; one is running tests for the flag off, and one is running the tests for the flag on.  It isn&rsquo;t required to be like this of course, but it does mean you can spread the work further.</p>
<p>Features are developed, tests are written, and deployments are done.</p>
<h2 id="ready-for-release">Ready for Release</h2>
<p>The team, which now includes the QA by default, is getting close to being ready to release their new rich notifications to the world.  They have one more test they would like to conduct: what is the load like when users are re-notifying themselves?  How do they even go about testing this?</p>
<p>The answer, perhaps unsurprisingly, is a feature flag.  In this case, a new feature flag called <code>load-generator-rich-notifications</code>.  When this flag is enabled, the rich notifications system is still hidden, but a small piece of code randomly activates notifications for re-notifying and varying intervals.  The team can switch it on for a few percent of users and then watch their traces and monitoring systems to keep an eye on the health of the system.</p>
<p>They can add more and more users to the test until they are happy.  Then disable the load generator and clean up all the mess it has left.</p>
<blockquote>
<p>Aside; this is how Facebook Messenger was load tested before the public saw anything!</p>
</blockquote>
<h2 id="wrapping-up">Wrapping Up</h2>
<p>The key takeaway from this is that QA is an important part of the delivery lifecycle.  Your QA Engineers are smart people who want to make things better, so involve them early and see what conversations and ideas can happen when you put smart people together and task them with making things better.</p>
<p>This was a lot longer than it sounded in my head when I thought this up while cycling home, but I like how it&rsquo;s gone.  I might even turn this into a talk to give to clients if it is well received.</p>
]]></content:encoded></item><item><title>Deploy != Release</title><link>https://andydote.co.uk/2022/11/02/deploy-doesnt-mean-release/</link><pubDate>Wed, 02 Nov 2022 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2022/11/02/deploy-doesnt-mean-release/</guid><description>Recently we were having a debate about release processes, and I wrote that deployments are not always equal to releases.
also deploy != release
—Andy, baiting discussion in Slack This turned out to be somewhat controversial until we discussed what I specifically meant by deploy and release.
As with all things, agreeing on definitions or understanding what someone means when they use a specific term is essential, so I thought I would write down a short blog post on it.</description><content:encoded><![CDATA[<p>Recently we were having a debate about release processes, and I wrote that deployments are not always equal to releases.</p>
<blockquote>
<p>also <code>deploy</code> != <code>release</code></p>
</blockquote>
<figcaption>—Andy, <cite>baiting discussion in Slack</cite></figcaption>
<p>This turned out to be somewhat controversial until we discussed what I specifically meant by <code>deploy</code> and <code>release</code>.</p>
<p>As with all things, agreeing on definitions or understanding what someone means when they use a specific term is essential, so I thought I would write down a short blog post on it.</p>
<p>To start with, a picture helps in my experience:</p>
<p><img loading="lazy" src="definitions.jpg" alt="definitons"  />
</p>
<h2 id="tldr">TLDR</h2>
<p><strong>Deploy</strong> is the act of moving software into an environment and running it.</p>
<p><strong>Release</strong> is the process of making a feature visible to a user or subset of users.</p>
<p>Read on for longer descriptions.</p>
<h2 id="build">Build</h2>
<p>A build is a process, usually run in a central CI system, which produces one or many <strong>artefacts</strong>.  A build process can consist of testing, linting, compilation, transpilation, or any other number of steps.</p>
<h2 id="artefact">Artefact</h2>
<p>An <strong>artefact</strong> is the result of the <strong>build</strong>.  It has a <strong>version</strong>, and can be <strong>deployed</strong> to an <strong>environment</strong>.  An artefact can contain many features which can be uniquely controlled.</p>
<p>It should also have metadata embedded in it to link it back to the build which produced it and also to the source it was built from.</p>
<p>If a build is producing multiple different versioned artefacts, having a way to link them all to the same process is important.</p>
<h2 id="version">Version</h2>
<p>A <strong>version</strong> is an identifier which uniquely labels an artefact.   This can be a chosen format such as SemVer, a datestamp, or a commit hash.  It could also be an auto-incrementing build counter.</p>
<h2 id="deploy">Deploy</h2>
<p>The process of getting an <strong>artifact</strong> into an <strong>environment</strong>.  Doesn&rsquo;t necessarily cause any visible changes to a user or client of the application.</p>
<h2 id="environment">Environment</h2>
<p>A location running the application.  An environment may have multiple applications running, making up one complete product.</p>
<h2 id="release">Release</h2>
<p><strong>Release</strong> is switching on (or off) a feature to users, independent of <strong>deploy</strong>.  This is usually done with Feature Flags, and can mean releasing to all users, or just a subset (either a random sample or specific users.)</p>
<p>You can also automate feature rollout by combining it with your observability data, rolling out to more users over time if, for example, error rates don&rsquo;t increase.</p>
]]></content:encoded></item><item><title>Content based change detection with Make</title><link>https://andydote.co.uk/2022/09/19/make-content-hash/</link><pubDate>Mon, 19 Sep 2022 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2022/09/19/make-content-hash/</guid><description>On several occasions when building complex projects, I have been tempted to set up Bazel to help speed up the build process; after all, it has a lot to offer: only building what has changed, caching built artifacts, and sharing that cache between machines for even more speed.
TLDR We can use Make and a couple of short shell scripts to implement file content-based caching and read/write that cache to remote storage, such as S3.</description><content:encoded><![CDATA[<p>On several occasions when building complex projects, I have been tempted to set up <a href="https://bazel.build/">Bazel</a> to help speed up the build process; after all, it has a lot to offer: only building what has changed, caching built artifacts, and sharing that cache between machines for even more speed.</p>
<h2 id="tldr">TLDR</h2>
<p>We can use <a href="https://www.gnu.org/software/make/">Make</a> and a couple of short shell scripts to implement file content-based caching and read/write that cache to remote storage, such as S3.  The <a href="https://github.com/Pondidum/make-cas">demo repository</a> contains a version using <a href="https://min.io/">minio</a> for ease of demonstration.</p>
<h2 id="bazel">Bazel</h2>
<p>However, Bazel has quite a high barrier to entry; there are two drawbacks: a specialised build language and the need to host extra components.  While the specialised language is not much of a drawback, the hosting side is more of an issue.  If you wish to have a shared cache (which is required to get fast builds), you need to either run <code>bazel-remote</code>, which is not actually part of the Bazel project, and requires some shared storage such as S3, or Nginx, which again requires some shared storage somewhere.</p>
<p>It boils down to not wanting to have to maintain a lot of infrastructure on top of all the usual CI bits just to have fast builds.</p>
<h2 id="so-what-about-make">So what about Make?</h2>
<p>Whereas Bazel&rsquo;s caching method is based on a hash of the input artifacts, <a href="https://www.gnu.org/software/make/">Make</a>&rsquo;s is based on the input sources and output artifacts&rsquo; <code>lastModified</code> times.</p>
<p>I tried adding distributed caching to Make by copying the output artifacts to S3, and on the next build (on a different agent), restoring them to the working directory, and seeing what would happen.</p>
<p>As both Git and S3 set the file <code>lastModified</code> dates to the time they ran, the build process either never ran (artifacts are newer than source), or always ran (sources are newer than artifacts).</p>
<p>This sent me on a relatively short journey to see if I could add hash-based change detection to Make, without recompiling Make.</p>
<p>Spoiler: it is!</p>
<h2 id="hashing">Hashing</h2>
<p>The first question is how to hash all our source files reliably.  It turns out you can do all of this with <code>sha256sum</code> in a one-liner:</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>find src -iname <span style="color:#e6db74">&#34;*.ts&#34;</span> -print0 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  | xargs -0 sha256sum <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  | LC_ALL<span style="color:#f92672">=</span>C sort <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  | sha256sum <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  | cut -d<span style="color:#e6db74">&#34; &#34;</span> -f <span style="color:#ae81ff">1</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>This does the following:</p>
<ol>
<li>Find all typescript files (for example)</li>
<li>Sort all the files <a href="https://unix.stackexchange.com/a/87763">using the &ldquo;simple&rdquo; locale</a></li>
<li>generate a hash of the content of each file</li>
<li>generate a hash of all the path+hash pairs</li>
<li>trim the output to only the hash</li>
</ol>
<p>Now that I have a hash for the files, its time to figure out how to use that with Make.</p>
<p>We&rsquo;ll be trying to make this totally legitimate build target in a <code>Makefile</code> run only when content changes, regardless of file edit dates:</p>
<pre tabindex="0"><code>dist/index.js: $(shell find src -iname &#34;*.ts&#34; -not -iname &#34;*.test.ts&#34;)
	@echo &#34;==&gt; Building&#34;
	@sleep 3s
	@mkdir -p &#34;dist&#34;
	@echo &#34;compiled at $(shell date)&#34; &gt; &#34;$@&#34;
	@echo &#34;==&gt; Done&#34;</code></pre><footer style="margin: 10px auto;">
  <small><a href="https://github.com/Pondidum/make-cas/blob/40e26dde9973479a861e4521e2a55d8222451b28/makefile">Source</a></small>
</footer>

<p>All this build step does is write the current date to a file called <code>dist/index.js</code>.  To make this more realistic, you could change the <code>sleep 3s</code> to <code>sleep 10m</code> ;)</p>
<p>The idea I have to make this hashing work is to use a file that I control and mess with its edit date:</p>
<ol>
<li>Check if a file called <code>${current_hash}</code> exists</li>
<li>If it doesn&rsquo;t exist, write the current timestamp to a new file called <code>${current_hash}</code></li>
<li>If it does exist, set the file <code>${current_hash}</code>&rsquo;s modified date to the timestamp stored inside the file</li>
<li><code>echo</code> the filename so that it can be consumed by Make</li>
</ol>
<p>This way, the file&rsquo;s edit date will change whenever the hash changes,  and if the hash doesn&rsquo;t change, we leave the edit date as is (which fixes the S3 file edit date being wrong.)</p>
<p>Code wise, it&rsquo;s a few lines of shell script:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>STORE_PATH<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>CAS_STORE_PATH<span style="color:#66d9ef">:-</span>.state<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>mkdir -p <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>STORE_PATH<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>now<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>date <span style="color:#e6db74">&#34;+%s&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>current_hash<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>echo <span style="color:#e6db74">&#34;</span>$@<span style="color:#e6db74">&#34;</span> | xargs -n <span style="color:#ae81ff">1</span> | LC_ALL<span style="color:#f92672">=</span>C sort | xargs sha256sum | sha256sum | cut -d<span style="color:#e6db74">&#34; &#34;</span> -f 1<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>key<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>current_hash<span style="color:#e6db74">}</span><span style="color:#e6db74">.sha256&#34;</span>
</span></span><span style="display:flex;"><span>state_path<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>STORE_PATH<span style="color:#e6db74">}</span><span style="color:#e6db74">/</span><span style="color:#e6db74">${</span>key<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># this hash is in the state store, re-apply it&#39;s date to the state file (as something like s3</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># sync might have changed the file&#39;s modified date.</span>
</span></span><span style="display:flex;"><span>  last_date<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>sed -n <span style="color:#e6db74">&#39;s/date:\s*\(.*\)/\1/p&#39;</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>  touch -d <span style="color:#e6db74">&#34;@</span><span style="color:#e6db74">${</span>last_date<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># this is a new hash</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;date: </span>$now<span style="color:#e6db74">&#34;</span> &gt; <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span></span></span></code></pre></div><footer style="margin: 10px auto;">
  <small><a href="https://github.com/Pondidum/make-cas/blob/1f88779e38c44f4b3af4155de5d864354863e05a/build/cas.sh">Source</a></small>
</footer>

<p>And the usage inside the <code>makefile</code> is only adding an extra <code>$(shell ./build/cas.sh .... )</code> around our dependency list:</p>
<pre tabindex="0"><code>dist/index.js: $(shell ./build/cas.sh $(shell find src -iname &#34;*.ts&#34; -not -iname &#34;*.test.ts&#34;))
	@echo &#34;==&gt; Building&#34;
	@sleep 3s
	@mkdir -p &#34;dist&#34;
	@echo &#34;compiled at $(shell date)&#34; &gt; &#34;$@&#34;
	@echo &#34;==&gt; Done&#34;</code></pre><footer style="margin: 10px auto;">
  <small><a href="https://github.com/Pondidum/make-cas/blob/1f88779e38c44f4b3af4155de5d864354863e05a/makefile">Source</a></small>
</footer>

<h2 id="testing">Testing</h2>
<p>We have a few test cases to cover:</p>
<ol>
<li>Entirely blank repository; after all, it should work when you first run <code>git clone</code>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ git clean -dxf
</span></span><span style="display:flex;"><span>$ make build
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">==</span>&gt; Building
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">==</span>&gt; Done
</span></span></code></pre></div></li>
<li>Files have not changed at all; it should have the same behaviour as normal make, i.e. nothing happens
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ git clean -dxf
</span></span><span style="display:flex;"><span>$ make build
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">==</span>&gt; Building
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">==</span>&gt; Done
</span></span><span style="display:flex;"><span>$ make build
</span></span><span style="display:flex;"><span>  make: Nothing to be <span style="color:#66d9ef">done</span> <span style="color:#66d9ef">for</span> <span style="color:#e6db74">&#39;build&#39;</span>.
</span></span></code></pre></div></li>
<li>File <code>lastModified</code> date has changed; this should cause nothing to happen also, as the content of the files hasn&rsquo;t changed:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ git clean -dxf
</span></span><span style="display:flex;"><span>$ make build
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">==</span>&gt; Building
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">==</span>&gt; Done
</span></span><span style="display:flex;"><span>$ touch src/index.ts
</span></span><span style="display:flex;"><span>$ make build
</span></span><span style="display:flex;"><span>  make: Nothing to be <span style="color:#66d9ef">done</span> <span style="color:#66d9ef">for</span> <span style="color:#e6db74">&#39;build&#39;</span>.
</span></span></code></pre></div></li>
<li>File content has changed (but <code>lastModified</code> hasn&rsquo;t); forcing a file to have different content with the same <code>lastModified</code> to show that its only content that matters:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ git clean -dxf
</span></span><span style="display:flex;"><span>$ make build
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">==</span>&gt; Building
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">==</span>&gt; Done
</span></span><span style="display:flex;"><span>$ set old_date <span style="color:#f92672">(</span>date -r src/index.ts <span style="color:#e6db74">&#34;+%s&#34;</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>$ echo <span style="color:#e6db74">&#34;// change&#34;</span> &gt;&gt; src/index.ts
</span></span><span style="display:flex;"><span>$ touch -d @$old_date src/index.ts
</span></span><span style="display:flex;"><span>$ make build
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">==</span>&gt; Building
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">==</span>&gt; Done
</span></span></code></pre></div></li>
</ol>
<h2 id="collecting-assets">Collecting Assets</h2>
<p>Before we can implement remote caching, we need to be able to mark what assets should be included for the given source hash.</p>
<p>I initially tried to achieve this by passing the name of the make target into the <code>cas.sh</code> script, but this involves a lot of repetition as the special &ldquo;target name&rdquo; make variable (<code>$@</code>) doesn&rsquo;t work if it&rsquo;s included in the source list:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-make" data-lang="make"><span style="display:flex;"><span><span style="color:#a6e22e">dist/index.js</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">$(</span>shell ./build/cas.sh <span style="color:#66d9ef">$</span>@ <span style="color:#66d9ef">$(</span>shell find src -iname &#34;*.ts&#34; -not -iname &#34;*.test.ts&#34;<span style="color:#66d9ef">))</span>
</span></span><span style="display:flex;"><span>  @echo <span style="color:#e6db74">&#34;==&gt; Building&#34;</span>
</span></span></code></pre></div><p>Besides not working, this is also not very flexible; what happens if you have other artifacts to store, other than the one acting as your make target?  What happens if you are using a sentinel file instead of actual output as a make target?  or a <code>.PHONY</code> target?</p>
<p>The answer to these questions is an extra script to store artifacts, called <code>artifact.sh</code>, which writes the path of an artifact to the hash file with a prefix of <code>artifact: </code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>key<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$1<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>artifact<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$2<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -n <span style="color:#e6db74">&#34;</span>$CAS_VERBOSE<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Storing </span><span style="color:#e6db74">${</span>artifact<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;artifact: </span><span style="color:#e6db74">${</span>artifact<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> &gt;&gt; <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>key<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span></code></pre></div><footer style="margin: 10px auto;">
  <small><a href="https://github.com/Pondidum/make-cas/blob/e0889484bd55e1098a85f4b15f2c81a8798321e9/build/artifact.sh">Source</a></small>
</footer>

<p>Which is used in the <code>makefile</code>, utilising some of Make&rsquo;s magic variables: the <code>$&lt;</code> is the filepath to the first dependency (which is the hash file produced by <code>cas.sh</code>), and usually, we use <code>$@</code>, which is the name of the target being built.  In this example, a second invocation marks another file as an artifact of the make rule:</p>
<pre tabindex="0"><code>	@./build/artifact.sh &#34;$&lt;&#34; &#34;$@&#34;
	@./build/artifact.sh &#34;$&lt;&#34; &#34;artifacts/coverage.json&#34;
</code></pre><footer style="margin: 10px auto;">
  <small><a href="https://github.com/Pondidum/make-cas/blob/e0889484bd55e1098a85f4b15f2c81a8798321e9/makefile">Source</a></small>
</footer>

<h2 id="remote-caching">Remote Caching</h2>
<p>As mentioned earlier, I want to manage as little infrastructure for this as possible, so cloud object storage such as S3 is ideal.  For local testing, we&rsquo;ll use a <a href="https://min.io/">minio</a> docker container.</p>
<p>First up, as I want this to be reasonably extensible, rather than hardcode s3 logic into the scripts, I check for an environment variable <code>CAS_REMOTE</code>, and execute that with specific arguments if it exists, both in <code>cas.sh</code> and <code>artifact.sh</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>STORE_PATH<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>CAS_STORE_PATH<span style="color:#66d9ef">:-</span>.state<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>mkdir -p <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>STORE_PATH<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>now<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>date <span style="color:#e6db74">&#34;+%s&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>current_hash<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>echo <span style="color:#e6db74">&#34;</span>$@<span style="color:#e6db74">&#34;</span> | xargs -n <span style="color:#ae81ff">1</span> | LC_ALL<span style="color:#f92672">=</span>C sort | xargs sha256sum | sha256sum | cut -d<span style="color:#e6db74">&#34; &#34;</span> -f 1<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>key<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>current_hash<span style="color:#e6db74">}</span><span style="color:#e6db74">.sha256&#34;</span>
</span></span><span style="display:flex;"><span>state_path<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>STORE_PATH<span style="color:#e6db74">}</span><span style="color:#e6db74">/</span><span style="color:#e6db74">${</span>key<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex; background-color:#3c3d38"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>CAS_REMOTE<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>  <span style="color:#e6db74">${</span>CAS_REMOTE<span style="color:#e6db74">}</span> fetch-state <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>key<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># this hash is in the state store, re-apply it&#39;s date to the state file (as something like s3</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># sync might have changed the file&#39;s modified date.</span>
</span></span><span style="display:flex;"><span>  last_date<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>sed -n <span style="color:#e6db74">&#39;s/date:\s*\(.*\)/\1/p&#39;</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>  touch -d <span style="color:#e6db74">&#34;@</span><span style="color:#e6db74">${</span>last_date<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>  <span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>CAS_REMOTE<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>    artifacts<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>sed -n <span style="color:#e6db74">&#39;s/artifact:\s*\(.*\)/\1/p&#39;</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -n <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>artifacts<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>      echo <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>artifacts<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> | xargs <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>CAS_REMOTE<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> fetch-artifacts <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>key<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>      echo <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>artifacts<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> | xargs touch -d <span style="color:#e6db74">&#34;@</span><span style="color:#e6db74">${</span>last_date<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>    <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>  <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># this is a new hash</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;date: </span>$now<span style="color:#e6db74">&#34;</span> &gt; <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>  <span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>CAS_REMOTE<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>    <span style="color:#e6db74">${</span>CAS_REMOTE<span style="color:#e6db74">}</span> store-state <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>key<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>  <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span></code></pre></div><footer style="margin: 10px auto;">
  <small><a href="https://github.com/Pondidum/make-cas/blob/e3c00c7924d24a1aba6bdd2fad7996a3428ee530/build/cas.sh">Source</a></small>
</footer>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>key<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$1<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>artifact<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$2<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -n <span style="color:#e6db74">&#34;</span>$CAS_VERBOSE<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Storing </span><span style="color:#e6db74">${</span>artifact<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;artifact: </span><span style="color:#e6db74">${</span>artifact<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> &gt;&gt; <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>key<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex; background-color:#3c3d38"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>CAS_REMOTE<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>  hash<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">$(</span>basename <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>key<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>  <span style="color:#e6db74">${</span>CAS_REMOTE<span style="color:#e6db74">}</span> store-artifact <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>hash<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>artifact<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>  <span style="color:#e6db74">${</span>CAS_REMOTE<span style="color:#e6db74">}</span> store-state <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>hash<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>key<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span><span style="color:#66d9ef">fi</span>
</span></span></code></pre></div><footer style="margin: 10px auto;">
  <small><a href="https://github.com/Pondidum/make-cas/blob/e3c00c7924d24a1aba6bdd2fad7996a3428ee530/build/artifact.sh">Source</a></small>
</footer>

<p>The main point is keeping how state and artifacts are copied around separate from the logic of how their <code>lasModified</code> dates are manipulated.  In the case of the <code>fetch-artifacts</code> call, we first pull all the artifacts using the remote script, and then update their <code>lastModified</code> dates to match the state&rsquo;s <code>lastModified</code> date:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>CAS_REMOTE<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    artifacts<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>sed -n <span style="color:#e6db74">&#39;s/artifact:\s*\(.*\)/\1/p&#39;</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -n <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>artifacts<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>      echo <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>artifacts<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> | xargs <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>CAS_REMOTE<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> fetch-artifacts <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>key<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>      echo <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>artifacts<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> | xargs touch -d <span style="color:#e6db74">&#34;@</span><span style="color:#e6db74">${</span>last_date<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span></span></span></code></pre></div><footer style="margin: 10px auto;">
  <small><a href="https://github.com/Pondidum/make-cas/blob/e3c00c7924d24a1aba6bdd2fad7996a3428ee530/build/cas.sh">Source</a></small>
</footer>

<h2 id="s3-remote-cache">S3 Remote Cache</h2>
<p>The S3 remote script implements four functions: <code>fetch-state</code>, <code>fetch-artifacts</code>, <code>store-state</code>, and <code>store-artifact</code>, with the convention that the first parameter is always the key - e.g. the state file name.</p>
<p>In this demo, the actual S3 command is defaulted to use the local minio endpoint, unless <code>CAS_S3_CMD</code> is specified, as I cannot find a way to set the <code>--endpoint-url</code> via an environment variable directly:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>s3<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>CAS_S3_CMD<span style="color:#66d9ef">:-</span><span style="color:#e6db74">&#34;aws --endpoint-url http://localhost:9000 s3&#34;</span><span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span></span></span></code></pre></div><footer style="margin: 10px auto;">
  <small><a href="https://github.com/Pondidum/make-cas/blob/e3c00c7924d24a1aba6bdd2fad7996a3428ee530/build/remote_s3.sh">Source</a></small>
</footer>

<p>This is used in each of the four functions to interact with S3.  For example, to fetch the state; note how we use both <code>--quiet</code> and <code>&gt;&amp;2</code> to redirect all output to <code>stderr</code>, as anything on <code>stdout</code> make will pick up as a filename, causing issues.  We also use <code>|| true</code> for fetching state, as it might not exist:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>fetch_state<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  key<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$1<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  state_path<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$2<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  log <span style="color:#e6db74">&#34;</span>$key<span style="color:#e6db74">: Fetching remote state to </span>$state_path<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  $s3 cp <span style="color:#e6db74">&#34;s3://</span><span style="color:#e6db74">${</span>bucket<span style="color:#e6db74">}</span><span style="color:#e6db74">/state/</span><span style="color:#e6db74">${</span>key<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>state_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> --quiet &gt;&amp;<span style="color:#ae81ff">2</span> <span style="color:#f92672">||</span> true
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span></span></span></code></pre></div><footer style="margin: 10px auto;">
  <small><a href="https://github.com/Pondidum/make-cas/blob/e3c00c7924d24a1aba6bdd2fad7996a3428ee530/build/remote_s3.sh">Source</a></small>
</footer>

<h2 id="testing-remote-caching">Testing Remote Caching</h2>
<p>First, we need to start our minio container and configure the environment:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>docker-compose up -d
</span></span><span style="display:flex;"><span>export <span style="color:#e6db74">&#34;AWS_ACCESS_KEY_ID=minio&#34;</span>
</span></span><span style="display:flex;"><span>export <span style="color:#e6db74">&#34;AWS_SECRET_ACCESS_KEY=password&#34;</span>
</span></span><span style="display:flex;"><span>export <span style="color:#e6db74">&#34;CAS_REMOTE=./build/remote_s3.sh&#34;</span>
</span></span><span style="display:flex;"><span>export <span style="color:#e6db74">&#34;CAS_S3_BUCKET_PATH=makestate/cas-demo/&#34;</span>
</span></span><span style="display:flex;"><span>export <span style="color:#e6db74">&#34;CAS_READ_ONLY=0&#34;</span>
</span></span><span style="display:flex;"><span>export <span style="color:#e6db74">&#34;CAS_VERBOSE=1&#34;</span>
</span></span></code></pre></div><p>Also, we need to create the S3 bucket using the AWS cli:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>aws --endpoint-url http://localhost:9000 s3 mb s3://makestate
</span></span></code></pre></div><p>We&rsquo;re now ready to try a build:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ git clean -dxf
</span></span><span style="display:flex;"><span>$ make build
</span></span><span style="display:flex;"><span>  c2bac686e507434398d9bf4e33f63f275dfd3bfecfe851d698f8f17672eeccbe.sha256: Fetching remote state to .state/c2bac686e507434398d9bf4e33f63f275dfd3bfecfe851d698f8f17672eeccbe.sha256
</span></span><span style="display:flex;"><span>  c2bac686e507434398d9bf4e33f63f275dfd3bfecfe851d698f8f17672eeccbe.sha256: Storing state from .state/c2bac686e507434398d9bf4e33f63f275dfd3bfecfe851d698f8f17672eeccbe.sha256
</span></span><span style="display:flex;"><span>  977e50e9421f0a2749587de6a887ba63f2ddf9109d27ab7cae895a6664b2711a.sha256: Fetching remote state to .state/977e50e9421f0a2749587de6a887ba63f2ddf9109d27ab7cae895a6664b2711a.sha256
</span></span><span style="display:flex;"><span>  977e50e9421f0a2749587de6a887ba63f2ddf9109d27ab7cae895a6664b2711a.sha256: Storing state from .state/977e50e9421f0a2749587de6a887ba63f2ddf9109d27ab7cae895a6664b2711a.sha256
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">==</span>&gt; Building
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">==</span>&gt; Done
</span></span><span style="display:flex;"><span>  Storing dist/index.js
</span></span><span style="display:flex;"><span>  c2bac686e507434398d9bf4e33f63f275dfd3bfecfe851d698f8f17672eeccbe.sha256: Storing artifact dist/index.js
</span></span><span style="display:flex;"><span>  c2bac686e507434398d9bf4e33f63f275dfd3bfecfe851d698f8f17672eeccbe.sha256: Storing state from .state/c2bac686e507434398d9bf4e33f63f275dfd3bfecfe851d698f8f17672eeccbe.sha256
</span></span><span style="display:flex;"><span>$ cat dist/index.js
</span></span><span style="display:flex;"><span>  compiled at la 17.9.2022 13.16.48 +0300
</span></span></code></pre></div><p>If we now clean the repository and build again, we should end up with all the artifacts from the original build but no build process actually running:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ git clean -dxf
</span></span><span style="display:flex;"><span>$ make build
</span></span><span style="display:flex;"><span>  c2bac686e507434398d9bf4e33f63f275dfd3bfecfe851d698f8f17672eeccbe.sha256: Fetching remote state to .state/c2bac686e507434398d9bf4e33f63f275dfd3bfecfe851d698f8f17672eeccbe.sha256
</span></span><span style="display:flex;"><span>  c2bac686e507434398d9bf4e33f63f275dfd3bfecfe851d698f8f17672eeccbe.sha256: Fetching dist/index.js
</span></span><span style="display:flex;"><span>  977e50e9421f0a2749587de6a887ba63f2ddf9109d27ab7cae895a6664b2711a.sha256: Fetching remote state to .state/977e50e9421f0a2749587de6a887ba63f2ddf9109d27ab7cae895a6664b2711a.sha256
</span></span><span style="display:flex;"><span>  make: Nothing to be <span style="color:#66d9ef">done</span> <span style="color:#66d9ef">for</span> <span style="color:#e6db74">&#39;build&#39;</span>.
</span></span><span style="display:flex;"><span>$ cat dist/index.js
</span></span><span style="display:flex;"><span>  compiled at la 17.9.2022 13.16.48 +0300
</span></span></code></pre></div><h2 id="extra-features">Extra Features</h2>
<p>I added a <code>CAS_READ_ONLY</code> environment variable, which by default prevents the scripts from pushing state and artifacts to remote storage but does allow fetching from storage.  The idea of this is that local development can make use of the caches, but only CI machines can write to the cache:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>CAS_REMOTE<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$CAS_READ_ONLY<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;0&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span></span></span></code></pre></div><footer style="margin: 10px auto;">
  <small><a href="https://github.com/Pondidum/make-cas/blob/b40aabf2affa88a4d8f143ac5895354d4e932bad/build/artifact.sh">Source</a></small>
</footer>

<h2 id="wrapping-up">Wrapping Up</h2>
<p>Overall, I am very happy with how this has gone; it all works, and hopefully I&rsquo;ll be testing it in parallel to normal build processes over the coming weeks.</p>
]]></content:encoded></item><item><title>Embedding ain't easy, but its alright</title><link>https://andydote.co.uk/2022/09/14/embed/</link><pubDate>Wed, 14 Sep 2022 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2022/09/14/embed/</guid><description>I write a lot of blog posts which contain code snippets. Like most people, I have done this using a fenced codeblock in markdown which is fine for short blocks of code.
The problem occours when I am embedding code from another repository; often there will be tweaks or bug fixes, and keeping the code in the blog post in sync with the code in the other repo is annoying and manual.</description><content:encoded><![CDATA[<p>I write a lot of blog posts which contain code snippets.  Like most people, I have done this using a fenced codeblock in markdown which is fine for short blocks of code.</p>
<p>The problem occours when I am embedding code from another repository; often there will be tweaks or bug fixes, and keeping the code in the blog post in sync with the code in the other repo is annoying and manual.</p>
<p>To make life easier for myself, I wrote a <a href="https://gohugo.io/content-management/shortcodes/">shortcode</a> called <code>git-embed</code>, which at build time will fetch the specified file, and embed either the whole file, or a line range in a highlighted code block.  It supports line ranges (<code>start</code>, <code>finish</code>), and it will use the <code>file</code>&rsquo;s extension as the highlight language, unless you override with <code>lang</code> parameter.</p>
<p>Usage is like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>{{&lt; <span style="color:#f92672">git-embed</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">user</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Pondidum&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">repo</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;pondidum.github.io&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ref</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;master&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">file</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;layouts/shortcodes/git-embed.html&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">lang</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;go&#34;</span>
</span></span><span style="display:flex;"><span>&gt;}}
</span></span></code></pre></div><p>Which I am using to embed the shorcode&rsquo;s own shortcode:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">user</span> <span style="color:#f92672">:=</span> .<span style="color:#a6e22e">Get</span> <span style="color:#e6db74">&#34;user&#34;</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">repo</span> <span style="color:#f92672">:=</span> .<span style="color:#a6e22e">Get</span> <span style="color:#e6db74">&#34;repo&#34;</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">ref</span> <span style="color:#f92672">:=</span> .<span style="color:#a6e22e">Get</span> <span style="color:#e6db74">&#34;ref&#34;</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">file</span> <span style="color:#f92672">:=</span> .<span style="color:#a6e22e">Get</span> <span style="color:#e6db74">&#34;file&#34;</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">source</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">printf</span> <span style="color:#e6db74">&#34;https://github.com/%s/%s/blob/%s/%s&#34;</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">user</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">repo</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">ref</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">file</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">url</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">printf</span> <span style="color:#e6db74">&#34;https://raw.githubusercontent.com/%s/%s/%s/%s&#34;</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">user</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">repo</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">ref</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">file</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">remote</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">resources</span>.<span style="color:#a6e22e">GetRemote</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">url</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{{ <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">all_lines</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">split</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">remote</span>.<span style="color:#a6e22e">Content</span> <span style="color:#e6db74">&#34;\n&#34;</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">start</span> <span style="color:#f92672">:=</span> <span style="color:#ae81ff">1</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">isset</span> .<span style="color:#a6e22e">Params</span> <span style="color:#e6db74">&#34;start&#34;</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>  {{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">start</span> = (.<span style="color:#a6e22e">Get</span> <span style="color:#e6db74">&#34;start&#34;</span>) | <span style="color:#66d9ef">int</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#a6e22e">end</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">finish</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">len</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">all_lines</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">isset</span> .<span style="color:#a6e22e">Params</span> <span style="color:#e6db74">&#34;finish&#34;</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>  {{ <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">finish</span> = (.<span style="color:#a6e22e">Get</span> <span style="color:#e6db74">&#34;finish&#34;</span>) | <span style="color:#66d9ef">int</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#a6e22e">end</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">start</span> = <span style="color:#a6e22e">math</span>.<span style="color:#a6e22e">Max</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">start</span> <span style="color:#ae81ff">1</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">finish</span> = <span style="color:#a6e22e">math</span>.<span style="color:#a6e22e">Min</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">finish</span> (<span style="color:#a6e22e">len</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">all_lines</span>) <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">lines</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">slice</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#66d9ef">range</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">index</span>, <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">num</span> <span style="color:#f92672">:=</span> (<span style="color:#a6e22e">seq</span> (<span style="color:#a6e22e">add</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">start</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>) (<span style="color:#a6e22e">add</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">finish</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>)) <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>  {{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">lines</span> = <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">lines</span> | <span style="color:#a6e22e">append</span> (<span style="color:#a6e22e">index</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">all_lines</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">num</span>) <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#a6e22e">end</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">lang</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">strings</span>.<span style="color:#a6e22e">TrimPrefix</span> <span style="color:#e6db74">&#34;.&#34;</span> (<span style="color:#a6e22e">path</span>.<span style="color:#a6e22e">Ext</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">file</span>) <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">isset</span> .<span style="color:#a6e22e">Params</span> <span style="color:#e6db74">&#34;lang&#34;</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>  {{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">lang</span> = .<span style="color:#a6e22e">Get</span> <span style="color:#e6db74">&#34;lang&#34;</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#a6e22e">end</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">options</span> <span style="color:#f92672">:=</span> <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">isset</span> .<span style="color:#a6e22e">Params</span> <span style="color:#e6db74">&#34;options&#34;</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>  {{<span style="color:#f92672">-</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">options</span> = .<span style="color:#a6e22e">Get</span> <span style="color:#e6db74">&#34;options&#34;</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#a6e22e">end</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{{<span style="color:#f92672">-</span> <span style="color:#a6e22e">highlight</span> ( <span style="color:#a6e22e">delimit</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">lines</span> <span style="color:#e6db74">&#34;\n&#34;</span>) <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">lang</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#a6e22e">options</span> <span style="color:#f92672">-</span>}}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&lt;<span style="color:#a6e22e">footer</span> <span style="color:#a6e22e">style</span>=<span style="color:#e6db74">&#34;margin: 10px auto;&#34;</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#a6e22e">small</span>&gt;&lt;<span style="color:#a6e22e">a</span> <span style="color:#a6e22e">href</span>=<span style="color:#e6db74">&#34;{{- $source -}}&#34;</span>&gt;<span style="color:#a6e22e">Source</span>&lt;<span style="color:#f92672">/</span><span style="color:#a6e22e">a</span>&gt;&lt;<span style="color:#f92672">/</span><span style="color:#a6e22e">small</span>&gt;
</span></span><span style="display:flex;"><span>&lt;<span style="color:#f92672">/</span><span style="color:#a6e22e">footer</span>&gt;
</span></span></code></pre></div><footer style="margin: 10px auto;">
  <small><a href="https://github.com/Pondidum/pondidum.github.io/blob/master/layouts/shortcodes/git-embed.html">Source</a></small>
</footer>

<h2 id="future-improvements">Future Improvements</h2>
<p>I&rsquo;d quite like to add a parameter that would allow me to embed a named function, rather than a line range.  I think I&rsquo;d use <a href="https://tree-sitter.github.io/tree-sitter/">Tree-Sitter</a> to do this, but Hugo doesn&rsquo;t seem to have a way to execute an arbitrary command on build, so I&rsquo;d need to make a small API that would do all the work&hellip;  So that can wait for when the itch needs scratching more than this.</p>
]]></content:encoded></item><item><title>The reports of UML's death are greatly exaggerated</title><link>https://andydote.co.uk/2022/09/11/uml-isnt-dead/</link><pubDate>Sun, 11 Sep 2022 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2022/09/11/uml-isnt-dead/</guid><description>This is in response to the recent posts about the death of UML; while I think some parts of UML have fallen ill, the remaining parts are still alive, and useful to this day.
TLDR Out of 14 types of diagram there are 3 that I use on a regular basis: Activity Diagram, State Machine Diagram, and Sequence Diagram. I think the Timing Diagram is borderline, but I can only think of a couple of occasions when it has been useful.</description><content:encoded><![CDATA[<p>This is in response to the <a href="https://buttondown.email/hillelwayne/archive/why-uml-really-died/">recent</a> <a href="https://garba.org/posts/2021/uml/">posts</a> about the death of UML;  while I think some parts of UML have fallen ill, the remaining parts are still alive, and useful to this day.</p>
<h2 id="tldr">TLDR</h2>
<p>Out of <a href="https://creately.com/blog/diagrams/uml-diagram-types-examples/">14 types of diagram</a> there are 3 that I use on a regular basis: <strong>Activity Diagram</strong>, <strong>State Machine Diagram</strong>, and <strong>Sequence Diagram</strong>.  I think the Timing Diagram is borderline, but I can only think of a couple of occasions when it has been useful.</p>
<p>Writing the diagrams in text and rendering them with <a href="https://mermaid-js.github.io/mermaid/#/">Mermaid</a> makes including them in documentation and websites painless, and the project is under active development.</p>
<h2 id="what-i-use-often">What I use often</h2>
<p>The diagram I use the most is the <strong>Sequence Diagram</strong>;  It&rsquo;s a great way to document how multiple systems (or micro services) will interact with each other.  This diagram type has worked really well on both physical whiteboards, and in documentation.  For example, part of a diagram I used to help design a system recently:</p>

<div class="mermaid" align="left">
sequenceDiagram
    participant api
    participant cas
    participant storage

    api ->>+cas: dependencies

    alt exists
        cas ->>+storage: get key
        storage ->>-cas: key, date
    else doesn't exist
        cas ->>+storage: get key
        storage ->>-cas: [not found]
        cas ->>+storage: write key, now()
        storage ->>-cas: [ok]
    end

    cas ->>-api: key path
</div>
<p>Next most used is the <strong>Activity Diagram</strong>, also more commonly known as a <strong>Flow Chart</strong>.  This is mostly used when discribing an algorithm or process without needing to indicate different participants in the algorithm.</p>

<div class="mermaid" align="left">
graph LR
    deps[key Dependencies]
    in_store{key in Storage?}
    write_to_store[key + current date to storage]
    update_date[Update store date from file]
    return[return key path]

    deps --> in_store
    in_store -->|Yes| update_date --> return
    in_store -->|No| write_to_store --> return
</div>
<p>The last type that I use often is the <strong>State Machine Diagram</strong>;  I think that State Machines themselves are an under utilised design pattern, and that a lot of complex problems can be rendered into the state pattern quite easily.</p>
<p>In a previous job there was a state machine with around 34 different states; being able to render this in a diagram made understanding the process much more approachable; even our support staff used the diagram to answer user questions.</p>
<p>For example, a line processor could be represented as follows, where depending on the kind of error the process will either terminate, or skip the line and wait for the next:</p>

<div class="mermaid" align="left">
stateDiagram
    state "Wait for Line" as wait
    state "Process Line" as process

    [*] --> wait
    wait --> process
    process --> wait
    process --> Error
    Error --> wait
    Error --> [*]
</div>
<h2 id="who-else-is-using-uml">Who else is using UML?</h2>
<p>The <a href="https://mermaid-js.github.io/mermaid/#/">Mermaid</a> library to render these kind of diagrams is being integrated all over the place:  Github uses it to handle any <code>```mermaid</code> blocks in your markdown files.</p>
<p>Likewise, <a href="https://gohugo.io/">Hugo</a> uses it when rendering your markdown content too (which is what has drawn these nice diagrams here.)</p>
<p>There are <a href="https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid">extensions for vscode</a> to render them too.</p>
<h2 id="why-should-i-care">Why should I care?</h2>
<p>Because explaining concepts is hard; and pictures often help.  The old phrase of a picture being worth a thousand words is applicable here; its far easier to glance over a diagram than read a few paragraphs of prose.</p>
<p>This being the case, it is a good idea to have some common formats, standards or symbols to use, making the diagrams even clearer to people who already know the symbols (and don&rsquo;t forget to explain them if they don&rsquo;t know, and perhaps include a legend in your diagram.)</p>
<p>When creating these diagrams was done in tools like Visio, and then screenshots embedded in documents (usually buried in a wiki where no one will find them), the barrier to making a useful diagram was high.  Being able to embed them in the markdown in your repo, <em>so they can be read from code even if they aren&rsquo;t rendered</em> lowers that barrier to making useful diagrams considerably.</p>
<p>So do your co-workers, contributors, and your future-self a favour, and add some simple diagrams to your docs.</p>
]]></content:encoded></item><item><title>Pulumi Conditional Infrastructure for Speed</title><link>https://andydote.co.uk/2022/07/17/pulumi-faster-processes/</link><pubDate>Sun, 17 Jul 2022 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2022/07/17/pulumi-faster-processes/</guid><description>One of the reasons I prefer Pulumi over Terraform is the additional control I have over my processes due to the fact that it&amp;rsquo;s a programming language.
For example, I have a CLI, that creates a cluster of machines for a user; the machines use IAM Authentication with Vault so that they can request certificates on boot. The trouble with this application is that it is slow; it takes 175 seconds on average to provision the machines, write the IAM information to Vault, and then re-run the cloud-init script on all the machines in the cluster (as when they first booted, the configuration hadn&amp;rsquo;t been written to Vault yet.</description><content:encoded><![CDATA[<p>One of the reasons I prefer <a href="https://pulumi.com">Pulumi</a> over <a href="https://terraform.io">Terraform</a> is the additional control I have over my processes due to the fact that it&rsquo;s a programming language.</p>
<p>For example, I have a CLI, that creates a cluster of machines for a user; the machines use IAM Authentication with <a href="https://www.vaultproject.io">Vault</a> so that they can request certificates on boot.  The trouble with this application is that it is slow; it takes 175 seconds on average to provision the machines, write the IAM information to Vault, and then re-run the cloud-init script on all the machines in the cluster (as when they first booted, the configuration hadn&rsquo;t been written to Vault yet.) so that they can request a certificate.  The process is roughly this:</p>
<ul>
<li>Create infrastructure</li>
<li>Write configuration to Vault</li>
<li>Wait for the machines to be ready</li>
<li>Wait for SSH</li>
<li>Re-run cloud-init</li>
</ul>
<p>The CLI can&rsquo;t write the configuration to Vault before the machines boot, as the configuration values are from the same infrastructure stack as the machines themselves.  You can see the process in the <a href="https://honeycomb.io">Honeycomb</a> trace UI (with more details about what infra is created thanks to my <a href="/2021/03/01/observability-with-infrastructure-as-code/">pulumi-honeycomb stream adaptor</a>):</p>
<p><img loading="lazy" src="pulumi-infra-slow.png" alt="pulumi trace showing execution time of 175 seconds"  />
</p>
<p>I don&rsquo;t want to make two separate stacks for this, one containing IAM Roles and other configuration data, the other containing all the other infrastructure (load balancers, auto-scale groups, etc.)  But what if I could dynamically change what the stack does?</p>
<p>By adding an <code>IsInit</code> property to the configuration of the stack, we can change the pulumi program to return early when the value of <code>IsInit</code> is <code>true</code>, meaning we only create the minimal amount of infrastructure for the configuration call to succeed:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">DefineInfrastructure</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">pulumi</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">cfg</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">ClusterConfiguration</span>) <span style="color:#66d9ef">error</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">role</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">iam</span>.<span style="color:#a6e22e">NewRole</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">Name</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#34;-iam-role&#34;</span>, <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">iam</span>.<span style="color:#a6e22e">RoleArgs</span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">NamePrefix</span>:       <span style="color:#a6e22e">pulumi</span>.<span style="color:#a6e22e">String</span>(<span style="color:#a6e22e">Name</span>),
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">AssumeRolePolicy</span>: <span style="color:#a6e22e">allowEc2Json</span>,
</span></span><span style="display:flex;"><span>  })
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">iam</span>.<span style="color:#a6e22e">NewRolePolicy</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">Name</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#34;-iam-policy-cluster&#34;</span>, <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">iam</span>.<span style="color:#a6e22e">RolePolicyArgs</span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">NamePrefix</span>: <span style="color:#a6e22e">pulumi</span>.<span style="color:#a6e22e">String</span>(<span style="color:#a6e22e">Name</span>),
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">Role</span>:       <span style="color:#a6e22e">role</span>.<span style="color:#a6e22e">ID</span>(),
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">Policy</span>:     <span style="color:#a6e22e">findMachinesJson</span>,
</span></span><span style="display:flex;"><span>  })
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">Export</span>(<span style="color:#e6db74">&#34;role-arn&#34;</span>, <span style="color:#a6e22e">role</span>.<span style="color:#a6e22e">Arn</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>  <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">cfg</span>.<span style="color:#a6e22e">IsInit</span> {
</span></span><span style="display:flex; background-color:#3c3d38"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex; background-color:#3c3d38"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">asg</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">autoscaling</span>.<span style="color:#a6e22e">NewGroup</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">Name</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#34;-asg&#34;</span>, <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">autoscaling</span>.<span style="color:#a6e22e">GroupArgs</span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">LaunchConfiguration</span>: <span style="color:#a6e22e">createLaunchConfiguration</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">cfg</span>, <span style="color:#a6e22e">role</span>),
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">VpcZoneIdentifiers</span>:  <span style="color:#a6e22e">cfg</span>.<span style="color:#a6e22e">ZoneIdentifiers</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">DesiredCapacity</span>:     <span style="color:#a6e22e">cfg</span>.<span style="color:#a6e22e">ClusterSize</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">MinSize</span>:             <span style="color:#a6e22e">cfg</span>.<span style="color:#a6e22e">ClusterSize</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">MaxSize</span>:             <span style="color:#a6e22e">cfg</span>.<span style="color:#a6e22e">ClusterSize</span>,
</span></span><span style="display:flex;"><span>  })
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">Export</span>(<span style="color:#e6db74">&#34;asg-name&#34;</span>, <span style="color:#a6e22e">asg</span>.<span style="color:#a6e22e">Name</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Now that the stack can be run to create only partial infrastructure, the process changes to this:</p>
<ul>
<li>Create minimal infrastructure</li>
<li>Write configuration to Vault</li>
<li>Create remaining infrastructure</li>
</ul>
<p>But is the new process faster?  I had hoped it would be a little faster, as waiting for cloud-init and SSH can take a while, and thankfully, it is significantly faster.  It takes on average 98 seconds, so around 77 seconds faster.</p>
<p><img loading="lazy" src="pulumi-infra-fast.png" alt="pulumi trace showing execution time of 98 seconds"  />
</p>
<p>Comparing the before and after traces, I can see that the additional pulumi call adds 20 seconds to the processes, but the <code>consul_configure</code> span drops from 100 seconds to 3.5, which is quite the speed increase.</p>
<h2 id="what-about-terraform">What about Terraform?</h2>
<p>This is still possible to do with a terraform stack, but not in a pleasant way; in pulumi I can return early from the infra function, but with terraform, I would have to add a <code>count = var.is_init ?  0 : 1</code> to every resource I didn&rsquo;t want to create up front, which quickly becomes unwieldy.</p>
<p>There is also the downside of not being able to embed the Terraform inside a CLI tool like I can with Pulumi.</p>
<p>Overall, I am happy with how this has turned out.  The diff for enabling this optimisation is 3 files changed, 15 insertions, 7 deletions, which included some explanatory comments!</p>
]]></content:encoded></item><item><title>An NGINX and DNS based outage</title><link>https://andydote.co.uk/2022/04/23/nginx-dns/</link><pubDate>Sat, 23 Apr 2022 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2022/04/23/nginx-dns/</guid><description>I recently encountered a behaviour in Nginx that I didn&amp;rsquo;t expect and caused a production outage in the process. While I would love to blame DNS for this, as it&amp;rsquo;s usually the cause of most network-related issues, in this case, the fault lies with Nginx.
I was running a very simple Nginx proxy, relaying an internal service to the outside world. The internal service is behind an AWS ALB, and the Nginx configuration was proxying to the ALB&amp;rsquo;s FQDN:</description><content:encoded><![CDATA[<p>I recently encountered a behaviour in Nginx that I didn&rsquo;t expect and caused a production outage in the process.  While I would love to blame DNS for this, as it&rsquo;s usually the cause of most network-related issues, in this case, the fault lies with Nginx.</p>
<p>I was running a very simple Nginx proxy, relaying an internal service to the outside world.  The internal service is behind an AWS ALB, and the Nginx configuration was proxying to the ALB&rsquo;s FQDN:</p>
<pre tabindex="0"><code>http {
  server {
    listen              8000;
    server_name         server.example.com;

    location ~* ^/some/path {
      proxy_pass              https://some.internal.alb.address.amazonaws.com;
      proxy_set_header        Host $host;
      proxy_read_timeout      120;
      proxy_ignore_headers    Cache-Control;
      proxy_ignore_headers    Expires;
      proxy_ignore_headers    Set-Cookie;
    }
  }
}
</code></pre><p>The proxy was working fine for several weeks, until suddenly it wasn&rsquo;t.  To make matters more strange, when we checked the internal site directly, it showed as up and responding.  No deployments of any services had happened, and we had made no changes in any infrastructure either.  We restarted the Nginx service, and everything started working again.</p>
<p>The first is that AWS&rsquo;s can, and does, change the IP addresses associated with load balancers.  This can happen for many unknown reasons as the underlying implementation of the AWS load balancers is a black box.  One known reason is the load balancer scaling to handle more or less traffic.  There is no API that we are aware of that allows you to see when these changes have happened; the only way we know is to run <code>dig</code> in a loop and send the results to our observability tool when they change.</p>
<p>The second detail is how Nginx resolves DNS.  My initial expectation was that it worked like most DNS clients, and would query an address on the first request and then again after the TTL had elapsed.  It turns out my assumption was wrong, and that by default, Nginx queries addresses once on startup, <em>and never again</em>.</p>
<p>So with these two facts, we can see why the proxy stopped working at some point; the target ALB had removed whichever IP address(es) Nginx had received from DNS at startup.  There are two different ways this can be fixed.</p>
<p>The first way is to force Nginx to cache all IPs resolved for a fixed time window:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span>http {
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">+  resolver_timeout 30s;
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>
</span></span><span style="display:flex;"><span>  server {
</span></span><span style="display:flex;"><span>    listen              8000;
</span></span><span style="display:flex;"><span>    server_name         server.example.com;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    location ~* ^/some/path {
</span></span></code></pre></div><p>The second fix is to cause Nginx to re-resolve the upstream when it&rsquo;s DNS record expires (based on the DNS TTL):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span>http {
</span></span><span style="display:flex;"><span>  server {
</span></span><span style="display:flex;"><span>    listen              8000;
</span></span><span style="display:flex;"><span>    server_name         server.example.com;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">+    set $upstream some.internal.alb.address.amazonaws.com;
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>
</span></span><span style="display:flex;"><span>    location ~* ^/some/path {
</span></span><span style="display:flex;"><span><span style="color:#f92672">-     proxy_pass              https://some.internal.alb.address.amazonaws.com;
</span></span></span><span style="display:flex;"><span><span style="color:#f92672"></span><span style="color:#a6e22e">+     proxy_pass              https://$upstream;
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>      proxy_set_header        Host $host;
</span></span><span style="display:flex;"><span>      proxy_read_timeout      120;
</span></span><span style="display:flex;"><span>      proxy_ignore_headers    Cache-Control;
</span></span><span style="display:flex;"><span>      proxy_ignore_headers    Expires;
</span></span><span style="display:flex;"><span>      proxy_ignore_headers    Set-Cookie;
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><p>While I am glad there are two easy ways to solve this issue, I still find the default &ldquo;only resolve once at startup&rdquo; behaviour odd, as it goes against the <a href="https://en.wikipedia.org/wiki/Principle_of_least_astonishment">Principle of least surprise</a>;  I expect Nginx to re-query based on the TTL of the DNS Record.  I suspect this behaviour exists for performance reasons, but I don&rsquo;t know for sure.</p>
]]></content:encoded></item><item><title>The Operator Pattern in Nomad</title><link>https://andydote.co.uk/2021/11/22/nomad-operator-pattern/</link><pubDate>Mon, 22 Nov 2021 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2021/11/22/nomad-operator-pattern/</guid><description>The Operator Pattern from Kubernetes is an excellent way of handling tasks in a cluster in an automated way, for example, provisioning applications, running backups, requesting certificates, and injecting chaos testing.
As a Nomad user, I wanted to do something similar for my clusters, so I set about seeing how it would be possible. It turns out; it is much easier than I expected! While Nomad doesn&amp;rsquo;t support the idea of Custom Resource Definitions, we can achieve an operator by utilising a regular Nomad job and the nomad HTTP API.</description><content:encoded><![CDATA[<p>The <a href="https://kubernetes.io/docs/concepts/extend-kubernetes/operator/">Operator Pattern</a> from Kubernetes is an excellent way of handling tasks in a cluster in an automated way, for example, provisioning applications, running backups, requesting certificates, and injecting chaos testing.</p>
<p>As a Nomad user, I wanted to do something similar for my clusters, so I set about seeing how it would be possible.  It turns out; it is much easier than I expected!  While Nomad doesn&rsquo;t support the idea of Custom Resource Definitions, we can achieve an operator by utilising a regular Nomad job and the nomad HTTP API.</p>
<h2 id="the-setup">The Setup</h2>
<p>We&rsquo;re going to build an automated backup operator!  We&rsquo;ll use the  <a href="https://www.nomadproject.io/api-docs/events">Nomad Streaming API</a> to watch for jobs being registered and deregistered.  If a job has some metadata for auto backup, we&rsquo;ll create (or update) a backup job.  If a job is deregistered or doesn&rsquo;t have any auto backup metadata, we&rsquo;ll try to delete a backup job if it exists.</p>
<p>The complete source code is available in the <a href="https://github.com/Pondidum/nomad-operator">Nomad-Operator</a> repo on my GitHub.</p>
<h2 id="consuming-the-nomad-streaming-api">Consuming the Nomad Streaming API</h2>
<p>The <a href="https://pkg.go.dev/github.com/hashicorp/nomad/api">Nomad Go API library</a> makes it easy to consume the streaming API, handling all the details, such as deserialisation for us.</p>
<p>The client is created with no additional parameters, as the <code>Address</code> and <code>SecretID</code> will be populated from environment variables automatically (<code>NOMAD_ADDR</code> and <code>NOMAD_TOKEN</code> respectively):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">client</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">NewClient</span>(<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">Config</span>{})
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As we want to only listen to jobs that have been modified after our application deploys, we need to query what the current job index is at startup:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">index</span> <span style="color:#66d9ef">uint64</span> = <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">meta</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">client</span>.<span style="color:#a6e22e">Jobs</span>().<span style="color:#a6e22e">List</span>(<span style="color:#66d9ef">nil</span>); <span style="color:#a6e22e">err</span> <span style="color:#f92672">==</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">index</span> = <span style="color:#a6e22e">meta</span>.<span style="color:#a6e22e">LastIndex</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Next, we use the <code>EventStream</code> API and subscribe to all job event types (in practice, this means <code>JobRegistered</code>, <code>JobDeregistered</code>, and <code>JobBatchDeregistered</code>):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">topics</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">map</span>[<span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">Topic</span>][]<span style="color:#66d9ef">string</span>{
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">TopicJob</span>: {<span style="color:#e6db74">&#34;*&#34;</span>},
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">eventsClient</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">client</span>.<span style="color:#a6e22e">EventStream</span>()
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">eventCh</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">eventsClient</span>.<span style="color:#a6e22e">Stream</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">topics</span>, <span style="color:#a6e22e">index</span>, <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">QueryOptions</span>{})
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>Stream(...)</code> call itself returns a channel which we can loop over forever consuming events, ignoring the heartbeat events:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">select</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">case</span> <span style="color:#f92672">&lt;-</span><span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">Done</span>():
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">case</span> <span style="color:#a6e22e">event</span> <span style="color:#f92672">:=</span> <span style="color:#f92672">&lt;-</span><span style="color:#a6e22e">eventCh</span>:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">event</span>.<span style="color:#a6e22e">IsHeartbeat</span>() {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">continue</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">handleEvent</span>(<span style="color:#a6e22e">event</span>)
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Finally, this operator only cares about jobs being registered and deregistered, so we loop through all the events and only handle the <code>JobRegistered</code> and <code>JobDeregistered</code> events:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">e</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">event</span>.<span style="color:#a6e22e">Events</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">e</span>.<span style="color:#a6e22e">Type</span> <span style="color:#f92672">!=</span> <span style="color:#e6db74">&#34;JobRegistered&#34;</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">e</span>.<span style="color:#a6e22e">Type</span> <span style="color:#f92672">!=</span> <span style="color:#e6db74">&#34;JobDeregistered&#34;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">job</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">e</span>.<span style="color:#a6e22e">Job</span>()
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">onJob</span>(<span style="color:#a6e22e">e</span>.<span style="color:#a6e22e">Type</span>, <span style="color:#a6e22e">job</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="handling-jobs">Handling Jobs</h2>
<p>When we see jobs, we need to handle a few different cases:</p>
<ul>
<li>Jobs which are backup jobs themselves should be ignored</li>
<li>Jobs without backup settings should have their backup job removed (if it exists)</li>
<li>Jobs with backup settings should have their job created (or updated if it exists)</li>
<li>Deregistered jobs should have their backup job removed (if it exists)</li>
</ul>
<p>We&rsquo;re using the job level <code>meta</code> stanza in the <code>.nomad</code> files for our settings, which looks something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-hcl" data-lang="hcl"><span style="display:flex;"><span><span style="color:#66d9ef">task</span> <span style="color:#e6db74">&#34;server&#34;</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">meta</span> {
</span></span><span style="display:flex;"><span>    auto-backup <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>    backup-schedule <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;@daily&#34;</span>
</span></span><span style="display:flex;"><span>    backup-target-db <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;postgres&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> (<span style="color:#a6e22e">b</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">Backup</span>) <span style="color:#a6e22e">OnJob</span>(<span style="color:#a6e22e">eventType</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">job</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">Job</span>) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">strings</span>.<span style="color:#a6e22e">HasPrefix</span>(<span style="color:#f92672">*</span><span style="color:#a6e22e">job</span>.<span style="color:#a6e22e">ID</span>, <span style="color:#e6db74">&#34;backup-&#34;</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">backupID</span> <span style="color:#f92672">:=</span> <span style="color:#e6db74">&#34;backup-&#34;</span> <span style="color:#f92672">+</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">job</span>.<span style="color:#a6e22e">ID</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">settings</span>, <span style="color:#a6e22e">enabled</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">b</span>.<span style="color:#a6e22e">parseMeta</span>(<span style="color:#a6e22e">job</span>.<span style="color:#a6e22e">Meta</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">eventType</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;JobDeregistered&#34;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">b</span>.<span style="color:#a6e22e">tryRemoveBackupJob</span>(<span style="color:#a6e22e">backupID</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> !<span style="color:#a6e22e">enabled</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">b</span>.<span style="color:#a6e22e">tryRemoveBackupJob</span>(<span style="color:#a6e22e">backupID</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">b</span>.<span style="color:#a6e22e">createBackupJob</span>(<span style="color:#a6e22e">backupID</span>, <span style="color:#a6e22e">settings</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Attempting to remove the job is straightforward as we don&rsquo;t care if it fails - it could be that the job doesn&rsquo;t exist, or is already stopped, or any other number of reasons, so we can use the <code>Deregister()</code> call and discard the output:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> (<span style="color:#a6e22e">b</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">Backup</span>) <span style="color:#a6e22e">tryRemoveBackupJob</span>(<span style="color:#a6e22e">jobID</span> <span style="color:#66d9ef">string</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">b</span>.<span style="color:#a6e22e">client</span>.<span style="color:#a6e22e">Jobs</span>().<span style="color:#a6e22e">Deregister</span>(<span style="color:#a6e22e">jobID</span>, <span style="color:#66d9ef">false</span>, <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">WriteOptions</span>{})
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Creating the backup job involves rendering a go template of the nomad file we will use, and then calling <code>Register</code> to submit the job to Nomad.  We&rsquo;re using the fact that our backup IDs are stable, so re-running the same backup ID will replace the job with a new version.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> (<span style="color:#a6e22e">b</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">Backup</span>) <span style="color:#a6e22e">createBackupJob</span>(<span style="color:#a6e22e">id</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">s</span> <span style="color:#a6e22e">settings</span>) <span style="color:#66d9ef">error</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">t</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">template</span>.<span style="color:#a6e22e">New</span>(<span style="color:#e6db74">&#34;&#34;</span>).<span style="color:#a6e22e">Delims</span>(<span style="color:#e6db74">&#34;[[&#34;</span>, <span style="color:#e6db74">&#34;]]&#34;</span>).<span style="color:#a6e22e">Parse</span>(<span style="color:#a6e22e">backupHcl</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">buffer</span> <span style="color:#a6e22e">bytes</span>.<span style="color:#a6e22e">Buffer</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">t</span>.<span style="color:#a6e22e">Execute</span>(<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">buffer</span>, <span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">backup</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">jobspec</span>.<span style="color:#a6e22e">Parse</span>(<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">buffer</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">b</span>.<span style="color:#a6e22e">client</span>.<span style="color:#a6e22e">Jobs</span>().<span style="color:#a6e22e">Register</span>(<span style="color:#a6e22e">backup</span>, <span style="color:#66d9ef">nil</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The nomad file is embedded using the Go <a href="https://pkg.go.dev/embed">embed</a> package to store the <code>.nomad</code> file in the binary, so we still have a single artefact to deploy:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#75715e">//go:embed backup.nomad
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">backupHcl</span> <span style="color:#66d9ef">string</span>
</span></span></code></pre></div><p>And the <code>backup.nomad</code> file itself is a go template with custom delimiters (<code>[[</code> and <code>]]</code>) for fields, as the <code>.nomad</code> file, can contain <code>{{ }}</code> when using the inbuilt templating for populating secrets, amongst other things:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>job <span style="color:#e6db74">&#34;[[ .JobID ]]&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  datacenters <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;dc1&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;batch&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  periodic <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    cron             <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;[[ .Schedule ]]&#34;</span>
</span></span><span style="display:flex;"><span>    prohibit_overlap <span style="color:#f92672">=</span> true
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  group <span style="color:#e6db74">&#34;backup&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    task <span style="color:#e6db74">&#34;backup&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>      driver <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;docker&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      config <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>        image   <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;alpine:latest&#34;</span>
</span></span><span style="display:flex;"><span>        command <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;echo&#34;</span>
</span></span><span style="display:flex;"><span>        args    <span style="color:#f92672">=</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;backing up [[ .SourceJobID ]]&#39;s [[ .TargetDB ]] database&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      env <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>        PGHOST     <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;postgres.service.consul&#34;</span>
</span></span><span style="display:flex;"><span>        PGDATABASE <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;[[ .TargetDB ]]&#34;</span>
</span></span><span style="display:flex;"><span>        AWS_REGION <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;eu-west-1&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><h2 id="testing-manual">Testing (Manual)</h2>
<p>The great thing about developing against Nomad is that testing is straightforward.  We can start a local copy by running <code>nomad agent -dev</code>, and then run our application locally to check it works properly, <em>before</em> needing to package it up into a Docker container and deploying it to a real cluster.  It also doesn&rsquo;t need to be packaged in a container for Nomad; we could use <a href="https://www.nomadproject.io/docs/drivers/exec">Isolated Exec</a> or <a href="https://www.nomadproject.io/docs/drivers/raw_exec">Raw Exec</a> too.)</p>
<p>There is a <code>start.sh</code> script in the repository which will use <code>tmux</code> to start 3 terminals, one to run a Nomad agent in dev mode (<code>nomad agent -dev</code>), one to build and run the operator (<code>go build &amp;&amp; ./operator</code>), and one to register and deregister nomad jobs.</p>
<p>When all is ready, submit the example job with the following command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>nomad job run example.nomad
</span></span></code></pre></div><p>Will cause the following output in the operator&rsquo;s terminal:</p>
<pre tabindex="0"><code>==&gt; JobRegistered: example (pending)...
    Registering backup job
    Backup created: backup-example
--&gt; Done
==&gt; JobRegistered: backup-example (running)...
    Job is a backup, skipping
</code></pre><p>We can also check the Nomad UI, running on http://localhost:4646, which shows our two jobs:</p>
<p><img loading="lazy" src="nomad-backup-jobs.png" alt="nomad jobs showing the example service and the backup periodic job"  />
</p>
<p>Note how the <code>example</code> job is a <code>service</code>, which continuously runs, and the <code>backup-example</code> is a <code>periodic</code> job, scheduled to run daily.</p>
<p>Removing the example job  with the following command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>nomad job stop example
</span></span></code></pre></div><p>This will be seen by the operator, which will remove the backup job:</p>
<pre tabindex="0"><code>==&gt; JobDeregistered: example (running)...
    Trying to remove a backup, if any
==&gt; JobDeregistered: backup-example (dead)...
    Job is a backup, skipping
</code></pre><p>Note how it also sees the <code>backup-example</code> job being deregistered and ignores it as, in our case, backups don&rsquo;t have backups!</p>
<h2 id="testing-automated">Testing (Automated)</h2>
<p>We can also write automated tests in two ways for this operator; Tests that run against a saved or synthetic event stream, and tests that work in the same way as the manual test; start Nomad, run a test suite; stop Nomad.</p>
<p>Reading from a file of known events, we can test the <code>handleEvent</code> function directly:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">seenEvents</span> <span style="color:#f92672">:=</span> []<span style="color:#66d9ef">string</span>{}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">c</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">NewConsumer</span>(<span style="color:#66d9ef">nil</span>, <span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">eventType</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">job</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">Job</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">seenEvents</span> = append(<span style="color:#a6e22e">seenEvents</span>, <span style="color:#a6e22e">eventType</span>)
</span></span><span style="display:flex;"><span>})
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">line</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">strings</span>.<span style="color:#a6e22e">Split</span>(<span style="color:#a6e22e">eventsJson</span>, <span style="color:#e6db74">&#34;\n&#34;</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">events</span> <span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">Events</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">json</span>.<span style="color:#a6e22e">Unmarshal</span>([]byte(<span style="color:#a6e22e">line</span>), <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">events</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">handleEvent</span>(<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">events</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>.<span style="color:#a6e22e">Len</span>(<span style="color:#a6e22e">t</span>, <span style="color:#a6e22e">seenEvents</span>, <span style="color:#ae81ff">2</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>.<span style="color:#a6e22e">Equal</span>(<span style="color:#a6e22e">t</span>, []<span style="color:#66d9ef">string</span>{<span style="color:#e6db74">&#34;JobRegistered&#34;</span>, <span style="color:#e6db74">&#34;JobDeregistered&#34;</span>}, <span style="color:#a6e22e">seenEvents</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The other way of testing is running a nomad instance in dev mode next to the application and registering jobs to it.  Usually, when doing this, I would start the Nomad application before running the tests and then stop it after, to save the time of waiting for Nomad to start between each test:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">wait</span> <span style="color:#f92672">:=</span> make(<span style="color:#66d9ef">chan</span> <span style="color:#66d9ef">bool</span>, <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">client</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">NewClient</span>(<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">Config</span>{})
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>.<span style="color:#a6e22e">NoError</span>(<span style="color:#a6e22e">t</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">seenJobID</span> <span style="color:#f92672">:=</span> <span style="color:#e6db74">&#34;&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">c</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">NewConsumer</span>(<span style="color:#a6e22e">client</span>, <span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">eventType</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">job</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">Job</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">seenJobID</span> = <span style="color:#f92672">*</span><span style="color:#a6e22e">job</span>.<span style="color:#a6e22e">ID</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">wait</span> <span style="color:#f92672">&lt;-</span> <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>})
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">go</span> <span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">Start</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//register a job
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#a6e22e">job</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">jobspec</span>.<span style="color:#a6e22e">Parse</span>(<span style="color:#a6e22e">strings</span>.<span style="color:#a6e22e">NewReader</span>(<span style="color:#a6e22e">withBackupHcl</span>))
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>.<span style="color:#a6e22e">NoError</span>(<span style="color:#a6e22e">t</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">client</span>.<span style="color:#a6e22e">Jobs</span>().<span style="color:#a6e22e">Register</span>(<span style="color:#a6e22e">job</span>, <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">WriteOptions</span>{})
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// block until the job handler has run once
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#f92672">&lt;-</span><span style="color:#a6e22e">wait</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>.<span style="color:#a6e22e">Equal</span>(<span style="color:#a6e22e">t</span>, <span style="color:#f92672">*</span><span style="color:#a6e22e">job</span>.<span style="color:#a6e22e">ID</span>, <span style="color:#a6e22e">seenJobID</span>)
</span></span></code></pre></div><p>As this is running against a real copy of Nomad, we need to wait for jobs to be registered and only stop our test once things have been processed; hence we use a <code>bool</code> channel to block until our job handler has seen a job.</p>
<p>In a real test suite, you would need to make the job handler filter to the specific job it is looking for; as this would prevent shared state issues (currently this will stop after <em>any</em> job is seen), and thus allow you to run the tests in parallel.</p>
<h2 id="deployment">Deployment</h2>
<p>No operator pattern would be complete without pushing the operator itself into the Nomad cluster, and while we <em>could</em> just run the binary directly in Nomad (utilising the <a href="https://www.nomadproject.io/docs/job-specification/artifact">Artifact Stanza</a> and <a href="https://www.nomadproject.io/docs/drivers/exec">Isolated Exec</a>), its probably easier to create a docker container.</p>
<p>We have a single <code>Dockerfile</code> with a multistage build so that our output container only contains the binary itself, rather than all the layers and intermediate artefacts from the build process:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> golang:1.16.10-alpine3.14 as builder</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">WORKDIR</span><span style="color:#e6db74"> /app</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> go.mod go.sum ./<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> go mod download<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> . ./<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> go build<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> alpine:3.14 as output</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> --from<span style="color:#f92672">=</span>builder /app/operator /usr/local/bin/operator<span style="color:#960050;background-color:#1e0010">
</span></span></span></code></pre></div><p>Once the container is built and tagged:</p>
<pre tabindex="0"><code>docker build -t operator:local .
</code></pre><p>We can verify it works as intended by running the container directly; <code>--net=host</code> is passed to the <code>run</code> command so that the operator can connect to Nomad on <code>localhost:4646</code>, rather than having to pass in our host IP through an environment variable.  If you want to do this, add <code>-e NOMAD_ADDR=http://SOME_IP_OR_HOST:4646</code> to the <code>docker run</code> command:</p>
<pre tabindex="0"><code>docker run --rm -it --net=host operator:local
</code></pre><p>Assuming we&rsquo;re happy, we can run the Operator container in our local Nomad instance without pushing it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>task <span style="color:#e6db74">&#34;operator&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  driver <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;docker&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    image <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;operator:latest&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  template <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    data <span style="color:#f92672">=</span> <span style="color:#e6db74">&lt;&lt;EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    {{ with secret &#34;nomad/creds/operator-job&#34; }}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    NOMAD_TOKEN={{ .Data.secret_id  | toJSON }}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    {{ end }}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
</span></span><span style="display:flex;"><span>    destination <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;secrets/db.env&#34;</span>
</span></span><span style="display:flex;"><span>    env <span style="color:#f92672">=</span> true
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  env <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    NOMAD_ADDR <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;nomad.service.consul&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><h2 id="wrapping-up">Wrapping Up</h2>
<p>The Operator Pattern is a great way to handle everyday tasks that a cluster operator would normally, and I have used it to handle things like automatic backups, certificate generation (at least until Vault supports LetEncrypt), and job cleanup (for example, developer branch builds only stay in the cluster for 3 days.)</p>
]]></content:encoded></item><item><title>How do you tag docker images?</title><link>https://andydote.co.uk/2021/11/10/docker-tagging/</link><pubDate>Wed, 10 Nov 2021 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2021/11/10/docker-tagging/</guid><description>An interesting question came up at work today: how do you tag your Docker images? In previous projects, I&amp;rsquo;ve always used a short git sha, or sometimes a semver, but with no great consistency.
As luck would have it, I had pushed for a change in tagging format at a client not so long ago as the method we were using didn&amp;rsquo;t make a lot of sense and, worst of all, it was a manual process.</description><content:encoded><![CDATA[<p>An interesting question came up at work today: how do you tag your Docker images?  In previous projects, I&rsquo;ve always used a short git sha, or sometimes a semver, but with no great consistency.</p>
<p>As luck would have it, I had pushed for a change in tagging format at a client not so long ago as the method we were using didn&rsquo;t make a lot of sense and, worst of all, it was a <em>manual</em> process.  One of the things that I push at all clients is documenting all architectural decisions made, in the form of <a href="/2019/06/29/architecture-decision-records">Architecture Decision Records</a>, so I&rsquo;m reproducing it here, with a few details changed to mask where this happened.</p>
<p>One of the most interesting points of this is that I went in with an idea on the right way to do this, and over the course of discussion and review of the document, <em>changed my mind</em>.</p>
<hr>
<h2 id="change-versioning-scheme">Change Versioning Scheme</h2>
<h3 id="status">Status</h3>
<p>Accepted</p>
<h3 id="context">Context</h3>
<p>Currently, the UI uses a <a href="https://semver.org/">SemVer</a> style version number. However, we have no convention for what kind of modifications constitute a major, minor, or patch change.  We also have no processes or people who care specifically about what kind of change it is, just that a new version was deployed.</p>
<p>The other problem with using SemVer is that people wait until a branch has been approved, and then make an additional commit with the version number change (as another prod deployment might have happened in the meantime), meaning they need to wait for an additional build before they can deploy.</p>
<p>Not to mention, it&rsquo;s possible to accidentally go backwards in numbers if a value was misread or if someone forgets to update the version number in their branch.</p>
<h3 id="considered-options">Considered Options</h3>
<h4 id="1-auto-incrementing-integer-version">1. Auto-incrementing integer version</h4>
<p>On production deployment, we would write a version number to the application.  The negative of this approach is not having a version number in pre-production environments, such as test environments.</p>
<p>We could generate the number on the build phase (when the container is created), but this means that we might not release versions &ldquo;in order&rdquo;, as the order of what feature is deployed to production is not guaranteed, although the need to merge <code>master</code> into your branch would mean a rebuild, so a new version could be generated.</p>
<p>This method would also mean gaps in version numbers, as not all builds hit production, which might be a touch confusing.</p>
<p>Another issue with this method is that we build multiple containers from the same commit in separate pipelines, so we would need some way to generate a version in both pipelines which would match, which would mean either a function deriving from the commit hash or a service which would calculate and cache version numbers so they could be generated and looked up by multiple pipelines.</p>
<p>Example Version:</p>
<pre tabindex="0"><code>1870
</code></pre><h4 id="2-git-short-sha-of-the-commit">2. Git (short) sha of the commit</h4>
<p>On build, write the short (7 char) SHA as the version number.  The negative of this approach is not having an easy to understand order of version numbers.  However, this scheme means we can easily see exactly which commit is currently running in production (or any environment, for that matter.)</p>
<p>Example Version:</p>
<pre tabindex="0"><code>84d33bb
</code></pre><h4 id="3-build-id-from-ci-system">3. Build ID from CI System</h4>
<p>On build, embed the buildID as the version number.  The pipeline id is a 24 character string consisting of numbers and letters, so this is functionally similar to <a href="#2-git-short-sha-of-the-commit">Option 2</a>, but with a longer number that doesn&rsquo;t tie back to a commit.</p>
<p>As with <a href="#1-auto-incrementing-integer-version">Option 1</a>, we would need to decide if this number comes from the build pipeline, or from the deployment pipeline.  This also has the same multi-pipeline problem too.</p>
<p>Example Version:</p>
<pre tabindex="0"><code>611a0be261ddea19dab67c22
</code></pre><h4 id="4-datestamp">4. Datestamp</h4>
<p>On build, use the current commit&rsquo;s datestamp as the tag.</p>
<p>As long as we keep the resolution of the datestamp large enough, the multiple pipelines needing to generate the same ID shouldn&rsquo;t be a problem.  I guess 1-minute resolution would be enough, although if a rebuild is needed (e.g. flakey internet connection), we would end up with a different datestamp.</p>
<p>Example Version:</p>
<pre tabindex="0"><code>2021-08-16.13-07
</code></pre><h4 id="5-commit-datestamp">5. Commit Datestamp</h4>
<p>Similar to <a href="#4-datestamp">Option 4</a>, except we use the commit&rsquo;s commit date to build the version number.  This solves multiple pipelines needing to generate the same tag in parallel, as well as being unique and ordered.  The timestamps can also be higher precision than <a href="#4-datestamp">Option 4</a>, as we don&rsquo;t need to hope that pipelines start at a close enough time.</p>
<p>This is how we would generate it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>timestamp<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>git show -s --format<span style="color:#f92672">=</span>%cd --date<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;format:%Y-%m-%d.%H-%M-%S&#34;</span><span style="color:#66d9ef">)</span>
</span></span></code></pre></div><p>Example Version:</p>
<pre tabindex="0"><code>2021-08-16.13-07-34
</code></pre><h4 id="6-automatic-semver">6. Automatic SemVer</h4>
<p>On build, calculate the version number using <a href="https://github.com/semantic-release/semantic-release">Semantic-Release</a>.</p>
<p>This method means that we would need to start enforcing commit message styles, and I am not sure the format that Semantic Release is ideal for us, so it might be better to cover the commit message formatting outside this process.</p>
<p>The commit format would be as follows:</p>
<pre tabindex="0"><code>&lt;type&gt;(&lt;scope&gt;): &lt;short summary&gt;
│       │             │
│       │             └─⫸ Summary in the present tense. Not capitalized. No period at the end.
│       │
│       └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
│                          elements|forms|http|language-service|localize|platform-browser|
│                          platform-browser-dynamic|platform-server|router|service-worker|
│                          upgrade|zone.js|packaging|changelog|dev-infra|docs-infra|migrations|
│                          ngcc|ve
│
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|test
</code></pre><p>Having worked in repositories with this enforced, I would recommend against it, as it causes a lot of frustration (&ldquo;omg <em>why</em> has my commit been rejected again?!&rdquo;) and as mentioned in other options, I am not sure semver itself makes sense for our UI (or UI projects in general.)</p>
<p>We will still need developers to decide if a given commit is a major/minor/patch.</p>
<p>Example Version:</p>
<pre tabindex="0"><code>13.4.17
</code></pre><h4 id="6-combination-datestamp--git">6. Combination: Datestamp + Git</h4>
<p>On build, use a combination of <a href="#5-commit-datestamp">Option 5</a> and <a href="#2-git-short-sha-of-the-commit">Option 2</a> to generate a unique build number.</p>
<p>This method had the advantage of the meaning of the date, with the uniqueness of the git commit, but the likelihood of us needing to distinguish two commits made at identical times by their commit sha is unlikely, especially as we require clean merges to master.</p>
<p>Example Version:</p>
<pre tabindex="0"><code>2021-08-16.13-07-34.84d33bb
</code></pre><h3 id="chosen-decision">Chosen Decision</h3>
<p><a href="#5-commit-datestamp">Option 5</a></p>
<p>We will also embed other build information as labels in the docker container, such as:</p>
<ul>
<li>branch name</li>
<li>pipeline/build number</li>
<li>git hash</li>
<li>git commit timestamp</li>
</ul>
<h3 id="consequences">Consequences</h3>
<ul>
<li>No need to tag commits as a released version, but we could automate this if we wanted</li>
<li>No need to rebuild for changing the version number</li>
<li>No need to remember to change the version number</li>
<li>No need to decide on major/minor/patch semantics</li>
<li>Gain an understandable version number, with meaning</li>
</ul>
<hr>
<h2 id="summary">Summary</h2>
<p>As I said earlier, I went into this process (which I drove) wanting to pick the 2nd option - Short Git Sha, and I came away agreeing that the commit datestamp was the best thing to use.</p>
<p>Not only was my mind changed in the course of this, but also people who join the project later can check out the <code>./docs/adr/</code> and see what options we considered for everything about this project, and how we arrived at the conclusions.  It also means I have examples to refer back to when people ask interesting questions at work.</p>
<p>How do <em>you</em> tag your containers?</p>
]]></content:encoded></item><item><title>The Problem with CPUs and Kubernetes</title><link>https://andydote.co.uk/2021/06/02/os-cpus-and-kubernetes/</link><pubDate>Wed, 02 Jun 2021 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2021/06/02/os-cpus-and-kubernetes/</guid><description>Key Takeaway: os .cpus() returns the number of cores on a Kubernetes host, not the number of cores assigned to a pod.
Investigating excessive memory usage Recently, when I was looking through a cluster health dashboard for a Kubernetes cluster, I noticed that one of the applications deployed was using a considerable amount of RAM - way more than I thought could be reasonable. Each instance (pod) of the application used approximately 8 GB of RAM, which was definitely excessive for a reasonably simple NodeJS webserver.</description><content:encoded><![CDATA[<h2 id="key-takeaway">Key Takeaway:</h2>
<blockquote>
<p><code>os .cpus()</code> returns the number of cores on a Kubernetes host, not the number of cores assigned to a pod.</p>
</blockquote>
<h2 id="investigating-excessive-memory-usage">Investigating excessive memory usage</h2>
<p>Recently, when I was looking through a cluster health dashboard for a Kubernetes cluster, I noticed that one of the applications deployed was using a considerable amount of RAM - way more than I thought could be reasonable.  Each instance (pod) of the application used approximately 8 GB of RAM, which was definitely excessive for a reasonably simple NodeJS webserver.  Combined with the application running 20-30 replicas or so, it makes the total RAM usage between 160 GB and 240 GB.</p>
<p>One of the first things I noticed was that the deployment manifest in Kubernetes had the <code>NODE_MAX_MEM</code> environment variable specified and set to 250 MB:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">NODE_MAX_MEM</span>: <span style="color:#ae81ff">250</span>
</span></span></code></pre></div><p><em>Interesting</em>.  So how is a single container using more RAM than that?</p>
<p>The application used to be deployed to EC2 machines and to fully utilise the multiple cores in the machines, the <a href="https://www.npmjs.com/package/cluster">cluster</a> library was used.</p>
<p>This library essentially forks the node process into <code>n</code> child processes, and in this case, <code>n</code> was set to <code>os.cpus()</code>, which returns the number of cores available on the machine in NodeJS.</p>
<p>While this works for direct virtual machine usage, when the application was containerised and deployed to Kubernetes, it used about the same amount of ram as before, so no one realised there was a problem.</p>
<h2 id="oscpus-and-kubernetes">os.cpus() and Kubernetes</h2>
<p>The interesting thing about <code>os.cpus()</code> when called in a container in Kubernetes is that it reports the number of cores available on the host machine, not the amount of CPU assigned to the container (e.g. through resource requests and limits).</p>
<p>So every replica for the application spawns 32 child processes, as our EC2 hosts have that many cores.  As they had a limited per-pod CPU budget, was there any benefit to doing this?</p>
<p>So I did what seemed natural - I replaced <code>os.cpus()</code> with <code>1</code>, and deployed the application to production, and watched the performance metrics to see what happened.</p>
<p>And what do you know? No difference in request performance <em>at all</em> - and the memory usage dropped by 7.75 GB per pod.</p>
<p>This means overall, we have saved 155 GB to 232.5 GB of RAM, with no performance difference!</p>
]]></content:encoded></item><item><title>Adding Observability to Vault</title><link>https://andydote.co.uk/2021/05/27/vault-observe/</link><pubDate>Thu, 27 May 2021 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2021/05/27/vault-observe/</guid><description>One of the things I like to do when setting up a Vault cluster is to visualise all the operations Vault is performing, which helps see usage patterns changing, whether there are lots of failed requests coming in, and what endpoints are receiving the most traffic.
While Vault has a lot of data available in Prometheus telemetry, the kind of information I am after is best taken from the Audit backend.</description><content:encoded><![CDATA[<p>One of the things I like to do when setting up a Vault cluster is to visualise all the operations Vault is performing, which helps see usage patterns changing, whether there are lots of failed requests coming in, and what endpoints are receiving the most traffic.</p>
<p>While Vault has a lot of data available in Prometheus telemetry, the kind of information I am after is best taken from the Audit backend.  Setting up an audit backend for Vault is reasonably easy - it supports three methods of communication: file, socket and syslog.  For this application, I use a Unix socket and a small daemon running on the same machine as the Vault instance to send the data to a tracing system.</p>
<h2 id="the-goal">The Goal</h2>
<p>Write a small application that receives audit events and writes traces (spans) to an observability tool.   In this case, I am implementing both Honeycomb and Zipkin via OpenTelemetry.</p>
<p>The <a href="https://github.com/Pondidum/vault-observe">code is available on Github</a>, and the most interesting parts are covered in the rest of this blog post.</p>
<h2 id="receiving-and-processing-messages">Receiving and Processing Messages</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">ln</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">net</span>.<span style="color:#a6e22e">Listen</span>(<span style="color:#e6db74">&#34;unix&#34;</span>, <span style="color:#e6db74">&#34;/tmp/observe.sock&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">conn</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">ln</span>.<span style="color:#a6e22e">Accept</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">message</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">bufio</span>.<span style="color:#a6e22e">NewReader</span>(<span style="color:#a6e22e">conn</span>).<span style="color:#a6e22e">ReadBytes</span>(<span style="color:#e6db74">&#39;\n&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// do something with the message
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><p>We only need to do minimal processing of the data for this application before sending it on to Honeycomb or Zipkin.  As the messages contain nested objects, we need to flatten the object hierarchy for easier viewing in spans.  So instead of this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;request&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;operation&#34;</span>: <span style="color:#e6db74">&#34;update&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;namespace&#34;</span>: { <span style="color:#f92672">&#34;id&#34;</span>: <span style="color:#e6db74">&#34;root&#34;</span> },
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;path&#34;</span>: <span style="color:#e6db74">&#34;sys/audit/socket&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;data&#34;</span>: {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;local&#34;</span>: <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We want to send this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;request.operation&#34;</span>: <span style="color:#e6db74">&#34;update&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;request.namespace.id&#34;</span>: <span style="color:#e6db74">&#34;root&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;request.path&#34;</span>: <span style="color:#e6db74">&#34;sys/audit/socket&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;request.data.local&#34;</span>: <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We also want to get a few strongly typed pieces of data out of the message, too, such as the <code>type</code> (<code>request</code> or <code>response</code>) and the request&rsquo;s <code>id</code>, which is in both messages and can be used to group the spans.</p>
<p>To save us from deserialising the json twice, we can do the following:</p>
<ol>
<li>deserialize into a <code>map[string]interface{}</code></li>
<li>create a flattened version of the event using the <a href="https://pkg.go.dev/github.com/jeremywohl/flatten">flatten</a> library</li>
<li>turn the map into a typed struct using the <a href="https://pkg.go.dev/github.com/mitchellh/mapstructure">mapstructure</a> library</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#75715e">// 1 deserialize
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#a6e22e">event</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">map</span>[<span style="color:#66d9ef">string</span>]<span style="color:#66d9ef">interface</span>{}{}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">json</span>.<span style="color:#a6e22e">Unmarshal</span>(<span style="color:#a6e22e">message</span>, <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">event</span>); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 2 flatten
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#a6e22e">flat</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">flatten</span>.<span style="color:#a6e22e">Flatten</span>(<span style="color:#a6e22e">event</span>, <span style="color:#e6db74">&#34;&#34;</span>, <span style="color:#a6e22e">flatten</span>.<span style="color:#a6e22e">DotStyle</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 3 type
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#a6e22e">typed</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">Event</span>{}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">mapstructure</span>.<span style="color:#a6e22e">Decode</span>(<span style="color:#a6e22e">event</span>, <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">typed</span>); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Now that we have our flattened version and our typed version of the message, we can forward it to our span processors.  There are two implementations (3 if you count <code>stdout</code>), so let&rsquo;s look at them one at a time.</p>
<h2 id="honeycomb">Honeycomb</h2>
<p>To send the spans to Honeycomb, I am using their lower-level library <a href="https://pkg.go.dev/github.com/honeycombio/libhoney-go">libhoney-go</a>, rather than the more usual <a href="https://pkg.go.dev/github.com/honeycombio/beeline-go">beeline</a> as I don&rsquo;t need all the <code>context</code> propagation or automatic ID generation.</p>
<p>For the first version of this application, just sending the two events to Honeycomb linked together is enough; however, both spans will show  0ms durations.  We&rsquo;ll fix this problem for both Honeycomb and OpenTelemetry later.</p>
<p>To link our spans together properly, I use the <code>.Request.ID</code> property from the event as the <code>trace.trace_id</code>; it&rsquo;s already a guid and is the same for both the request and response events.  Then, for a <code>request</code> event, I make it the parent span by using the <code>.Request.ID</code> again, but this time as the <code>trace.span_id</code>.  Finally, for the <code>response</code> event, I set the <code>trace.parent_id</code> to the <code>.Request.ID</code>, and generate a random value for the <code>trace.span_id</code> field.</p>
<p>Lastly, I loop through the flattened version of the event, adding each key-value pair to the event&rsquo;s attributes and finally send the event.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">ev</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">libhoney</span>.<span style="color:#a6e22e">NewEvent</span>()
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#e6db74">&#34;trace.trace_id&#34;</span>, <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">ID</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Type</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;request&#34;</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#e6db74">&#34;trace.span_id&#34;</span>, <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">ID</span>)
</span></span><span style="display:flex;"><span>} <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#e6db74">&#34;trace.parent_id&#34;</span>, <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">ID</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#e6db74">&#34;trace.span_id&#34;</span>, <span style="color:#a6e22e">generateSpanID</span>())
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#e6db74">&#34;service_name&#34;</span>, <span style="color:#e6db74">&#34;vault&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#e6db74">&#34;name&#34;</span>, <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Type</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> <span style="color:#a6e22e">key</span>, <span style="color:#a6e22e">val</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">event</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#a6e22e">key</span>, <span style="color:#a6e22e">val</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">Send</span>()
</span></span></code></pre></div><h2 id="zipkin--opentelemetry">Zipkin / OpenTelemetry</h2>
<p>The process for sending via OpenTelemetry is reasonably similar; we start a new span, copy the flattened structure into the span&rsquo;s attributed and call <code>End()</code>, making the TracerProvider send the span to our configured backends (Zipkin in this case.)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">id</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">uuid</span>.<span style="color:#a6e22e">Parse</span>(<span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">ID</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ctx</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">WithValue</span>(<span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Background</span>(), <span style="color:#e6db74">&#34;request_id&#34;</span>, <span style="color:#a6e22e">id</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">tr</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">otel</span>.<span style="color:#a6e22e">GetTracerProvider</span>().<span style="color:#a6e22e">Tracer</span>(<span style="color:#e6db74">&#34;main&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">span</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">tr</span>.<span style="color:#a6e22e">Start</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Type</span>, <span style="color:#a6e22e">trace</span>.<span style="color:#a6e22e">WithSpanKind</span>(<span style="color:#a6e22e">trace</span>.<span style="color:#a6e22e">SpanKindServer</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> <span style="color:#a6e22e">key</span>, <span style="color:#a6e22e">value</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">event</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">SetAttributes</span>(<span style="color:#a6e22e">attribute</span>.<span style="color:#a6e22e">KeyValue</span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">Key</span>:   <span style="color:#a6e22e">attribute</span>.<span style="color:#a6e22e">Key</span>(<span style="color:#a6e22e">key</span>),
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">Value</span>: <span style="color:#a6e22e">attribute</span>.<span style="color:#a6e22e">StringValue</span>(<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Sprintf</span>(<span style="color:#e6db74">&#34;%v&#34;</span>, <span style="color:#a6e22e">value</span>)),
</span></span><span style="display:flex;"><span>  })
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Error</span> <span style="color:#f92672">!=</span> <span style="color:#e6db74">&#34;&#34;</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">SetStatus</span>(<span style="color:#a6e22e">codes</span>.<span style="color:#a6e22e">Error</span>, <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Error</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">End</span>()
</span></span></code></pre></div><p>The hard part was figuring out how to feed the <code>.Request.ID</code> into the Tracer as the TraceID, which was achieved by configuring OpenTelemetry with a custom ID generator that would use the <code>request_id</code> property of the current <code>context</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">Generator</span> <span style="color:#66d9ef">struct</span>{}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> (<span style="color:#a6e22e">g</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">Generator</span>) <span style="color:#a6e22e">NewIDs</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>) (<span style="color:#a6e22e">trace</span>.<span style="color:#a6e22e">TraceID</span>, <span style="color:#a6e22e">trace</span>.<span style="color:#a6e22e">SpanID</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">val</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">Value</span>(<span style="color:#e6db74">&#34;request_id&#34;</span>).(<span style="color:#a6e22e">uuid</span>.<span style="color:#a6e22e">UUID</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">tid</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">trace</span>.<span style="color:#a6e22e">TraceID</span>{}
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">req</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">val</span>.<span style="color:#a6e22e">MarshalText</span>()
</span></span><span style="display:flex;"><span>  copy(<span style="color:#a6e22e">tid</span>[:], <span style="color:#a6e22e">req</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">sid</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">trace</span>.<span style="color:#a6e22e">SpanID</span>{}
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">rand</span>.<span style="color:#a6e22e">Read</span>(<span style="color:#a6e22e">sid</span>[:])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">tid</span>, <span style="color:#a6e22e">sid</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I am sure more copying and allocation is happening in this method than necessary, but it is good enough for now.  Configuring it for use by OpenTelemetry is straightforward; it just needs adding to the <code>NewTracerProvider</code> call by wrapping it with <code>trace.WithIDGenerator()</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">exporter</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">zipkin</span>.<span style="color:#a6e22e">NewRawExporter</span>(
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;http://localhost:9411/api/v2/spans&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">zipkin</span>.<span style="color:#a6e22e">WithSDKOptions</span>(<span style="color:#a6e22e">sdktrace</span>.<span style="color:#a6e22e">WithSampler</span>(<span style="color:#a6e22e">sdktrace</span>.<span style="color:#a6e22e">AlwaysSample</span>())),
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">processor</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">sdktrace</span>.<span style="color:#a6e22e">NewSimpleSpanProcessor</span>(<span style="color:#a6e22e">exporter</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">tp</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">sdktrace</span>.<span style="color:#a6e22e">NewTracerProvider</span>(
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">sdktrace</span>.<span style="color:#a6e22e">WithSpanProcessor</span>(<span style="color:#a6e22e">processor</span>),
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">sdktrace</span>.<span style="color:#a6e22e">WithResource</span>(<span style="color:#a6e22e">resource</span>.<span style="color:#a6e22e">NewWithAttributes</span>(
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">semconv</span>.<span style="color:#a6e22e">ServiceNameKey</span>.<span style="color:#a6e22e">String</span>(<span style="color:#e6db74">&#34;vault-observe&#34;</span>),
</span></span><span style="display:flex;"><span>  )),
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">sdktrace</span>.<span style="color:#a6e22e">WithIDGenerator</span>(<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">Generator</span>{}),
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">otel</span>.<span style="color:#a6e22e">SetTracerProvider</span>(<span style="color:#a6e22e">tp</span>)
</span></span></code></pre></div><h2 id="testing">Testing</h2>
<p>To verify that it works, I have a single <code>docker-compose.yml</code> file which sets up a Vault instance in dev mode, and a Zipkin instance.  It mounts the current working directory into the Vault container as <code>/sockets</code> to share the socket file between the host and the container.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">version</span>: <span style="color:#e6db74">&#34;3.9&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">vault</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">vault:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">cap_add</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">IPC_LOCK</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;./:/sockets:rw&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;8200:8200&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">VAULT_DEV_ROOT_TOKEN_ID</span>: <span style="color:#e6db74">&#34;vault&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">zipkin</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">openzipkin/zipkin-slim</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;9411:9411&#34;</span>
</span></span></code></pre></div><p>Running the application along with the docker container is now as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>go build
</span></span><span style="display:flex;"><span>docker-compose up -d
</span></span><span style="display:flex;"><span>./vault-observe --zipkin --socket-path observe.sock
</span></span></code></pre></div><p>In another terminal, you can now enable the new audit backend and send some requests so we can look at them in Zipkin:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export VAULT_ADDR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://localhost:8200&#34;</span>
</span></span><span style="display:flex;"><span>export VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;vault&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault audit enable socket address<span style="color:#f92672">=</span>/sockets/observe.sock socket_type<span style="color:#f92672">=</span>unix
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault secrets enable -version<span style="color:#f92672">=</span><span style="color:#ae81ff">2</span> kv
</span></span><span style="display:flex;"><span>vault kv put /secrets/test name<span style="color:#f92672">=</span>andy
</span></span><span style="display:flex;"><span>vault kv get /secrets/test
</span></span></code></pre></div><h2 id="running-in-production">Running in Production</h2>
<p>There are a few things you should be aware of, running this in production:</p>
<ul>
<li>This <em>must not</em> be your only audit backend: Vault will fail requests if they are not successfully written to at least one audit backend if any are enabled.</li>
<li>There is the possibility of losing data if the <code>vault-observe</code> process stops</li>
</ul>
<h2 id="improvements">Improvements</h2>
<p>As I am using this for keeping an eye on request durations and patterns in behaviour, capturing the actual time it takes for Vault to handle a request would be pretty valuable.  So instead of processing both events, I will keep just the timestamp from the <code>request</code>, and then when the <code>response</code> event comes in, look up the timestamp and calculate the duration.</p>
<p>As I don&rsquo;t want an ever-expanding list of timestamps in memory, I use an <a href="https://pkg.go.dev/github.com/patrickmn/go-cache">automatically expiring cache</a> so keep them for around 10 seconds, as no request to Vault should be that slow!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">requests</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">cache</span>.<span style="color:#a6e22e">New</span>(<span style="color:#ae81ff">10</span><span style="color:#f92672">*</span><span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span>, <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Minute</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">processMessage</span>(<span style="color:#a6e22e">requests</span>, <span style="color:#a6e22e">conn</span>, <span style="color:#a6e22e">sender</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#a6e22e">io</span>.<span style="color:#a6e22e">EOF</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>processMessage</code> function now handles the <code>request</code> and <code>response</code> messages separately.  The <code>request</code> just inserts the event&rsquo;s <code>time</code> property into the cache, and exists:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Type</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;request&#34;</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">requests</span>.<span style="color:#a6e22e">Set</span>(<span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">ID</span>, <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Time</span>, <span style="color:#a6e22e">cache</span>.<span style="color:#a6e22e">DefaultExpiration</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>response</code>  version pulls the time back out of the cache and stores it into the event itself - it&rsquo;s then up to the sender if it wants to use the value or not.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Type</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;response&#34;</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">x</span>, <span style="color:#a6e22e">found</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">requests</span>.<span style="color:#a6e22e">Get</span>(<span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">ID</span>); <span style="color:#a6e22e">found</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">StartTime</span> = <span style="color:#a6e22e">x</span>.(<span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Time</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">requests</span>.<span style="color:#a6e22e">Delete</span>(<span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">ID</span>)
</span></span><span style="display:flex;"><span>  } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Errorf</span>(<span style="color:#e6db74">&#34;No request found in the cache for %s&#34;</span>, <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">ID</span>)
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In the Honeycomb sender, we can remove all the parenting logic; we only need to set the <code>Timestamp</code> and <code>duration_ms</code> fields to get the duration showing correctly:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">duration</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Time</span>.<span style="color:#a6e22e">Sub</span>(<span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">StartTime</span>).<span style="color:#a6e22e">Milliseconds</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ev</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">libhoney</span>.<span style="color:#a6e22e">NewEvent</span>()
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">Timestamp</span> = <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">StartTime</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#e6db74">&#34;duration_ms&#34;</span>, <span style="color:#a6e22e">duration</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#e6db74">&#34;trace.trace_id&#34;</span>, <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">ID</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#e6db74">&#34;trace.span_id&#34;</span>, <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">ID</span>)
</span></span></code></pre></div><p>For the OpenTelemetry sender, we can add a <code>trace.WithTimestamp()</code> call to both the <code>Start()</code> and <code>End()</code> calls so use our events&rsquo; timestamps:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">ctx</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">WithValue</span>(<span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Background</span>(), <span style="color:#e6db74">&#34;request_id&#34;</span>, <span style="color:#a6e22e">id</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">tr</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">otel</span>.<span style="color:#a6e22e">GetTracerProvider</span>().<span style="color:#a6e22e">Tracer</span>(<span style="color:#e6db74">&#34;main&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">span</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">tr</span>.<span style="color:#a6e22e">Start</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Type</span>, <span style="color:#a6e22e">trace</span>.<span style="color:#a6e22e">WithSpanKind</span>(<span style="color:#a6e22e">trace</span>.<span style="color:#a6e22e">SpanKindServer</span>), <span style="color:#a6e22e">trace</span>.<span style="color:#a6e22e">WithTimestamp</span>(<span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">StartTime</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// ...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">End</span>(<span style="color:#a6e22e">trace</span>.<span style="color:#a6e22e">WithTimestamp</span>(<span style="color:#a6e22e">typed</span>.<span style="color:#a6e22e">Time</span>))
</span></span></code></pre></div>]]></content:encoded></item><item><title>Getting NodeJS OpenTelemetry data into NewRelic</title><link>https://andydote.co.uk/2021/03/12/nodejs-opentelemetry-newrelic/</link><pubDate>Fri, 12 Mar 2021 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2021/03/12/nodejs-opentelemetry-newrelic/</guid><description>I had the need to get some OpenTelemetry data out of a NodeJS application, and into NewRelic&amp;rsquo;s distributed tracing service, but found that there is no way to do it directly, and in this use case, adding a separate collector is more hassle than it&amp;rsquo;s worth.
Luckily, there is an NodeJS OpenTelemetry library which can report to Zipkin, and NewRelic can also ingest Zipkin format data.
To use it was relatively straight forward:</description><content:encoded><![CDATA[<p>I had the need to get some OpenTelemetry data out of a NodeJS application, and into NewRelic&rsquo;s distributed tracing service, but found that there is no way to do it directly, and in this use case, adding a separate collector is more hassle than it&rsquo;s worth.</p>
<p>Luckily, there is an NodeJS <a href="https://www.npmjs.com/package/@opentelemetry/exporter-zipkin">OpenTelemetry library which can report to Zipkin</a>, and NewRelic can also <a href="https://docs.newrelic.com/docs/understand-dependencies/distributed-tracing/trace-api/report-zipkin-format-traces-trace-api/">ingest Zipkin format data</a>.</p>
<p>To use it was relatively straight forward:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">import</span> { <span style="color:#a6e22e">context</span>, <span style="color:#a6e22e">setSpan</span>, <span style="color:#a6e22e">Span</span>, <span style="color:#a6e22e">trace</span> } <span style="color:#a6e22e">from</span> <span style="color:#e6db74">&#34;@opentelemetry/api&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">import</span> { <span style="color:#a6e22e">BasicTracerProvider</span>, <span style="color:#a6e22e">BatchSpanProcessor</span> } <span style="color:#a6e22e">from</span> <span style="color:#e6db74">&#34;@opentelemetry/tracing&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">import</span> { <span style="color:#a6e22e">ZipkinExporter</span> } <span style="color:#a6e22e">from</span> <span style="color:#e6db74">&#34;@opentelemetry/exporter-zipkin&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">exporter</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">ZipkinExporter</span>({
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">url</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;https://trace-api.newrelic.com/trace/v1&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">serviceName</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;interesting-service&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Api-Key&#34;</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">NEWRELIC_APIKEY</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Data-Format&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;zipkin&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Data-Format-Version&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;2&#34;</span>,
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">provider</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">BasicTracerProvider</span>();
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">provider</span>.<span style="color:#a6e22e">addSpanProcessor</span>(<span style="color:#66d9ef">new</span> <span style="color:#a6e22e">BatchSpanProcessor</span>(<span style="color:#a6e22e">exporter</span>));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">provider</span>.<span style="color:#a6e22e">register</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">tracer</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">trace</span>.<span style="color:#a6e22e">getTracer</span>(<span style="color:#e6db74">&#34;default&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">rootSpan</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">tracer</span>.<span style="color:#a6e22e">startSpan</span>(<span style="color:#e6db74">&#34;main&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// do something fantastically interesting
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">rootSpan</span>.<span style="color:#a6e22e">end</span>();
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">provider</span>.<span style="color:#a6e22e">shutdown</span>();
</span></span></code></pre></div><p>This has the added benefit of being able to test with Zipkin locally, using the <code>openzipkin/zipkin-slim</code> docker container, by just removing the URL property from the <code>ZipkinExporter</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker run --rm -d -p 9411:9411 openzipkin/zipkin-slim
</span></span></code></pre></div><h2 id="child-spans">Child Spans</h2>
<p>Figuring out how to create child spans was actually harder in the end, in part because the OpenTelemetry docs don&rsquo;t quite match the actual function signatures.</p>
<p>In the end, I wrote this little helper function:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">import</span> { <span style="color:#a6e22e">context</span>, <span style="color:#a6e22e">setSpan</span>, <span style="color:#a6e22e">Span</span> } <span style="color:#a6e22e">from</span> <span style="color:#e6db74">&#34;@opentelemetry/api&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">startSpan</span>(<span style="color:#a6e22e">parent</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">Span</span>, <span style="color:#a6e22e">name</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">string</span>)<span style="color:#f92672">:</span> <span style="color:#a6e22e">Span</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">tracer</span>.<span style="color:#a6e22e">startSpan</span>(<span style="color:#a6e22e">name</span>, <span style="color:#66d9ef">undefined</span>, <span style="color:#a6e22e">setSpan</span>(<span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">active</span>(), <span style="color:#a6e22e">parent</span>));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Which I can use like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">async</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">DoInterestingThings</span>(<span style="color:#a6e22e">span</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">Span</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">span</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">startSpan</span>(<span style="color:#a6e22e">span</span>, <span style="color:#e6db74">&#34;do-interesting-things&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// interesting things happen here
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">end</span>();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Doing both of these means I can now see what my misbehaving cron jobs are actually doing, rather than trying to guess what their problems are.</p>
]]></content:encoded></item><item><title>Observability with Infrastructure as Code</title><link>https://andydote.co.uk/2021/03/01/observability-with-infrastructure-as-code/</link><pubDate>Mon, 01 Mar 2021 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2021/03/01/observability-with-infrastructure-as-code/</guid><description>This article was originally published on the Pulumi blog.
When using the Pulumi Automation API to create applications which can provision infrastructure, it is very handy to be able to use observability techniques to ensure the application functions correctly and to help see where performance bottlenecks are.
One of the applications I work on creates a VPC and Bastion host and then stores the credentials into a Vault instance. The problem is that the “create infrastructure” part is an opaque blob, in that I can see it takes 129 seconds to create, but I can’t see what it’s doing, or why it takes this amount of time.</description><content:encoded><![CDATA[<blockquote>
<p>This article was originally published on the <a href="https://www.pulumi.com/blog/observability-with-infrastructure-as-code/">Pulumi blog</a>.</p>
</blockquote>
<p>When using the <a href="https://www.pulumi.com/blog/tag/automation-api/">Pulumi Automation API</a> to create applications which can provision infrastructure, it is very handy to be able to use observability techniques to ensure the application functions correctly and to help see where performance bottlenecks are.</p>
<p>One of the applications I work on creates a VPC and Bastion host and then stores the credentials into a Vault instance.  The problem is that the “create infrastructure” part is an opaque blob, in that I can see it takes 129 seconds to create, but I can’t see what it’s doing, or why it takes this amount of time.</p>
<p><img loading="lazy" src="pulumi-observability-before.png" alt="honeycomb traces of one pulumi stack resource"  />
</p>
<p>So can I do better?</p>
<h2 id="the-initial-application">The Initial Application</h2>
<p>In this example I use <a href="https://honeycomb.io/">Honeycomb&rsquo;s</a> <a href="https://github.com/honeycombio/beeline-go/">Go Beeline</a> to capture all the data I care about; durations, errors, any context which is “interesting”:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">Init</span>(<span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">Config</span>{
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">WriteKey</span>: <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Getenv</span>(<span style="color:#e6db74">&#34;HONEYCOMB_API_KEY&#34;</span>),
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">Dataset</span>:  <span style="color:#e6db74">&#34;pulumi-demo&#34;</span>,
</span></span><span style="display:flex;"><span>	})
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">Close</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">span</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">StartSpan</span>(<span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Background</span>(), <span style="color:#e6db74">&#34;basic-vpc&#34;</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">span</span>.<span style="color:#a6e22e">Send</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">name</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">auto</span>.<span style="color:#a6e22e">FullyQualifiedStackName</span>(<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Getenv</span>(<span style="color:#e6db74">&#34;PULUMI_USERNAME&#34;</span>), <span style="color:#e6db74">&#34;basic-vpc&#34;</span>, <span style="color:#e6db74">&#34;dev&#34;</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">stack</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">auto</span>.<span style="color:#a6e22e">UpsertStackInlineSource</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">name</span>, <span style="color:#e6db74">&#34;basic-vpc&#34;</span>, <span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">pc</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">pulumi</span>.<span style="color:#a6e22e">Context</span>) <span style="color:#66d9ef">error</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">azs</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">getAvailabilityZones</span>(<span style="color:#a6e22e">ctx</span>)
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;err&#34;</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">v</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">vpc</span>.<span style="color:#a6e22e">NewVpc</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">pc</span>, <span style="color:#e6db74">&#34;dev&#34;</span>, <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">vpc</span>.<span style="color:#a6e22e">VpcArgs</span>{
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">Description</span>:           <span style="color:#e6db74">&#34;dev&#34;</span>,
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">BaseCidr</span>:              <span style="color:#e6db74">&#34;192.168.0.0/16&#34;</span>,
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">AvailabilityZoneNames</span>: <span style="color:#a6e22e">azs</span>,
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">S3Endpoint</span>:            <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">DynamoEndpoint</span>:        <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>		})
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;err&#34;</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	})
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;err&#34;</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Exit</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">stack</span>.<span style="color:#a6e22e">SetConfig</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;aws:region&#34;</span>, <span style="color:#a6e22e">auto</span>.<span style="color:#a6e22e">ConfigValue</span>{<span style="color:#a6e22e">Value</span>: <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Getenv</span>(<span style="color:#e6db74">&#34;PULUMI_REGION&#34;</span>)}); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;err&#34;</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Exit</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ws</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">stack</span>.<span style="color:#a6e22e">Workspace</span>()
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">ws</span>.<span style="color:#a6e22e">InstallPlugin</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;aws&#34;</span>, <span style="color:#e6db74">&#34;v3.23.0&#34;</span>); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;err&#34;</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Exit</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">stack</span>.<span style="color:#a6e22e">Refresh</span>(<span style="color:#a6e22e">ctx</span>); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;err&#34;</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Exit</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">stream</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">optup</span>.<span style="color:#a6e22e">ProgressStreams</span>(<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Stdout</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">stack</span>.<span style="color:#a6e22e">Up</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">stream</span>); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;err&#34;</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Exit</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">//vault code
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="adding-infrastructure-observability">Adding Infrastructure Observability</h2>
<p>To get a handle on what is happening when <code>stack.Up()</code> runs, I have mplemented a custom <code>io.Writer</code>, which will be passed into the <code>ProgressStream</code> constructor.</p>
<p>The custom progress stream&rsquo;s <code>Write</code> method is called once for each line emitted,  which allows us to start new spans when a resource starts being constructed, and send them when construction completes.  Currently, this is achieved by parsing the console output text, but I gather in the future, it will be possible to get streamed json blobs which can be unmarshaled into go structs.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">pulumiBeeline</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>      <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">contexts</span> <span style="color:#66d9ef">map</span>[<span style="color:#66d9ef">string</span>]<span style="color:#66d9ef">func</span>()
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">NewPulumiBeeline</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>) <span style="color:#f92672">*</span><span style="color:#a6e22e">pulumiBeeline</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">pulumiBeeline</span>{
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">ctx</span>:  	<span style="color:#a6e22e">ctx</span>,
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">contexts</span>: <span style="color:#66d9ef">map</span>[<span style="color:#66d9ef">string</span>]<span style="color:#66d9ef">func</span>(){},
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> (<span style="color:#a6e22e">cw</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">pulumiBeeline</span>) <span style="color:#a6e22e">Write</span>(<span style="color:#a6e22e">p</span> []<span style="color:#66d9ef">byte</span>) (<span style="color:#a6e22e">n</span> <span style="color:#66d9ef">int</span>, <span style="color:#a6e22e">err</span> <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">// todo: make more robust, support modifications, deletions etc.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>	<span style="color:#a6e22e">line</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">strings</span>.<span style="color:#a6e22e">TrimSpace</span>(string(<span style="color:#a6e22e">p</span>))
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">parts</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">strings</span>.<span style="color:#a6e22e">Split</span>(<span style="color:#a6e22e">line</span>, <span style="color:#e6db74">&#34; &#34;</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> len(<span style="color:#a6e22e">parts</span>) &lt; <span style="color:#ae81ff">5</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> len(<span style="color:#a6e22e">p</span>), <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">//+  aws-vpc dev creating
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>	<span style="color:#75715e">//+  &lt;type&gt; &lt;name&gt; &lt;action&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>	<span style="color:#a6e22e">resourceType</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">parts</span>[<span style="color:#ae81ff">2</span>]
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">resourceName</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">parts</span>[<span style="color:#ae81ff">3</span>]
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">resourceAction</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">parts</span>[<span style="color:#ae81ff">4</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">resourceAction</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;creating&#34;</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">c</span>, <span style="color:#a6e22e">s</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">StartSpan</span>(<span style="color:#a6e22e">cw</span>.<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">resourceName</span>)
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#a6e22e">c</span>, <span style="color:#e6db74">&#34;type&#34;</span>, <span style="color:#a6e22e">resourceType</span>)
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">// add other things here
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">cw</span>.<span style="color:#a6e22e">contexts</span>[<span style="color:#a6e22e">resourceName</span>] = <span style="color:#a6e22e">s</span>.<span style="color:#a6e22e">Send</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">resourceAction</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;created&#34;</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">cw</span>.<span style="color:#a6e22e">contexts</span>[<span style="color:#a6e22e">resourceName</span>]()
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> len(<span style="color:#a6e22e">p</span>), <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Modifying the <code>optup.ProgressStreams</code> is the only change needed to the original application:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">stream</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">optup</span>.<span style="color:#a6e22e">ProgressStreams</span>(<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Stdout</span>, <span style="color:#a6e22e">NewPulumiBeeline</span>(<span style="color:#a6e22e">ctx</span>))
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">stack</span>.<span style="color:#a6e22e">Up</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">stream</span>); <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">beeline</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#e6db74">&#34;err&#34;</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Exit</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Now when I run this program again, I can see a lot more information in my Honeycomb traces, which not only shows me that Pulumi is <em>highly</em> parallelised, but also gives me a better idea of where the time is taken when creating infrastructure; in this example, it’s the NAT Gateways:</p>
<p><img loading="lazy" src="pulumi-observability-after.png" alt="honeycomb traces of all infrastructure resources in the pulumi stack"  />
</p>
<p>In the future, I want to expand this to cover far more details, such as including the reasons resources were created/modified/destroyed and including as much information as possible about what caused a resource to fail.</p>
<h2 id="wrapping-up">Wrapping Up</h2>
<p>In the end, this turned out to be much easier to achieve than I had hoped.  Being able to use Pulumi progmatically, rather than running <code>os.Exec</code> directly myself was a huge productivity boost.</p>
<p>I am looking forward to all the new kinds of tooling I can build to solve my user&rsquo;s problems continuing to utilise Honeycomb for my observability and Pulumi for my infrastructure.</p>
]]></content:encoded></item><item><title>Forking Multi Container Docker Builds</title><link>https://andydote.co.uk/2020/11/03/docker-multi-output/</link><pubDate>Tue, 03 Nov 2020 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2020/11/03/docker-multi-output/</guid><description>Following on from my last post on Isolated Multistage Docker Builds, I thought it would be useful to cover another advantage to splitting your dockerfiles: building different output containers from a common base.
The Problem When I have an application which when built, needs to have all assets in one container, and a subset of assets in a second container.
For example, writing a node webapp, where you want the compiled/bundled static assets available in the container as a fallback, and also stored in an nginx container for serving.</description><content:encoded><![CDATA[<p>Following on from <a href="/2020/11/01/docker-multistage-containers/">my last post on Isolated Multistage Docker Builds</a>, I thought it would be useful to cover another advantage to splitting your dockerfiles: building different output containers from a common base.</p>
<h2 id="the-problem">The Problem</h2>
<p>When I have an application which when built, needs to have all assets in one container, and a subset of assets in a second container.</p>
<p>For example, writing a node webapp, where you want the compiled/bundled static assets available in the container as a fallback, and also stored in an nginx container for serving.  One of the reasons to do this is separation of concerns: I don&rsquo;t want to put my backend code where it doesn&rsquo;t need to be.  There is also, in this case, the fact that the backend code and nginx version need different base containers, meaning deploying the same container twice won&rsquo;t work.</p>
<p>So let&rsquo;s see how we solve this!</p>
<h2 id="creating-separate-dockerfiles">Creating Separate Dockerfiles</h2>
<p>The first dockerfile to write is the common base, which I name <code>Dockerfile.builder</code>.  This is the same as the previous post - we are assuming that the <code>yarn ci:build</code> step transpiles the typescript, and generates the static assets for our application.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> node:15.0.1-alpine3.12 as builder</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">WORKDIR</span><span style="color:#e6db74"> /app</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> . ./<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> yarn install --frozen-lockfile <span style="color:#f92672">&amp;&amp;</span> yarn cache clean<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> yarn ci:build<span style="color:#960050;background-color:#1e0010">
</span></span></span></code></pre></div><p>Next up is the server container, which will be in the <code>Dockerfile.backend</code> file, as try to name the files based on their purpose, rather than their technology used.  As in the previous post, this installs the production dependencies for the application, and copies in the compiled output from the <code>builder</code> stage:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#66d9ef">ARG</span> builder_image<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> ${builder_image} as builder</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> node:15.0.1-alpine3.12 as output</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">WORKDIR</span><span style="color:#e6db74"> /app</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> package.json yarn.lock /app<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> yarn install --frozen-lockfile --production <span style="color:#f92672">&amp;&amp;</span> yarn cache clean<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> --from builder /app/dist /app<span style="color:#960050;background-color:#1e0010">
</span></span></span></code></pre></div><p>Now let&rsquo;s deal with the <code>Dockerfile.frontend</code>.  This uses <code>nginx:1.19.3-alpine</code> as a base, and copies in the <code>nginx.conf</code> file from the host, and the static assets directory from the <code>builder</code> container:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#66d9ef">ARG</span> builder_image<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> ${builder_image} as builder</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> nginx:1.19.3-alpine as output</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> ./nginx.conf /etc/nginx/nginx.conf<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> --from builder /app/dist/static /app<span style="color:#960050;background-color:#1e0010">
</span></span></span></code></pre></div><h2 id="building-containers">Building Containers</h2>
<p>The reason we rely on the <code>builder</code> stage rather than the <code>backend</code> output stage is that we are now decoupled from layout/structural changes in that container, and we gain the ability to run the builds in parallel too (the <code>&amp;</code> at the end of the lines), for a bit of a speed up on our build agents:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>version<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>GIT_COMMIT:0:7<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>builder_tag<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;builder:</span>$version<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker build --file Dockerfile.builder -t <span style="color:#e6db74">&#34;</span>$builder_tag<span style="color:#e6db74">&#34;</span> .
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># run the builder container here to do tests, lint, static analysis etc.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker build --file dockerfile.backend --build-arg <span style="color:#e6db74">&#34;builder_image=</span>$builder_tag<span style="color:#e6db74">&#34;</span> -t backend:$version . &amp;
</span></span><span style="display:flex;"><span>docker build --file Dockerfile.frontend --build-arg <span style="color:#e6db74">&#34;builder_image=</span>$builder_tag<span style="color:#e6db74">&#34;</span> -t frontend:$version . &amp;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>wait
</span></span></code></pre></div><p>The result of this is 3 containers, all labled with the short version of the current git commit:</p>
<ul>
<li><code>builder:abc123e</code> - contains all packages, compiled output</li>
<li><code>backend:abc123e</code> - node based, contains the node backend and static assets</li>
<li><code>frontend:abc123e</code> - nginx based, contains the static assets</li>
</ul>
<p>I can now publish the builder internally (so it can be cloned before builds for <a href="/2020/05/14/docker-layer-sharing/">caching and speed</a>), and deploy the <code>backend</code> and <code>frontend</code> to their different locations.</p>
]]></content:encoded></item><item><title>Isolated Docker Multistage Images</title><link>https://andydote.co.uk/2020/11/01/docker-multistage-containers/</link><pubDate>Sun, 01 Nov 2020 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2020/11/01/docker-multistage-containers/</guid><description>Often when building applications, I will use a multistage docker build for output container size and efficiency, but will run the build in two halves, to make use of the extra assets in the builder container, something like this:
docker build \ --target builder \ -t builder:$GIT_COMMIT \ . docker run --rm \ -v &amp;#34;$PWD/artefacts/tests:/artefacts/tests&amp;#34; \ builder:$GIT_COMMIT \ yarn ci:test docker run --rm \ -v &amp;#34;$PWD/artefacts/lint:/artefacts/lint&amp;#34; \ builder:$GIT_COMMIT \ yarn ci:lint docker build \ --cache-from builder:$GIT_COMMIT \ --target output \ -t app:$GIT_COMMIT \ .</description><content:encoded><![CDATA[<p>Often when building applications, I will use a multistage docker build for output container size and efficiency, but will run the build in two halves, to make use of the extra assets in the builder container, something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker build <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --target builder <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -t builder:$GIT_COMMIT <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  .
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker run --rm <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -v <span style="color:#e6db74">&#34;</span>$PWD<span style="color:#e6db74">/artefacts/tests:/artefacts/tests&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  builder:$GIT_COMMIT <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  yarn ci:test
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker run --rm <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -v <span style="color:#e6db74">&#34;</span>$PWD<span style="color:#e6db74">/artefacts/lint:/artefacts/lint&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  builder:$GIT_COMMIT <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  yarn ci:lint
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker build <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --cache-from builder:$GIT_COMMIT <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --target output <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -t app:$GIT_COMMIT <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  .
</span></span></code></pre></div><p>This usually works fine, but sometimes the <code>.dockerignore</code> file won&rsquo;t have everything set correctly, and docker will decide that when it runs the last <code>build</code> command, that it needs to rebuild the <code>builder</code> container too, which is pretty irritating.</p>
<p>The first solution is to try and figure out what you need to add to your <code>.dockerignore</code> file, which depending on your repository structure and container usage, might be more hassle than it&rsquo;s worth.</p>
<p>The second solution is to prevent docker invalidating the first layers at all, by splitting the build into separate files.</p>
<h2 id="splitting-the-dockerfile">Splitting the Dockerfile</h2>
<p>Let&rsquo;s start with an example docker file, which is a generic yarn based application with multistage build configured:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> node:15.0.1-alpine3.12 as builder</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">WORKDIR</span><span style="color:#e6db74"> /app</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> . ./<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> yarn install --frozen-lockfile <span style="color:#f92672">&amp;&amp;</span> yarn cache clean<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> yarn ci:build<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> node:15.0.1-alpine3.12 as output</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">WORKDIR</span><span style="color:#e6db74"> /app</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> package.json yarn.lock /app<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> yarn install --frozen-lockfile --production <span style="color:#f92672">&amp;&amp;</span> yarn cache clean<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> --from builder /app/dist /app<span style="color:#960050;background-color:#1e0010">
</span></span></span></code></pre></div><p>The first file will be our <code>Docker.builder</code>, which is a direct copy paste:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> node:15.0.1-alpine3.12 as builder</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">WORKDIR</span><span style="color:#e6db74"> /app</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> . ./<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> yarn install --frozen-lockfile <span style="color:#f92672">&amp;&amp;</span> yarn cache clean<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> yarn ci:build<span style="color:#960050;background-color:#1e0010">
</span></span></span></code></pre></div><p>The second file can also be a direct copy paste, saved as <code>Dockerfile.output</code>, but it has a problem:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> node:15.0.1-alpine3.12 as output</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">WORKDIR</span><span style="color:#e6db74"> /app</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> package.json yarn.lock /app<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> yarn install --frozen-lockfile --production <span style="color:#f92672">&amp;&amp;</span> yarn cache clean<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> --from builder /app/dist /app<span style="color:#960050;background-color:#1e0010">
</span></span></span></code></pre></div><p>We want to copy from a different container, not a different stage, and while the <code>COPY</code> command does let you specify another container in the <code>--from</code> parameter, but we really want to specify which container it is at build time.  The first attempt at solving this was using a buildarg:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#66d9ef">ARG</span> builder_image<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> --from <span style="color:#e6db74">${</span>builder_image<span style="color:#e6db74">}</span> /app/dist /app<span style="color:#960050;background-color:#1e0010">
</span></span></span></code></pre></div><p>But alas, this doesn&rsquo;t work either, as the <code>--from</code> parameter doesn&rsquo;t support variables. The solution turns out to be that <code>FROM</code> command <em>does</em> support parameterisation, so we can (ab)use that:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#66d9ef">ARG</span> builder_image<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> ${builder_image} as builder</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> node:15.0.1-alpine3.12 as output</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">WORKDIR</span><span style="color:#e6db74"> /app</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> package.json yarn.lock /app<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> yarn install --frozen-lockfile --production <span style="color:#f92672">&amp;&amp;</span> yarn cache clean<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> --from builder /app/dist /app<span style="color:#960050;background-color:#1e0010">
</span></span></span></code></pre></div><p>Now our build script can use the <code>--build-arg</code> parameter to force the right container:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span>docker build \
</span></span><span style="display:flex;"><span><span style="color:#f92672">-  --target builder \
</span></span></span><span style="display:flex;"><span><span style="color:#f92672"></span><span style="color:#a6e22e">+  --file Dockerfile.builder \
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>  -t builder:$GIT_COMMIT \
</span></span><span style="display:flex;"><span>  .
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker run --rm \
</span></span><span style="display:flex;"><span>  -v &#34;$PWD/artefacts/tests:/artefacts/tests&#34; \
</span></span><span style="display:flex;"><span>  builder:$GIT_COMMIT \
</span></span><span style="display:flex;"><span>  yarn ci:test
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker run --rm \
</span></span><span style="display:flex;"><span>  -v &#34;$PWD/artefacts/lint:/artefacts/lint&#34; \
</span></span><span style="display:flex;"><span>  builder:$GIT_COMMIT \
</span></span><span style="display:flex;"><span>  yarn ci:lint
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker build \
</span></span><span style="display:flex;"><span><span style="color:#f92672">-  --cache-from builder:$GIT_COMMIT \
</span></span></span><span style="display:flex;"><span><span style="color:#f92672"></span><span style="color:#a6e22e">+  --build-arg &#34;builder_image=builder:$GIT_COMMIT&#34; \
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+  --file Dockerfile.output \
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>  -t app:$GIT_COMMIT \
</span></span><span style="display:flex;"><span>  .
</span></span></code></pre></div><p>We can now safely modfiy the working directory to our heart&rsquo;s content without worring about invalidating the layer caches.</p>
]]></content:encoded></item><item><title>Better BASHing Through Technology</title><link>https://andydote.co.uk/2020/08/28/better-bashing-through-technology/</link><pubDate>Fri, 28 Aug 2020 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2020/08/28/better-bashing-through-technology/</guid><description>I write a lot of bash scripts for both my day job and my personal projects, and while they are functional, bash scripts always seem to lack that structure that I want, especially when compared to writing something in Go or C#. The main problem I have with bash scripts is that when I use functions, I lose the ability to log things.
For example the get_config_path function will print the path to the configuration file, which will get consumed by the do_work function:</description><content:encoded><![CDATA[<p>I write a lot of bash scripts for both my day job and my personal projects, and while they are functional, bash scripts always seem to lack that structure that I want, especially when compared to writing something in Go or C#. The main problem I have with bash scripts is that when I use functions, I lose the ability to log things.</p>
<p>For example the <code>get_config_path</code> function will print the path to the configuration file, which will get consumed by the <code>do_work</code> function:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>get_config_path<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Finding Machine Configurtaion&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -n <span style="color:#e6db74">&#34;</span>$CONFIG_PATH<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">[</span> -e <span style="color:#e6db74">&#34;</span>$CONFIG_PATH<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># echo &#34;Using Configuration from environment&#34;</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;</span>$CONFIG_PATH<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -e <span style="color:#e6db74">&#34;~/.config/demo/config.toml&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># echo &#34;Using Configuration directory file&#34;</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;~/.config/demo/config.toml&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># echo &#34;Unable to find configuration&#34;</span>
</span></span><span style="display:flex;"><span>  exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>do_work<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  local -r config<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>get_config_path<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># actual work...</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>The problem is, if I include the <code>echo</code> statements which are log lines, the <code>config</code> variable in the <code>do_work</code> function will contain them too.</p>
<p>In the past, this has caused me to use functions in bash very sparingly; usually with things that are short that I don&rsquo;t need to add much logging to.  However, I was recently building some AMIs, and happened to be browsing the <a href="https://github.com/hashicorp/terraform-aws-consul">Consul</a> and <a href="https://github.com/hashicorp/terraform-aws-vault">Vault</a> terraform module source, which uses several bash scripts which are written in a different style, which makes them vastly more maintainable.</p>
<p>So let&rsquo;s have a look at the new structure I use, which is heavily based off these scripts.</p>
<h2 id="better-bash-scripts">Better Bash Scripts</h2>
<p>Before we get to the implementation, make sure you are using <a href="https://github.com/koalaman/shellcheck/">ShellCheck</a> it provides static analysis of your scripts, pointing out many things like missing quotes, or incorrectly handling arrays.  It has plugins for all your favourite editors too.</p>
<h3 id="0-general-styles-and-constructs">0. General Styles and Constructs</h3>
<p>All variables should be declared <code>readonly</code>, and <code>local</code> if possible, to help prevent surprise values from being present if other functions forget to do the same.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#top level</span>
</span></span><span style="display:flex;"><span>readonly SCRIPT_NAME<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">$(</span>basename <span style="color:#e6db74">&#34;</span>$0<span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>some_method<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># within a method</span>
</span></span><span style="display:flex;"><span>  local -r config_path<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$1<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>Functions should assign their passed arguments to named variables as the first thing they do, preferably matching the variable name they are passed, which helps later when you are searching through a script for usages of &ldquo;config_file&rdquo; and not having to find other names/aliases for the same value.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>read_config<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  local -r config_file<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$1<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  local -r skip_validation<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$2<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># ...</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>invoke<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># ...</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  read_config <span style="color:#e6db74">&#34;</span>$config_file<span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span>$skip_validation<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><h3 id="1-error-handling">1. Error Handling</h3>
<p>It should go without saying, but you really need to start your scripts with the following:</p>
<pre tabindex="0"><code>#!/bin/bash

set -euo pipefail;
</code></pre><p>There are <a href="https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/">many better articles</a> on what these specifically do, but suffice to say:</p>
<ul>
<li><code>e</code> causes the script to stop on errors</li>
<li><code>u</code> causes it to error on undefined variables being used</li>
<li><code>o pipefail</code> causes a non-zero exit code from any command in a pipeline to fail the script too (rather than just the last command.)</li>
</ul>
<h3 id="2-logging">2. Logging</h3>
<p>The real advantage of this structure is we get to have log statements! This is achieved by doing all logging to <code>stderr</code> instead of <code>stdout</code>.  We use a standardised <code>log</code> function across all the scripts, which also includes the script&rsquo;s name so when calling other scripts you can see which one wrote the log line:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>readonly SCRIPT_NAME<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">$(</span>basename <span style="color:#e6db74">&#34;</span>$0<span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>log<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  local -r level<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$1<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  local -r message<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$2<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  local -r timestamp<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>date +<span style="color:#e6db74">&#34;%Y-%m-%d %H:%M:%S&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  &gt;&amp;<span style="color:#ae81ff">2</span> echo -e <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>timestamp<span style="color:#e6db74">}</span><span style="color:#e6db74"> [</span><span style="color:#e6db74">${</span>level<span style="color:#e6db74">}</span><span style="color:#e6db74">] [</span>$SCRIPT_NAME<span style="color:#e6db74">] </span><span style="color:#e6db74">${</span>message<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>Invoking the function is <code>log &quot;INFO&quot; &quot;Some status&quot;</code> or <code>log &quot;WARN&quot; &quot;Something concerning&quot;</code> etc.</p>
<h3 id="3-error-checking">3. Error Checking</h3>
<p>We have some standard assertion functions which are used by the script when starting up to validate arguments:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>assert_not_empty<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  local -r arg_name<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$1<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  local -r arg_value<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$2<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#f92672">[[</span> -z <span style="color:#e6db74">&#34;</span>$arg_value<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    log <span style="color:#e6db74">&#34;ERROR&#34;</span> <span style="color:#e6db74">&#34;The value for &#39;</span>$arg_name<span style="color:#e6db74">&#39; cannot be empty&#34;</span>
</span></span><span style="display:flex;"><span>    exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>assert_is_installed<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  local -r name<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$1<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#f92672">[[</span> ! <span style="color:#66d9ef">$(</span>command -v <span style="color:#e6db74">&#34;</span>$name<span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span> <span style="color:#f92672">]]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    log <span style="color:#e6db74">&#34;ERROR&#34;</span> <span style="color:#e6db74">&#34;The binary &#39;</span>$name<span style="color:#e6db74">&#39; is required by this script but is not installed or in the system&#39;s PATH.&#34;</span>
</span></span><span style="display:flex;"><span>    exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><h3 id="4-argument-parsing">4. Argument parsing</h3>
<p>When scripts need to take parameters in, I prefer to use long-flag style, as they are little more readable for people checking invocations again in the future.  This function is usually always called <code>run</code>, and is the last function defined, and is invoked immediately after definition, passing in all script arguments (<code>run &quot;$@&quot;</code>):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>run<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  local namespace<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span>
</span></span><span style="display:flex;"><span>  local suffix<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span>
</span></span><span style="display:flex;"><span>  local dry_run<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;false&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">while</span> <span style="color:#f92672">[[</span> $# -gt <span style="color:#ae81ff">0</span> <span style="color:#f92672">]]</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    local key<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$1<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> <span style="color:#e6db74">&#34;</span>$key<span style="color:#e6db74">&#34;</span> in
</span></span><span style="display:flex;"><span>      --namespace<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        namespace<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$2<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>        shift
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>      --suffix<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        assert_not_empty <span style="color:#e6db74">&#34;</span>$key<span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span>$2<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>        suffix<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$2<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>        shift
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>      --dry-run<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        dry_run<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;true&#34;</span>
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>      --help<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        print_usage
</span></span><span style="display:flex;"><span>        exit
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>      *<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        log <span style="color:#e6db74">&#34;ERROR&#34;</span> <span style="color:#e6db74">&#34;Unrecognized argument: </span>$key<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>        print_usage
</span></span><span style="display:flex;"><span>        exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">esac</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    shift
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># mandatory flag validation</span>
</span></span><span style="display:flex;"><span>  assert_not_empty <span style="color:#e6db74">&#34;--namespace&#34;</span> <span style="color:#e6db74">&#34;</span>$namespace<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># make sure tools are installed</span>
</span></span><span style="display:flex;"><span>  assert_is_installed <span style="color:#e6db74">&#34;vault&#34;</span>
</span></span><span style="display:flex;"><span>  assert_is_installed <span style="color:#e6db74">&#34;openssl&#34;</span>
</span></span><span style="display:flex;"><span>  assert_is_installed <span style="color:#e6db74">&#34;jq&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># do the work!</span>
</span></span><span style="display:flex;"><span>  local -r cert<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>generate_cert <span style="color:#e6db74">&#34;</span>$suffix<span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  store_cert <span style="color:#e6db74">&#34;</span>$namespace<span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span>$cert<span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span>$dry_run<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>run <span style="color:#e6db74">&#34;</span>$@<span style="color:#e6db74">&#34;</span>
</span></span></code></pre></div><p>The validation uses the <code>assert_not_empty</code> function defined above, which is used in two ways: after the <code>while</code> loop to check mandatory values have been filled in, and within the <code>case</code> statement for optional flags values.</p>
<p>We also use <code>assert_is_installed</code> to validate that utilities we need are installed, such as <code>vault</code>, <code>openssl</code> and <code>jq</code></p>
<p>The <code>print_usage</code> function is just a set of <code>echo</code> statements giving all the flags, and an example of invokation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>print_usage<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  echo
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Usage: </span>$SCRIPT_NAME<span style="color:#e6db74"> [OPTIONS]&#34;</span>
</span></span><span style="display:flex;"><span>  echo
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;This script creates a new certiticate, and it installs it into the right namespace&#34;</span>
</span></span><span style="display:flex;"><span>  echo
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Options:&#34;</span>
</span></span><span style="display:flex;"><span>  echo
</span></span><span style="display:flex;"><span>  echo -e <span style="color:#e6db74">&#34;  --namespace\tThe namespace to install the certificate in&#34;</span>
</span></span><span style="display:flex;"><span>  echo -e <span style="color:#e6db74">&#34;  --suffix\tAn optional suffix for the hostname&#34;</span>
</span></span><span style="display:flex;"><span>  echo -e <span style="color:#e6db74">&#34;  --dry-run\tDon&#39;t install the certificate&#34;</span>
</span></span><span style="display:flex;"><span>  echo
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Example:&#34;</span>
</span></span><span style="display:flex;"><span>  echo
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;  </span>$SCRIPT_NAME<span style="color:#e6db74"> --namespace test --dry-run&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><h2 id="usage">Usage</h2>
<p>I keep a single template file which has all of this written into it, and new scripts start off with a copy-paste of the template.  Could it be <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a>er? Sure, but then I have to deal with dependency management, and it&rsquo;s just not worth the hassle and overhead.</p>
]]></content:encoded></item><item><title>Sharing Docker Layers Between Build Agents</title><link>https://andydote.co.uk/2020/05/14/docker-layer-sharing/</link><pubDate>Thu, 14 May 2020 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2020/05/14/docker-layer-sharing/</guid><description>Recently, I noticed that when we pull a new version of our application&amp;rsquo;s docker container, it fetches all layers, not just the ones that change.
The problem is that we use ephemeral build agents, which means that each version of the application is built using a different agent, so Docker doesn&amp;rsquo;t know how to share the layers used. While we can pull the published container before we run the build, this only helps with the final stage of the build.</description><content:encoded><![CDATA[<p>Recently, I noticed that when we pull a new version of our application&rsquo;s docker container, it fetches all layers, not just the ones that change.</p>
<p>The problem is that we use ephemeral build agents, which means that each version of the application is built using a different agent, so Docker doesn&rsquo;t know how to share the layers used.  While we can pull the published container before we run the build, this only helps with the final stage of the build.  We want to cache the other stages of the build too, as the earlier layers don&rsquo;t change often, and can be quite slow to build.</p>
<p>We can achieve this by tweaking how we build our stages, which will also allow some other interesting optimisations.</p>
<h2 id="the-dockerfile">The Dockerfile</h2>
<p>An example dockerfile is below.  There are two stages, <code>builder</code> and <code>prod</code>.  In the case we are looking at, both the OS packages and application dependencies rarely change, but can take quite a while to install.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> node:14.2.0-alpine3.11 AS builder</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">WORKDIR</span><span style="color:#e6db74"> /app</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> apk add --no-cache make gcc g++ python<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> package.json yarn.lock ./<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> yarn install --no-progress --frozen-lockfile <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    yarn cache clean<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> ./src ./src<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> yarn build<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> node:14.2.0-alpine3.11 AS prod</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">WORKDIR</span><span style="color:#e6db74"> /app</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> package.json yarn.lock ./<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> yarn install --production --no-progress --frozen-lockfile <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    yarn cache clean<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">COPY</span> --from<span style="color:#f92672">=</span>builder /app/dist ./dist<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">CMD</span> [<span style="color:#e6db74">&#34;yarn&#34;</span>, <span style="color:#e6db74">&#34;start&#34;</span>]<span style="color:#960050;background-color:#1e0010">
</span></span></span></code></pre></div><p>The first step is to try and pull both <code>:builder</code> and <code>:latest</code> images.  We append <code>|| true</code> as the images might not exist yet, and we want the build to pass if they don&rsquo;t!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker pull app:builder <span style="color:#f92672">||</span> true
</span></span><span style="display:flex;"><span>docker pull app:latest <span style="color:#f92672">||</span> true
</span></span></code></pre></div><p>Now that we have the application images locally, we can proceed to building the <code>:builder</code> stage.  We tag it twice: once with just <code>app:builder</code> and once with the short-commit that built it.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker build <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --cache-from<span style="color:#f92672">=</span>app:builder <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --target builder <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -t app:builder-$COMMIT_SHORT <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -t app:builder <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    .
</span></span></code></pre></div><p>Now that we have built our <code>builder</code> stage, we can use this to do lots of other things which require both <code>dependencies</code> and <code>devDependencies</code>, such as running tests and linters, and we could even distribute these tasks to multiple other machines if we wanted extra parallelism:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker run --rm -it app:builder-$COMMIT_SHORT yarn test
</span></span><span style="display:flex;"><span>docker run --rm -it app:builder-$COMMIT_SHORT yarn test:integration
</span></span><span style="display:flex;"><span>docker run --rm -it app:builder-$COMMIT_SHORT yarn lint
</span></span></code></pre></div><p>Once we are happy with our tests, we can now build the production container, which we do by using the <code>--cache-from</code> directive twice; once with the builder image we just created, and once with the latest version of our application.  Note the order of the <code>--cache-from</code> parameters matters; this won&rsquo;t work if you specify the <code>app:latest</code> before <code>app:builder</code>!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker build <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --cache-from<span style="color:#f92672">=</span>app:builder <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --cache-from<span style="color:#f92672">=</span>app:latest <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -t app:$COMMIT_SHORT <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -t app:latest <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    .
</span></span></code></pre></div><p>Now we can publish everything.  We always publish the commit tagged version so that separate branch builds can be fetched and tested, and if the branch is <code>master</code>, we publish both the <code>:builder</code> and <code>:latest</code> tags:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker push app:$COMMIT_SHORT
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$BRANCH<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;master&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    docker push app:builder
</span></span><span style="display:flex;"><span>    docker push app:latest
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span></code></pre></div><p>The full build script looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker pull app:builder <span style="color:#f92672">||</span> true
</span></span><span style="display:flex;"><span>docker pull app:latest <span style="color:#f92672">||</span> true
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker build <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --cache-from<span style="color:#f92672">=</span>app:builder <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --target builder <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -t app:builder-$COMMIT_SHORT <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -t app:builder <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    .
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># run these in parallel</span>
</span></span><span style="display:flex;"><span>docker run --rm -it app:builder-$COMMIT_SHORT yarn test
</span></span><span style="display:flex;"><span>docker run --rm -it app:builder-$COMMIT_SHORT yarn test:integration
</span></span><span style="display:flex;"><span>docker run --rm -it app:builder-$COMMIT_SHORT yarn lint
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker build <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --cache-from<span style="color:#f92672">=</span>app:builder <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --cache-from<span style="color:#f92672">=</span>app:latest <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -t app:$COMMIT_SHORT <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -t app:latest <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    .
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker push app:$COMMIT_SHORT
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$BRANCH<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;master&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    docker push app:builder
</span></span><span style="display:flex;"><span>    docker push app:latest
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span></code></pre></div><h2 id="effects">Effects</h2>
<p>By publishing both our <code>:builder</code> and <code>:latest</code> tags, we can effectively share the layer caches for all build stages across all build agents.  As the layers are shared, pulling the images at the beginning of the builds is pretty fast, and the publishes at the end of the build are very, very fast.</p>
<p>The real benefit comes with building our monolith, which now only needs a small layer to be pulled on deployment, rather than all of the layers, which speeds up our deployments by minutes per host.</p>
]]></content:encoded></item><item><title>Service Mesh with Consul Connect (and Nomad)</title><link>https://andydote.co.uk/2020/05/04/service-mesh-consul-connect/</link><pubDate>Mon, 04 May 2020 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2020/05/04/service-mesh-consul-connect/</guid><description>When it comes to implementing a new feature in an application&amp;rsquo;s ecosystem, I don&amp;rsquo;t like spending my innovation tokens unless I have to, so I try not to add new tools to my infrastructure unless I really need them.
This same approach comes when I either want, need, or have been told, to implement a Service Mesh. This means I don&amp;rsquo;t instantly setup Istio. Not because it&amp;rsquo;s bad - far from it - but because it&amp;rsquo;s extra complexity I would rather avoid, unless I need it.</description><content:encoded><![CDATA[<p>When it comes to implementing a new feature in an application&rsquo;s ecosystem, I <a href="https://mcfunley.com/choose-boring-technology">don&rsquo;t like spending my innovation tokens</a> unless I have to, so I try not to add new tools to my infrastructure unless I <em>really</em> need them.</p>
<p>This same approach comes when I either want, need, or have been told, to implement a Service Mesh.  This means I don&rsquo;t instantly setup <a href="https://istio.io/">Istio</a>.  Not because it&rsquo;s bad - far from it - but because it&rsquo;s extra complexity I would rather avoid, unless I need it.</p>
<p>But what alternatives are there?</p>
<p>In most large systems I have been involved with <a href="https://www.consul.io">Consul</a> has been deployed;  usually for Service Discovery, <a href="/2018/09/06/consul-feature-toggles/">Feature Toggles</a>, it&rsquo;s key-value store, or distributed locking.  As Consul has Service Mesh functionality built in, why not use that?</p>
<p>So let&rsquo;s dive into setting up a <a href="https://www.consul.io/docs/connect/index.html">Consul Connect</a> based Service Mesh.</p>
<h2 id="implementing">Implementing</h2>
<p>The demo for this is made up of two parts (taken from HashiCorp&rsquo;s consul demo repo): a counter and a dashboard.  The counter listens for HTTP requests and will return the number of requests it&rsquo;s handled.  The dashboard polls the counter and displays the current count.</p>
<p>All the source code for the demo is in the <a href="https://github.com/Pondidum/consul-connect-nomad-demo">Consul Connect Example Repository</a>.</p>
<p>Clone the repository, and run the build script to create the apps:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git clone https://github.com/Pondidum/consul-connect-nomad-demo
</span></span><span style="display:flex;"><span>cd consul-connect-nomad-demo
</span></span><span style="display:flex;"><span>./apps/build.sh
</span></span></code></pre></div><h3 id="local-run">Local Run</h3>
<p>Run the apps locally to prove they work, in two separate terminals:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>PORT<span style="color:#f92672">=</span><span style="color:#ae81ff">9001</span> ./apps/bin/counter
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>PORT<span style="color:#f92672">=</span><span style="color:#ae81ff">9002</span> ./apps/bin/dashboard
</span></span></code></pre></div><p>Open <code>http://localhost:9002</code> to see the counter running.</p>
<h3 id="start-a-cluster">Start A Cluster</h3>
<p>Now we have established our apps actually start, we can create a small Consul cluster.  I am using my Hashibox to do this, so you&rsquo;ll need libvirt and Vagrant installed to do this.</p>
<p>Running <code>vagrant up</code> will spawn three machines, which will form a Consul cluster, which we can now experiment in.  Once it is up and running, we can manually register the two applications into Consul&rsquo;s service mesh to check that our in cluster communication works.</p>
<p>First, the counter service.  The script writes a service definition into consul, which, by specifying the <code>connect</code> stanza, indicates this service is to be included in the service mesh.  Once this is done, the counter is started (and sent to the background), and a consul connect proxy is started for this service:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl --request PUT --url http://localhost:8500/v1/agent/service/register <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --data <span style="color:#e6db74">&#39;{
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;name&#34;: &#34;counter&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;port&#34;: 9001,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;connect&#34;: {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#34;sidecar_service&#34;: {}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    }
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  }&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>PORT<span style="color:#f92672">=</span><span style="color:#ae81ff">9001</span> /vagrant/apps/bin/counter &amp;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>consul connect proxy -sidecar-for counter
</span></span></code></pre></div><p>We can run this script in a new terminal by running this command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vagrant ssh one -c <span style="color:#e6db74">&#39;/vagrant/scripts/counter.sh&#39;</span>
</span></span></code></pre></div><p>Finally, we start the dashboard.  The script is very similar, in that we write a service definiton into consul, start the service and run a proxy.  The only notable difference is the service registation payload itself:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;dashboard&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;port&#34;</span>: <span style="color:#ae81ff">9002</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;connect&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;sidecar_service&#34;</span>: {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;proxy&#34;</span>: {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;upstreams&#34;</span>: [
</span></span><span style="display:flex;"><span>          { <span style="color:#f92672">&#34;destination_name&#34;</span>: <span style="color:#e6db74">&#34;counter&#34;</span>, <span style="color:#f92672">&#34;local_bind_port&#34;</span>: <span style="color:#ae81ff">8080</span> }
</span></span><span style="display:flex;"><span>        ]
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As before, it registers a service, and on what port it will be listening on, but in the <code>connect</code> stanza, we specify that we want to connect to the <code>counter</code>, and we want to talk to it on <code>localhost:8080</code>.</p>
<p>In a new terminal, you can run this script like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vagrant ssh two -c <span style="color:#e6db74">&#39;/vagrant/scripts/dashboard.sh&#39;</span>
</span></span></code></pre></div><p>Now that both are up and running, you can open a browser to the dashboard and see it working: <code>http://two.karhu.xyz:9002</code>.  Once you are satisfied, you can stop the services by hitting <code>ctrl+c</code> in both terminals&hellip;or try running a second counter or dashboard on the third vagrant machine (<code>vagrant ssh three -c '/vagrant/scripts/dashboard.sh'</code>)</p>
<h3 id="nomad">Nomad</h3>
<p>Now that we have seen how to run the services manually let&rsquo;s see how easy it is to use the service mesh using <a href="https://nomadproject.io">Nomad</a>.</p>
<p>There are two nomad job definitions in the included project, so let&rsquo;s look at the counter&rsquo;s first:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">job</span> <span style="color:#e6db74">&#34;counter&#34;</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">datacenters</span> = [<span style="color:#e6db74">&#34;dc1&#34;</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">group</span> <span style="color:#e6db74">&#34;api&#34;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">count</span> = <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">network</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">mode</span> = <span style="color:#e6db74">&#34;bridge&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">service</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">name</span> = <span style="color:#e6db74">&#34;count-api&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">port</span> = <span style="color:#e6db74">&#34;9001&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">connect</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">sidecar_service</span> {}
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">task</span> <span style="color:#e6db74">&#34;counter&#34;</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">driver</span> = <span style="color:#e6db74">&#34;exec&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">config</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">command</span> = <span style="color:#e6db74">&#34;/vagrant/apps/bin/counter&#34;</span>
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">env</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">PORT</span> = <span style="color:#ae81ff">9001</span>
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>network</code> stanza is set to <code>bridge</code> mode, which creates us an isolated network between all the services in the group only.  In our case, we will have a single <code>counter</code> service and the proxy.</p>
<p>The <code>service</code> stanza is replicating the same functionality we had by writing a service registration into Consul.  By specifying the <code>connect</code> part, Nomad knows that it also needs to start a proxy-based on the service stanza&rsquo;s settings, and will handle starting and stopping this proxy for us.</p>
<p>The <code>task &quot;counter&quot;</code> block uses the <code>exec</code> driver to run the counter app natively on the host, but <code>docker</code>, <code>java</code>, and others are available too.</p>
<p>To run this into our Nomad cluster, we can use the nomad CLI:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export NOMAD_ADDR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://one.karhu.xyz:4646&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>nomad job run apps/counter/counter.nomad
</span></span></code></pre></div><p>The dashboard&rsquo;s Nomad job is very similar:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">job</span> <span style="color:#e6db74">&#34;dashboard&#34;</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">datacenters</span> = [<span style="color:#e6db74">&#34;dc1&#34;</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">group</span> <span style="color:#e6db74">&#34;dashboard&#34;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">network</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">mode</span> = <span style="color:#e6db74">&#34;bridge&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">port</span> <span style="color:#e6db74">&#34;http&#34;</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">to</span>     = <span style="color:#ae81ff">9002</span>
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">service</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">name</span> = <span style="color:#e6db74">&#34;count-dashboard&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">port</span> = <span style="color:#ae81ff">9002</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">connect</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">sidecar_service</span> {
</span></span><span style="display:flex;"><span>          <span style="color:#a6e22e">proxy</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">upstreams</span> {
</span></span><span style="display:flex;"><span>              <span style="color:#a6e22e">destination_name</span> = <span style="color:#e6db74">&#34;count-api&#34;</span>
</span></span><span style="display:flex;"><span>              <span style="color:#a6e22e">local_bind_port</span>  = <span style="color:#ae81ff">8080</span>
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>          }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">task</span> <span style="color:#e6db74">&#34;dashboard&#34;</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">driver</span> = <span style="color:#e6db74">&#34;exec&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">config</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">command</span> = <span style="color:#e6db74">&#34;/vagrant/apps/bin/dashboard&#34;</span>
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">env</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">PORT</span> = <span style="color:#e6db74">&#34;${NOMAD_PORT_http}&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">COUNTING_SERVICE_URL</span> = <span style="color:#e6db74">&#34;http://${NOMAD_UPSTREAM_ADDR_count_api}&#34;</span>
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>network</code> block this time also specifies that we want to expose our service to the public.  As we don&rsquo;t have a <code>static = 9002</code> in the port definition, Nomad will assign one at random (this is better! You can avoid port clashes with multiple tasks on the same node), we do however specify that we will map to <code>9002</code>.  The rest of the file can use the Nomad variable <code>NOMAD_PORT_http</code> to get this port number, so we don&rsquo;t have to copy-paste the number everywhere.  Similarly, the <code>sidecar_service</code> stanza exposes a variable called <code>NOMAD_UPSTREAM_ADDR_&lt;destination_name&gt;</code>, so we can use that too for our dashboard task&rsquo;s environment variable values. This means we should only ever need to specify ports in 1 location in a Nomad file.</p>
<p>As with the counter, we can run the job using the CLI:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>nomad job run apps/counter/dashboard.nomad
</span></span></code></pre></div><p>If we want to get the address and port the dashboard is actually running at, it is easiest to go through the UI, but you can also get the information from the console using the Nomad CLI and jq:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>allocation_id<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>nomad alloc status -json | jq -r <span style="color:#e6db74">&#39;.[] | select(.JobID == &#34;dashboard&#34;) | .ID&#39;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>nomad alloc status -json <span style="color:#e6db74">&#34;</span>$allocation_id<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  | jq -r <span style="color:#e6db74">&#39;.AllocatedResources.Shared.Networks[0] | ( &#34;http://&#34; + .IP + &#34;:&#34; + (.DynamicPorts[] | select(.Label == &#34;http&#34;) | .Value | tostring))&#39;</span>
</span></span></code></pre></div><h2 id="wrapping-up">Wrapping Up</h2>
<p>With Consul Connect&rsquo;s supported APIs, there is great flexibility in how you can implement your service mesh; through definition files, through API requests, or through the container orchestrator directly.  Couple this with Consul already being in use in most systems I have been involved with, and hopefully you can see why it makes a great way of having a Service Mesh.</p>
]]></content:encoded></item><item><title>Observability Without Honeycomb</title><link>https://andydote.co.uk/2020/03/15/observability-without-honeycomb/</link><pubDate>Sun, 15 Mar 2020 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2020/03/15/observability-without-honeycomb/</guid><description>Before I start on this, I want to make it clear that if you can buy Honeycomb, you should. Outlined below is how I started to add observability to an existing codebase which already had the ELK stack available, and was unable to use Honeycomb. My hope, in this case, is that I can demonstrate how much value observability gives, and also show how much more value you would get with an excellent tool, such as Honeycomb.</description><content:encoded><![CDATA[<p>Before I start on this, I want to make it clear that if you can buy <a href="https://honeycomb.io">Honeycomb</a>, you <strong>should</strong>.  Outlined below is how I started to add observability to an existing codebase which already had the <a href="https://www.elastic.co/what-is/elk-stack">ELK stack</a> available, and was unable to use Honeycomb.  My hope, in this case, is that I can demonstrate how much value observability gives, and also show how much <em>more</em> value you would get with an excellent tool, such as Honeycomb.</p>
<p>With that said, what is observability, how is it different to logging (and metrics), and why should you care?</p>
<p>If you already know, or would rather skip to the implementation, jump to <a href="#implementing-with-elastic-search">Implementing with Elastic Search</a>.</p>
<h2 id="what-is-it">What is it?</h2>
<p>The term Observability comes from systems engineering and is how you can determine the behaviour of the entire system from its outputs.  In our case, this means the <strong>events</strong> we emit while processing requests.  If we look at (my) hierarchy of monitoring, you can see that it starts with logging, with the next steps up being to output structured logs, then centralising those logs (no more SSHing into random hosts), and finally onto events:</p>
<blockquote>
<p>logs &lt; structured logs &lt; centralised structured logs &lt; events (observability)</p>
</blockquote>
<h2 id="the-problem-with-logs-and-metrics">The Problem with Logs and Metrics</h2>
<p>With logs, you are writing out many lines as your process runs, which has a few problems, the primary being that you are often looking for data which is absent.</p>
<p>How many times have you been looking through many lines of logs, before realising &ldquo;oh, the line about cache invalidation is missing, which means&hellip;&rdquo;.  It is much harder to notice data which is absent than data which is present, but with an unexpected value.</p>
<p>The second problem is the size of the logs saved.  Logs, especially structured ones, contain a lot of useful information, such as request ids, session ids, paths, versions, host data, and anything else interesting.  The majority of these fields are repeated for every log entry in the system, and that means they need to be stored and queryable at some point.  Often, this is solved by deleting historical data, or sampling at write time, both of which cause data loss, and you are back to trying to notice data which isn&rsquo;t there.</p>
<p>Metrics exhibit the data loss problem <em>by design</em>.  Metrics are deliberately aggregated client-side and then shipped to storage.  The numbers you get from metrics can be useful, but when you look at where they come from, it becomes evident that they are just a projection of logs themselves.  How many codebases have you read where every <code>loggger.Info(&quot;...&quot;, props);</code> line is followed (or preceded) by <code>stats.increment(&quot;some_counter)</code>?</p>
<h2 id="so-what-is-an-event">So What is an Event?</h2>
<p>An Event is a structured piece of data, with as much information about the current request in it as possible.  The difference is that you emit <strong>one</strong> event per request <strong>per service</strong>, if you are doing microservices.  You create an event at the beginning of handling a request and send it somewhere at the end of the request (whether successful or unsuccessful).</p>
<p>For things like background tasks, again, emitting one event per execution, and in well-structured monoliths, one event per request per component.</p>
<p>This doesn&rsquo;t sound like much of a difference, until you start writing your code to add interesting properties to the event, rather than log lines.  We want to store as much high cardinality data as possible (so anything unique, or nearly unique), the more of it, the better, as it lets us slice and dice our events by anything at a later time (e.g. by requestid, userid, endpoint paths, url parameters, http method, etc.)</p>
<p>Looking at the caching example mentioned above, before we had this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">handleRequest</span>(<span style="color:#a6e22e">request</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">Request</span>) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">now</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Now</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">cache</span>[<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">UserID</span>] <span style="color:#f92672">==</span> <span style="color:#66d9ef">nil</span> <span style="color:#f92672">||</span> <span style="color:#a6e22e">cache</span>[<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">UserID</span>].<span style="color:#a6e22e">IsStale</span>(<span style="color:#a6e22e">now</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">logger</span>.<span style="color:#a6e22e">Write</span>(<span style="color:#e6db74">&#34;Cache miss for user&#34;</span>, <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">UserID</span>))
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">stats</span>.<span style="color:#a6e22e">Increment</span>(<span style="color:#e6db74">&#34;cache_misses&#34;</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">fillCache</span>(<span style="color:#a6e22e">cache</span>, <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">UserID</span>)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">stats</span>.<span style="color:#a6e22e">set</span>(<span style="color:#e6db74">&#34;request_duration&#34;</span>, <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Since</span>(<span style="color:#a6e22e">now</span>))
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>When the user is in the cache, there is no logline written, which is fine when everything is working.  However, when something unexpected happens, like daylight savings time or sudden clock drift, and suddenly all cache entries are never stale.  You have a decrease in latency (which looks good), your <code>cache_misses</code> counter goes down (looks good), but your data is older than you realised, and bad things are happening down the line.</p>
<p>If you were to write this function with observability in mind, you might write something like this instead:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">handleRequest</span>(<span style="color:#a6e22e">request</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">Request</span>) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">ev</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">libhoney</span>.<span style="color:#a6e22e">NewEvent</span>()
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">Send</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">now</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Now</span>()
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">Timestamp</span> = <span style="color:#a6e22e">now</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">Add</span>(<span style="color:#66d9ef">map</span>[<span style="color:#66d9ef">string</span>]<span style="color:#66d9ef">interface</span>{}{
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;request_id&#34;</span>: <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">ID</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;request_path&#34;</span>: <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">Path</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;request_method&#34;</span>: <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">method</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;user_id&#34;</span>: <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">UserID</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;cache_size&#34;</span>: len(<span style="color:#a6e22e">cache</span>),
</span></span><span style="display:flex;"><span>    })
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">userData</span>, <span style="color:#a6e22e">found</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">cache</span>[<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">UserID</span>]
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#e6db74">&#34;cache_hit&#34;</span>, <span style="color:#a6e22e">found</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> !<span style="color:#a6e22e">found</span> <span style="color:#f92672">||</span> <span style="color:#a6e22e">userData</span>.<span style="color:#a6e22e">IsStale</span>(<span style="color:#a6e22e">now</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">userData</span> = <span style="color:#a6e22e">fillCache</span>(<span style="color:#a6e22e">ev</span>, <span style="color:#a6e22e">cache</span>, <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">UserID</span>)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#e6db74">&#34;cache_expires&#34;</span>, <span style="color:#a6e22e">userData</span>.<span style="color:#a6e22e">CacheUntil</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#e6db74">&#34;cache_is_stale&#34;</span>, <span style="color:#a6e22e">userData</span>.<span style="color:#a6e22e">IsStale</span>(<span style="color:#a6e22e">now</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">AddField</span>(<span style="color:#e6db74">&#34;request_duration_ms&#34;</span>, <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Since</span>(<span style="color:#a6e22e">now</span>) <span style="color:#f92672">/</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Millisecond</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The resulting event will contain enough information so that in the future when a bug is introduced, you will be able to look at your events and see that yes, while <code>request_duration_ms</code> has gone down and <code>cache_hit</code> has gone up, all the events have <code>cache_is_stale=false</code> with <code>cache_expires</code> times much older than they should be.</p>
<p>So this is the value add of Observability: Answering Unknown Unknowns; the questions you didn&rsquo;t know you needed to ask.</p>
<h2 id="implementing-with-elastic-search">Implementing with Elastic Search</h2>
<p>I won&rsquo;t cover how to set up and manage the ELK stack (as my opinion is that you should pay someone else to run it.  Don&rsquo;t waste your engineering effort.)  I will assume you have a way to get information from <code>stdout</code> of a process into ElasticSearch somehow (I usually use piping to <a href="https://www.elastic.co/beats/filebeat">Filebeat</a>, which forwards to <a href="https://www.elastic.co/logstash">LogStash</a>, which processes and pushes into <a href="https://www.elastic.co/elasticsearch/">ElasticSearch</a>).</p>
<p>Besides, the code is the important part.  This is all written in Go, but I gather you can do similar to NodeJS apps etc.  We will use Honeycomb&rsquo;s [Libhoney-go] package to do the heavy lifting, and supply a custom <code>Transmission</code>.  The following is the important part of a custom stdout write (loosely based on libhoney&rsquo;s <code>WriterSender</code>):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> (<span style="color:#a6e22e">w</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">JsonSender</span>) <span style="color:#a6e22e">Add</span>(<span style="color:#a6e22e">ev</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">transmission</span>.<span style="color:#a6e22e">Event</span>) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">Data</span>[<span style="color:#e6db74">&#34;@timestamp&#34;</span>] = <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">Timestamp</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">content</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">json</span>.<span style="color:#a6e22e">Marshal</span>(<span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">Data</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">content</span> = append(<span style="color:#a6e22e">content</span>, <span style="color:#e6db74">&#39;\n&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">w</span>.<span style="color:#a6e22e">Lock</span>()
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">w</span>.<span style="color:#a6e22e">Unlock</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">w</span>.<span style="color:#a6e22e">Writer</span>.<span style="color:#a6e22e">Write</span>(<span style="color:#a6e22e">content</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">w</span>.<span style="color:#a6e22e">SendResponse</span>(<span style="color:#a6e22e">transmission</span>.<span style="color:#a6e22e">Response</span>{
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">Metadata</span>: <span style="color:#a6e22e">ev</span>.<span style="color:#a6e22e">Metadata</span>,
</span></span><span style="display:flex;"><span>    })
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The key difference here is that I am only serialising the <code>.Data</code> property of the Event, and am inserting an extra <code>@timestamp</code> key to make my event structure conform to the standard LogStash pattern.</p>
<p>All that remains to do is configure libhoney to use the custom sender:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">libhoney</span>.<span style="color:#a6e22e">Init</span>(<span style="color:#a6e22e">libhoney</span>.<span style="color:#a6e22e">Config</span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">Transmission</span>: <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">JsonSender</span>{<span style="color:#a6e22e">Writer</span>: <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Stdout</span>},
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">Dataset</span>:      <span style="color:#e6db74">&#34;my-api&#34;</span>,
</span></span><span style="display:flex;"><span>})
</span></span></code></pre></div><p>Running your service, you would start to see json objects on stdout which look something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;@timestamp&#34;</span>: <span style="color:#e6db74">&#34;2020-03-15T14:51:43.041744363+02:00&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;request_id&#34;</span>: <span style="color:#e6db74">&#34;7f46b313-0a37-457c-9727-b6fdc8c87733&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;request_path&#34;</span>: <span style="color:#e6db74">&#34;/api/user/dashboard&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;request_method&#34;</span>: <span style="color:#e6db74">&#34;GET&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;user_id&#34;</span>: <span style="color:#e6db74">&#34;e6baf70f-9812-4cff-94e9-80a308077955&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;cache_size&#34;</span>: <span style="color:#ae81ff">86</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;cache_hit&#34;</span>: <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;cache_expires&#34;</span>: <span style="color:#e6db74">&#34;2020-03-15T15:02:17.045625680+02:00&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;cache_is_stale&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;request_duration_ms&#34;</span>: <span style="color:#ae81ff">17</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>There are no message fields for you to read, but you can see everything which happened in this method; whether the user was found in the cache, how big the cache was etc.</p>
<p>Now if we push that into ElasticSearch, we can filter by any of the values in the event; in this case, I filtered by <code>user_id</code> and added columns for all the cache properties.</p>
<p><img loading="lazy" src="observability-elk.png" alt="Kibana Screenshot"  />
</p>
<p>Now everything is in one place; you can slice and dice your data and figure out what exactly is going on.  You can even write some metrics off your event queries if you want!</p>
<h2 id="improvements--caveats">Improvements &amp; Caveats</h2>
<p>The main caveat is that pushing this into ElasticSearch is not as good as what you get from Honeycomb - It is just an improvement on logging messages and enables you to demonstrate the value of observability easily.</p>
<p>Once you&rsquo;ve demonstrated how useful observability is, the next step is to migrate to Honeycomb and get even more value.</p>
<p>I have written the word Honeycomb a lot in this post (9 times so far), but I want to stress that it is observability that we are after and that Honeycomb is an implementation detail.  It also happens to be the only real observability tooling (although <a href="https://lightstep.com/">Lightstep</a>, kind of.)</p>
<p>And let&rsquo;s not get started on the &ldquo;3 pillars of observability&rdquo; bullshit being peddled by other vendors.</p>
]]></content:encoded></item><item><title>Nomad Isolated Exec</title><link>https://andydote.co.uk/2020/02/29/nomad-isolated-exec/</link><pubDate>Sat, 29 Feb 2020 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2020/02/29/nomad-isolated-exec/</guid><description>One of the many features of Nomad that I like is the ability to run things other than Docker containers. It has built-in support for Java, QEMU, and Rkt, although the latter is deprecated. Besides these inbuilt &amp;ldquo;Task Drivers&amp;rdquo; there are community maintained ones too, covering Podman, LXC, Firecraker and BSD Jails, amongst others.
The one I want to talk about today, however, is called exec. This Task Driver runs any given executable, so if you have an application which you don&amp;rsquo;t want (or can&amp;rsquo;t) put into a container, you can still schedule it with Nomad.</description><content:encoded><![CDATA[<p>One of the many features of <a href="https://nomadproject.io">Nomad</a> that I like is the ability to run things other than Docker containers.  It has built-in support for Java, QEMU, and Rkt, although the latter is deprecated.  Besides these inbuilt &ldquo;Task Drivers&rdquo; there are community maintained ones too, covering Podman, LXC, Firecraker and BSD Jails, amongst others.</p>
<p>The one I want to talk about today, however, is called <code>exec</code>.  This Task Driver runs any given executable, so if you have an application which you don&rsquo;t want (or can&rsquo;t) put into a container, you can still schedule it with Nomad.  When I run demos (particularly at conferences), I try to have everything runnable without an internet connection, which means I have to make sure all the Docker containers I wish to run are within a local Docker Registry already, and, well, sometimes I forget.  By using <code>exec</code>, I can serve a binary off my machine with no container overheads involved.</p>
<h2 id="insecurity">Insecurity?</h2>
<p>Until recently, I had always considered <code>exec</code> as a tradeoff: I don&rsquo;t need a docker container, but I lose the isolation of the container, and the application I run has full access to everything on this host.</p>
<p>What I hadn&rsquo;t realised, is that <code>exec</code> actually uses the host operating system&rsquo;s isolation features via the <a href="https://pkg.go.dev/github.com/opencontainers/runc/libcontainer?tab=doc">libcontainer</a> package to contain the application.  On Linux, this means using <code>cgroups</code> and a <code>chroot</code>, making the level of isolation roughly the same as a docker container provides.</p>
<p>When you specify a binary to run, it must meet a few criteria:</p>
<ul>
<li>An absolute path within Nomad&rsquo;s <code>chroot</code></li>
<li>A relative path within the Allocation Directory</li>
</ul>
<p>For instance, to run a dotnet core application consists of invoking <code>/usr/bin/dotnet</code> with the relative path of the dll extracted from the artifact:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>task <span style="color:#e6db74">&#34;consumer&#34;</span> {
</span></span><span style="display:flex;"><span>    driver <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;exec&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    config {
</span></span><span style="display:flex;"><span>        command <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/usr/bin/dotnet&#34;</span>
</span></span><span style="display:flex;"><span>        args <span style="color:#f92672">=</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;local/Consumer.dll&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    artifact {
</span></span><span style="display:flex;"><span>        source <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http://s3.internal.net/consumer-dotnet.zip&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Whereas running a go binary can be done with a path relative to the allocation directory:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>task <span style="color:#e6db74">&#34;consumer&#34;</span> {
</span></span><span style="display:flex;"><span>    driver <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;exec&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    config {
</span></span><span style="display:flex;"><span>        command <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;local/consumer&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    artifact {
</span></span><span style="display:flex;"><span>        source <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http://s3.internal.net/consumer-go.zip&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>But what happens if we want to run a binary which is not within the default chroot environment used by <code>exec</code>?</p>
<h2 id="configuring-the-chroot-environment">Configuring The chroot Environment</h2>
<p>By default, Nomad links the following paths into the task&rsquo;s chroot:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>[
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/bin&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/etc&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/lib&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/lib32&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/lib64&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/run/resolvconf&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/sbin&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/usr&#34;</span>
</span></span><span style="display:flex;"><span>]
</span></span></code></pre></div><p>We can configure the <code>chroot</code> per Nomad client, meaning we can provision nodes with different capabilities if necessary.  This is done with the <code>chroot_env</code> setting in the client&rsquo;s configuration file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>client {
</span></span><span style="display:flex;"><span>  chroot_env {
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/bin&#34;</span>            <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/bin&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/etc&#34;</span>            <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/etc&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/lib&#34;</span>            <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/lib&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/lib32&#34;</span>          <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/lib32&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/lib64&#34;</span>          <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/lib64&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/run/resolvconf&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/run/resolvconf&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/sbin&#34;</span>           <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/sbin&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/usr&#34;</span>            <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/usr&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/vagrant&#34;</span>        <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/vagrant&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In this case, I have added in the <code>/vagrant</code> path, which is useful as I usually provision a Nomad cluster using <a href="https://vagrantup.com">Vagrant</a>, and thus have all my binaries etc. available in <code>/vagrant</code>.  It means that my <code>.nomad</code> files for the demo have something like this for their tasks:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>task <span style="color:#e6db74">&#34;dashboard&#34;</span> {
</span></span><span style="display:flex;"><span>    driver <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;exec&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    config {
</span></span><span style="display:flex;"><span>        command <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/vagrant/apps/bin/dashboard&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Meaning I don&rsquo;t need to host a Docker Registry, or HTTP server to expose my applications to the Nomad cluster.</p>
<h2 id="need-full-access">Need Full Access?</h2>
<p>If you need full access to the host machine, you can use the non-isolating version of <code>exec</code>, called <code>raw_exec</code>.  <code>raw_exec</code> works in the same way as <code>exec</code>, but without using <code>cgroups</code> and <code>chroot</code>.  As this would be a security risk, it must be enabled on each Nomad client:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>client {
</span></span><span style="display:flex;"><span>    enabled <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>plugin <span style="color:#e6db74">&#34;raw_exec&#34;</span> {
</span></span><span style="display:flex;"><span>    config {
</span></span><span style="display:flex;"><span>        enabled <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="wrapping-up">Wrapping Up</h2>
<p>One of the many reasons I like Nomad is its simplicity, especially when compared to something as big and complex as Kubernetes.  Whenever I look into how Nomad works, I always seem to come away with the feeling that it has been well thought out, and how flexible it is because of this.</p>
<p>Being able to configure the chroot used by the Nomad clients means I can simplify my various demos further, as I can remove the need to have a webserver for an artifact source. As always, the less accidental complexity you have in your system, the better.</p>
]]></content:encoded></item><item><title>Consul DNS Fowarding in Alpine, revisited</title><link>https://andydote.co.uk/2019/12/30/consul-alpine-dns-revisited/</link><pubDate>Mon, 30 Dec 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/12/30/consul-alpine-dns-revisited/</guid><description>I noticed when running an Alpine based virtual machine with Consul DNS forwarding set up, that sometimes the machine couldn&amp;rsquo;t resolve *.consul domains, but not in a consistent manner. Inspecting the logs looked like the request was being made and responded to successfully, but the result was being ignored.
After a lot of googling and frustration, I was able to track down that it&amp;rsquo;s down to a difference (or optimisation) in musl libc, which glibc doesn&amp;rsquo;t do.</description><content:encoded><![CDATA[<p>I noticed when running an Alpine based virtual machine with Consul DNS forwarding set up, that sometimes the machine couldn&rsquo;t resolve <code>*.consul</code> domains, but not in a consistent manner. Inspecting the logs looked like the request was being made and responded to successfully, but the result was being ignored.</p>
<p>After a lot of googling and frustration, I was able to track down that it&rsquo;s down to a difference (or optimisation) in musl libc, which glibc doesn&rsquo;t do. From Musl libc&rsquo;s <a href="https://wiki.musl-libc.org/functional-differences-from-glibc.html">Functional differences from glibc</a> page, we can see under the Name Resolver/DNS section the relevant information:</p>
<blockquote>
<p>Traditional resolvers, including glibc&rsquo;s, make use of multiple nameserver lines in resolv.conf by trying each one in sequence and falling to the next after one times out. musl&rsquo;s resolver queries them all in parallel and accepts whichever response arrives first.</p>
</blockquote>
<p>The machine&rsquo;s <code>/etc/resolv.conf</code> file has two <code>nameserver</code> specified:</p>
<pre tabindex="0"><code>nameserver 127.0.0.1
nameserver 192.168.121.1
</code></pre><p>The first is our <code>Unbound</code> instance which handles the forwarding to Consul, and the second is the DHCP set DNS server, in this case, libvirt/qemu&rsquo;s dnsmasq instance.</p>
<p>When running in a glibc based system, queries go to the first <code>nameserver</code>, and then if that can&rsquo;t resolve the request, it is then sent to the next <code>nameserver</code>, and so forth. As Alpine Linux uses muslc, it makes the requests in parallel and uses the response from whichever response comes back first.</p>
<p><img loading="lazy" src="muslc-dns.png" alt="sequence diagram, showing parallel DNS requests"  />
</p>
<p>When the DHCP DNS server is a network hop away, the latency involved means our resolution usually works, as the queries will hit the local DNS and get a response first. However, when the DHCP DNS is not that far away, for example when it is the DNS server that libvirt runs in the virtual network the machine is attached to, it becomes much more likely to get a response from that DNS server first, causing the failures I was seeing.</p>
<p>The solution to this is to change the setup so that all requests go to Unbound, which can then decide where to send them on to.  This also has the additional benefits of making all DNS requests work the same on all systems; regardless of glibc or muslc being used.</p>
<p><img loading="lazy" src="unbound-dns.png" alt="sequence diagram, showing all DNS requests going through unbound"  />
</p>
<h2 id="rebuilding-dns-resolution">Rebuilding DNS Resolution</h2>
<p>You can follow the same instructions in my previous <a href="/2019/05/31/consul-dns-forwarding-alpine/#run-consul">Consul DNS forwarding</a> post to setup Consul, as that is already in the right state for us.</p>
<p>Once Consul is up and running, it&rsquo;s time to fix the rest of our pipeline.</p>
<h3 id="unbound">Unbound</h3>
<p>First, install <code>unbound</code> and configure it to start on boot:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>apk add unbound
</span></span><span style="display:flex;"><span>rc-update add unbound
</span></span></code></pre></div><p>The unbound config file (<code>/etc/unbound/unbound.conf</code>) is almost the same as the previous version, except we also have an <code>include</code> statement, pointing to a second config file, which we will generate shortly:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">server</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">verbosity</span>: <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">do-not-query-localhost</span>: <span style="color:#66d9ef">no</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">domain-insecure</span>: <span style="color:#e6db74">&#34;consul&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">stub-zone</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">name</span>: <span style="color:#e6db74">&#34;consul&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">stub-addr</span>: <span style="color:#ae81ff">127.0.0.1</span>@<span style="color:#ae81ff">8600</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">include</span>: <span style="color:#e6db74">&#34;/etc/unbound/forward.conf&#34;</span>
</span></span></code></pre></div><h3 id="dhclient">Dhclient</h3>
<p>Next, we install <code>dhclient</code> so that we can make use of it&rsquo;s hooks feature to generate our additional unbound config file.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>apk add dhclient
</span></span></code></pre></div><p>Create a config file for dhclient (<code>/etc/dhcp/dhclient.conf</code>), which again is almost the same as the previous post, but this time doesn&rsquo;t specify <code>prepend domain-name-servers</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-conf" data-lang="conf"><span style="display:flex;"><span><span style="color:#66d9ef">option</span> rfc3442-classless-static-routes code 121 <span style="color:#f92672">=</span> array of unsigned integer 8;
</span></span><span style="display:flex;"><span>send <span style="color:#66d9ef">host</span>-name <span style="color:#f92672">=</span> <span style="color:#a6e22e">gethostname</span>();
</span></span><span style="display:flex;"><span>request <span style="color:#66d9ef">subnet</span>-mask, broadcast-address, time-offset, routers,
</span></span><span style="display:flex;"><span> domain-name, domain-name-servers, domain-search, <span style="color:#66d9ef">host</span>-name,
</span></span><span style="display:flex;"><span> dhcp6.name-servers, dhcp6.domain-search, dhcp6.fqdn, dhcp6.sntp-servers,
</span></span><span style="display:flex;"><span> netbios-name-servers, netbios-scope, interface-mtu,
</span></span><span style="display:flex;"><span> rfc3442-classless-static-routes, ntp-servers;
</span></span></code></pre></div><p>Now we can write two hooks. The first is an enter hook, which we can use to write the <code>forward.conf</code> file out.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>touch /etc/dhclient-enter-hooks
</span></span><span style="display:flex;"><span>chmod +x /etc/dhclient-enter-hooks
</span></span></code></pre></div><p>The content is a single statement to write the <code>new_domain_name_servers</code> value into a <code>forward-zone</code> for unbound:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>
</span></span><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt;-EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">forward-zone:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> name: &#34;.&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> forward-addr: ${new_domain_name_servers}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">)</span> | sudo tee /etc/unbound/forward.conf
</span></span></code></pre></div><p>The second hook is an exit ook, which runs after dhclient has finished writing out all the files it controls (such as <code>/etc/resolv.conf</code>):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>touch /etc/dhclient-exit-hooks
</span></span><span style="display:flex;"><span>chmod +x /etc/dhclient-exit-hooks
</span></span></code></pre></div><p>The content is a single <code>sed</code> statement to replace the address of <code>nameserver</code> directives written to the <code>/etc/resolv.conf</code> with the unbound address:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>sudo sed -i <span style="color:#e6db74">&#39;s/nameserver.*/nameserver 127.0.0.1/g&#39;</span> /etc/resolv.conf
</span></span></code></pre></div><p>It&rsquo;s worth noting; we could put the content of the <code>enter</code> hook into the <code>exit</code> hook if you would rather.</p>
<p>Finally, we can delete our current <code>resolv.conf</code> and restart the networking service:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>rm /etc/resolv.conf <span style="color:#75715e"># hack due to it dhclient making an invalid `chown` call.</span>
</span></span><span style="display:flex;"><span>rc-service networking restart
</span></span></code></pre></div><h2 id="testing">Testing</h2>
<p>We can now test that we can resolve the three kinds of address we care about:</p>
<ul>
<li><code>dig consul.service.consul</code> - should return the <code>eth0</code> ip of the machine</li>
<li><code>dig alpinetest.karhu.xyz</code> - should be resolved by libvirt&rsquo;s dnsmasq instance</li>
<li><code>dig example.com</code> - should be resolved by an upstream DNS server</li>
</ul>
<h2 id="conculsion">Conculsion</h2>
<p>This was an interesting and somewhat annoying problem to solve, but it means I have a more robust setup in my virtual machines now. It&rsquo;s interesting to note that if the DNS server from DHCP were not a local instance, the network latency added would make all the system function properly most of the time, as the local instance would answer before the remote instance could.</p>
]]></content:encoded></item><item><title>Libvirt Hostname Resolution</title><link>https://andydote.co.uk/2019/12/22/libvirt-hostname-resolution/</link><pubDate>Sun, 22 Dec 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/12/22/libvirt-hostname-resolution/</guid><description>I use Vagrant when testing new machines and experimenting locally with clusters, and since moving (mostly) to Linux, I have been using the LibVirt Plugin to create the virtual machines. Not only is it significantly faster than Hyper-V was on windows, but it also means I don&amp;rsquo;t need to use Oracle products, so it&amp;rsquo;s win-win really.
The only configuration challenge I have had with it is setting up VM hostname resolution, and as I forget how to do it each time, I figured I should write about it.</description><content:encoded><![CDATA[<p>I use <a href="http://vagrantup.com/">Vagrant</a> when testing new machines and experimenting locally with clusters, and since moving (mostly) to Linux, I have been using the <a href="https://github.com/vagrant-libvirt/vagrant-libvirt">LibVirt Plugin</a> to create the virtual machines. Not only is it significantly faster than Hyper-V was on windows, but it also means I don&rsquo;t need to use Oracle products, so it&rsquo;s win-win really.</p>
<p>The only configuration challenge I have had with it is setting up VM hostname resolution, and as I forget how to do it each time, I figured I should write about it.</p>
<h2 id="setup">Setup</h2>
<p>First I install the plugin so Vagrant can talk to Libvirt.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vagrant plugin install vagrant-libvirt
</span></span></code></pre></div><p>I also created a single <code>vagrantfile</code> with two virtual machines defined in it, so that I can check that the machines can resolve each other, as well as the host being able to resolve the guests.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">Vagrant</span><span style="color:#f92672">.</span>configure(<span style="color:#e6db74">&#34;2&#34;</span>) <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>config<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span> config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>box <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;elastic/ubuntu-16.04-x86_64&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;one&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>n1<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span> n1<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>hostname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;one&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;two&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>n1<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span> n1<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>hostname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;two&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>Once running <code>vagrant up</code> has finished (either with <code>--provider libvirt</code> or setting <code> VAGRANT_DEFAULT_PROVIDER=libvirt</code>), connect to one of the machines, and try to ping the other:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>andy@karhu$ vagrant ssh one
</span></span><span style="display:flex;"><span>vagrant@one$ ping two
</span></span><span style="display:flex;"><span>ping: unknown host two
</span></span><span style="display:flex;"><span>vagrant@one$ exit
</span></span></code></pre></div><p>Now that we can see they can&rsquo;t resolve each other let&rsquo;s move on to fixing it.</p>
<h2 id="custom-domain">Custom Domain</h2>
<p>The solution is to configure the libvirt network to have a domain name, and then to set the host machine to send requests for that domain to the virtual network.</p>
<p>First, I picked a domain. It doesn&rsquo;t matter what it is, but I gather using <code>.local</code> will cause problems with other services, so instead, I picked <code>$HOSTNAME.xyz</code>, which is <code>karhu.xyz</code> in this case.</p>
<p>Vagrant-libvirt by default creates a network called <code>vagrant-libvirt</code>, so we can edit it to include the domain name configuration by running the following command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>virsh net-edit --network vagrant-libvirt
</span></span></code></pre></div><p>And adding the `<domain name='karhu.xyz' localOnly='yes' /> line to the xml which is displayed:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span>&lt;network ipv6=&#39;yes&#39;&gt;
</span></span><span style="display:flex;"><span> &lt;name&gt;vagrant-libvirt&lt;/name&gt;
</span></span><span style="display:flex;"><span> &lt;uuid&gt;d265a837-96fd-41fc-b114-d9e076462051&lt;/uuid&gt;
</span></span><span style="display:flex;"><span> &lt;forward mode=&#39;nat&#39;/&gt;
</span></span><span style="display:flex;"><span> &lt;bridge name=&#39;virbr1&#39; stp=&#39;on&#39; delay=&#39;0&#39;/&gt;
</span></span><span style="display:flex;"><span> &lt;mac address=&#39;52:54:00:a0:ae:fd&#39;/&gt;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ &lt;domain name=&#39;karhu.xyz&#39; localOnly=&#39;yes&#39;/&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span> &lt;ip address=&#39;192.168.121.1&#39; netmask=&#39;255.255.255.0&#39;&gt;
</span></span><span style="display:flex;"><span> &lt;dhcp&gt;
</span></span><span style="display:flex;"><span> &lt;range start=&#39;192.168.121.1&#39; end=&#39;192.168.121.254&#39;/&gt;
</span></span><span style="display:flex;"><span> &lt;/dhcp&gt;
</span></span><span style="display:flex;"><span> &lt;/ip&gt;
</span></span><span style="display:flex;"><span>&lt;/network&gt;
</span></span></code></pre></div><p>To make the changes take effect, we need to destroy and re-create the network, so first I destroy the vagrant machines, then destroy and restart the network:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vagrant destroy -f
</span></span><span style="display:flex;"><span>virsh net-destroy --network vagrant-libvirt
</span></span><span style="display:flex;"><span>virsh net-start --network vagrant-libvirt
</span></span></code></pre></div><p>Finally, we can re-create the machines, and log in to one to check that they can resolve each other:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>andy@karhu$ vagrant up
</span></span><span style="display:flex;"><span>andy@karhu$ vagrant ssh one
</span></span><span style="display:flex;"><span>vagrant@one$ ping two
</span></span><span style="display:flex;"><span>PING two.karhu.xyz <span style="color:#f92672">(</span>192.168.121.243<span style="color:#f92672">)</span> 56<span style="color:#f92672">(</span>84<span style="color:#f92672">)</span> bytes of data.
</span></span><span style="display:flex;"><span>vagrant@one$ exit
</span></span></code></pre></div><p>You can also check that the host can resolve the machine names when querying the virtual network&rsquo;s DNS server:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>andy@karhu$ dig @192.168.121.1 +short one
</span></span><span style="display:flex;"><span>&gt; 192.168.121.50
</span></span></code></pre></div><h2 id="host-dns-forwarding">Host DNS Forwarding</h2>
<p>The host cant talk to the machines by name still, so we need to tweak the host&rsquo;s DNS, which means fighting with SystemD. Luckily, we only need to forward requests to a DNS server running on port <code>53</code> - if it was on another port then replacing systemd-resolved like <a href="/2019/09/24/consul-ubuntu-dns-revisited/">my post on Consul DNS forwarding</a> would be necessary.</p>
<p>Edit <code>/etc/systemd/resolved.conf</code> on the host, to add two lines which instruct it to send DNS requests for the domain picked earlier to the DNS server run by libvirt (dnsmasq):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span>[Resolve]
</span></span><span style="display:flex;"><span><span style="color:#f92672">-#DNS=
</span></span></span><span style="display:flex;"><span><span style="color:#f92672"></span><span style="color:#a6e22e">+DNS=192.168.121.1
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>#FallbackDNS=
</span></span><span style="display:flex;"><span><span style="color:#f92672">-#Domains=
</span></span></span><span style="display:flex;"><span><span style="color:#f92672"></span><span style="color:#a6e22e">+Domains=~karhu.xyz
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>#LLMNR=no
</span></span><span style="display:flex;"><span>#MulticastDNS=no
</span></span><span style="display:flex;"><span>#DNSSEC=no
</span></span><span style="display:flex;"><span>#DNSOverTLS=no
</span></span><span style="display:flex;"><span>#Cache=yes
</span></span><span style="display:flex;"><span>#DNSStubListener=yes
</span></span><span style="display:flex;"><span>#ReadEtcHosts=yes
</span></span></code></pre></div><p>Lastly, restart systemd-resolved for the changes to take effect:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>systemctl restart systemd-resolved
</span></span></code></pre></div><p>Now we can resolve the guest machines by hostname at the domain we picked earlier:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>andy@karhu$ ping one.karhu.xyz
</span></span><span style="display:flex;"><span>PING one.karhu.xyz <span style="color:#f92672">(</span>192.168.121.50<span style="color:#f92672">)</span> 56<span style="color:#f92672">(</span>84<span style="color:#f92672">)</span> bytes of data.
</span></span></code></pre></div><p>Done!</p>
]]></content:encoded></item><item><title>Nomad Good, Kubernetes Bad</title><link>https://andydote.co.uk/2019/11/21/nomad-good-kubernetes-bad/</link><pubDate>Thu, 21 Nov 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/11/21/nomad-good-kubernetes-bad/</guid><description>I will update this post as I learn more (both positive and negative), and is here to be linked to when people ask me why I don&amp;rsquo;t like Kubernetes, and why I would pick Nomad in most situations if I chose to use an orchestrator at all.
TLDR: I don&amp;rsquo;t like complexity, and Kubernetes has more complexity than benefits.
Operational Complexity Operating Nomad is very straight forward. There are very few moving parts, so the number of things which can go wrong is significantly reduced.</description><content:encoded><![CDATA[<p>I will update this post as I learn more (both positive and negative), and is here to be linked to when people ask me why I don&rsquo;t like Kubernetes, and why I would pick Nomad in most situations if I chose to use an orchestrator <em>at all</em>.</p>
<p>TLDR: I don&rsquo;t like complexity, and Kubernetes has more complexity than benefits.</p>
<h3 id="operational-complexity">Operational Complexity</h3>
<p>Operating Nomad is very straight forward.  There are very few moving parts, so the number of things which can go wrong is significantly reduced.  No external dependencies are required to run it, and there is only one binary to use.  You run 3-5 copies in Server mode to manage the cluster and as many as you want running in Client mode to do the actual work.  You can add Consul if you want service discovery, but it&rsquo;s optional.  More on that later.</p>
<p>Compare this to operating a Kubernetes cluster.  There are multiple Kubernetes orchestration projects, tools, and companies to get clusters up and running, which should be an indication of the level of complexity involved.  Once you have the cluster set up, you need to keep it running.  There are so many moving parts (Controller Manager, Scheduler, API Server, Etcd, Kubelets) that it quickly becomes a full-time job to keep the cluster up and running.  Use a cloud service to run Kubernetes, and if you must use your own infrastructure, pay someone else to manage it.  It&rsquo;s cheaper in the long run. Trust me.</p>
<h3 id="deployment">Deployment</h3>
<p>Nomad, being a single binary, is easy to deploy.  If you want to use <a href="https://www.terraform.io/">Terraform</a> to create a cluster, Hashicorp provides modules for both <a href="https://github.com/hashicorp/terraform-aws-nomad">AWS</a> and <a href="https://github.com/hashicorp/terraform-azurerm-nomad">Azure</a>.  Alternatively, you can do everything yourself, as it&rsquo;s just keeping one binary running on hosts, and a bit of network/DNS config to get them talking to each other.</p>
<p>By comparison, Kubernetes has a multitude of tools to help you deploy a cluster. Still, while it gives you a lot of flexibility in choice, you also have to hope that the tool continues to exist and that there is enough community/company/documentation about that specific tool to help you when something goes wrong.</p>
<h3 id="upgrading-the-cluster">Upgrading The Cluster</h3>
<p>Upgrading Nomad involves doing a rolling deployment of the Servers and Clients.  If you are using the Hashicorp Terraform module, you re-apply the module with the new AMI ID to use, and then delete nodes (gracefully!) from the cluster and let the AutoScaleGroup take care of bringing new nodes up.  If you need to revert to an older version of Nomad, you follow the same process.</p>
<p>When it comes to Kubernetes, please pay someone else to do it.  It&rsquo;s not a fun process.  The process will differ depending on which cluster management tool you are using, and you also need to think about updates to etcd and managing state in the process.  There is a <a href="https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/">nice long document</a> on how to upgrade etcd.</p>
<h3 id="debugging-a-cluster">Debugging a Cluster</h3>
<p>As mentioned earlier, Nomad has a small number of moving parts.  There are three ports involved (HTTP, RPC and Gossip), so as long as those ports are open and reachable, Nomad should be operable.  Then you need to keep the Nomad agents alive.  That&rsquo;s pretty much it.</p>
<p>Where to start for Kubernetes? As many <a href="https://github.com/hjacobs/kubernetes-failure-stories">Kubernetes Failure Stories</a> point out: it&rsquo;s always DNS. Or etcd. Or Istio. Or networking. Or Kubelets. Or all of these.</p>
<h3 id="local-development">Local Development</h3>
<p>To run Nomad locally, you use the same binary as the production clusters, but in dev mode: <code>nomad agent -dev</code>.  To get a local cluster, you can spin up some Vagrant boxes instead.  I use my <a href="https://github.com/pondidum/hashibox">Hashibox</a> Vagrant box to do this when I do conference talks and don&rsquo;t trust the wifi to work.</p>
<p>To run Kubernetes locally to test things, you need to install/deploy MiniKube, K3S, etc.  The downside to this approach is that the environment is significantly different to your real Kubernetes cluster, and you can end up where a deployment works in one, but not the other, which makes debugging issues much harder.</p>
<h3 id="features--choice">Features &amp; Choice</h3>
<p>Nomad is relatively light on built-in features, which allows you the choice of what features to add, and what implementations of the features to use.  For example, it is pretty popular to use Consul for service discovery, but if you would rather use <a href="https://github.com/Netflix/eureka">Eureka</a>, or Zookeeper, or even etcd, that is fine, but you lose out on the seamless integration with Nomad that other Hashicorp tools have.  Nomad also supports <a href="https://www.nomadproject.io/docs/internals/plugins/index.html">Plugins</a> if you want to add support for your favourite tool.</p>
<p>By comparison, Kubernetes does everything, but like the phrase &ldquo;Jack of all trades, master of none&rdquo;, often you will have to supplement the inbuilt features.  The downside to this is that you can&rsquo;t switch off Kubernetes features you are not using, or don&rsquo;t want.  So if you add Vault for secret management, the Kubernetes Secrets are still available, and you have to be careful that people don&rsquo;t use them accidentally.  The same goes for all other features, such as Load Balancing, Feature Toggles, Service Discovery, DNS, etc.</p>
<h3 id="secret-management">Secret Management</h3>
<p>Nomad doesn&rsquo;t provide a Secret Management solution out of the box, but it does have seamless Vault integration, and you are also free to use any other Secrets As A Service tool you like.  If you do choose Vault, you can either use it directly from your tasks or use Nomad&rsquo;s integration to provide the secrets to your application.  It can even send a signal (e.g. <code>SIGINT</code> etc.) to your process when the secrets need re-reading.</p>
<p>Kubernetes, on the other hand, provides &ldquo;Secrets&rdquo;.  I put the word &ldquo;secrets&rdquo; in quotes because they are not secrets at all. The values are stored encoded in base64 in etcd, so anyone who has access to the etcd cluster has access to <em>all</em> the secrets.  The <a href="https://kubernetes.io/docs/concepts/configuration/secret/#risks">official documentation</a> suggests making sure only administrators have access to the etcd cluster to solve this.  Oh, and if you can deploy a container to the same namespace as a secret, you can reveal it by writing it to stdout.</p>
<blockquote>
<p>Kubernetes secrets are not secret, just &ldquo;slightly obscured.&rdquo;</p>
</blockquote>
<p>If you want real Secrets, you will almost certainly use Vault.  You can either run it inside or outside of Kubernetes, and either use it directly from containers via it&rsquo;s HTTPS API or use it to populate Kubernetes Secrets.  I&rsquo;d avoid populating Kubernetes Secrets if I were you.</p>
<h3 id="support">Support</h3>
<p>If Nomad breaks, you can either use community support or if you are using the Enterprise version, you have Hashicorp&rsquo;s support.</p>
<p>When Kubernetes breaks, you can either use community support or find and buy support from a Kubernetes management company.</p>
<p>The main difference here is &ldquo;when Kubernetes breaks&rdquo; vs &ldquo;if Nomad breaks&rdquo;.  The level of complexity in Kubernetes makes it far more likely to break, and that much harder to debug.</p>
]]></content:encoded></item><item><title>Creating a Vault instance with a TLS Consul Cluster</title><link>https://andydote.co.uk/2019/10/06/vault-consul-bootstrap/</link><pubDate>Sun, 06 Oct 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/10/06/vault-consul-bootstrap/</guid><description>So we want to set up a Vault instance, and have it&amp;rsquo;s storage be a TLS based Consul cluster. The problem is that the Consul cluster needs Vault to create the certificates for TLS, which is quite the catch-22. Luckily for us, quite easy to solve:
Start a temporary Vault instance as an intermediate ca Launch Consul cluster, using Vault to generate certificates Destroy temporary Vault instance Start a permanent Vault instance, with Consul as the store Reprovision the Consul cluster with certificates from the new Vault instance There is a repository on Github with all the scripts used, and a few more details on some options.</description><content:encoded><![CDATA[<p>So we want to set up a <a href="https://www.vaultproject.io/">Vault</a> instance, and have it&rsquo;s storage be a TLS based <a href="https://www.consul.io/">Consul</a> cluster.  The problem is that the Consul cluster needs Vault to create the certificates for TLS, which is quite the catch-22.  Luckily for us, quite easy to solve:</p>
<ol>
<li>Start a temporary Vault instance as an intermediate ca</li>
<li>Launch Consul cluster, using Vault to generate certificates</li>
<li>Destroy temporary Vault instance</li>
<li>Start a permanent Vault instance, with Consul as the store</li>
<li>Reprovision the Consul cluster with certificates from the new Vault instance</li>
</ol>
<p><img loading="lazy" src="consul-vault-bootstrap.png" alt="Sequence diagram of the previous numbered list"  />
</p>
<p>There is a <a href="https://github.com/Pondidum/vault-consul-bootstrap-demo">repository on Github with all the scripts</a> used, and a few more details on some options.</p>
<h2 id="assumptions">Assumptions:</h2>
<p>The Host machine needs the following software available in your <code>PATH</code>:</p>
<ul>
<li><a href="https://www.vagrantup.com/">Vagrant</a></li>
<li><a href="https://www.consul.io/">Consul</a></li>
<li><a href="https://www.vaultproject.io/">Vault</a></li>
</ul>
<p>You have a TLS Certificate you can use to create an intermediate CA with.  See this blog post for <a href="/2019/08/25/vault-development-ca/">How to create a local CA</a></p>
<h2 id="running">Running</h2>
<p>The <code>run.sh</code> script will do all of this for you, but an explanation of the steps is below:</p>
<ol>
<li>
<p>Start a Temporary Vault instance</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">storage &#34;inmem&#34; {}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">listener &#34;tcp&#34; {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  address = &#34;0.0.0.0:8200&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  tls_disable = 1
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">}&#39;</span> &gt; <span style="color:#e6db74">&#34;vault/temp_vault.hcl&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault server -config<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;vault/temp_vault.hcl&#34;</span> &amp;
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;</span>$!<span style="color:#e6db74">&#34;</span> &gt; vault.pid
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>export VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>./configure_vault.sh | tail -n 1<span style="color:#66d9ef">)</span>
</span></span></code></pre></div></li>
<li>
<p>Generate a Vault token for the Consul machines to use to authenticate with Vault</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export CONSUL_VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>vault write -field<span style="color:#f92672">=</span>token -force auth/token/create<span style="color:#66d9ef">)</span>
</span></span></code></pre></div></li>
<li>
<p>Launch 3 Consul nodes (uses the <code>CONSUL_VAULT_TOKEN</code> variable)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vagrant up
</span></span></code></pre></div><p>The <code>vagrantfile</code> just declares 3 identical machines:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">Vagrant</span><span style="color:#f92672">.</span>configure(<span style="color:#ae81ff">2</span>) <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>config<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>box <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;pondidum/hashibox&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provision <span style="color:#e6db74">&#34;consul&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">type</span>: <span style="color:#e6db74">&#34;shell&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">path</span>: <span style="color:#e6db74">&#34;./provision.sh&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">env</span>: {
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;VAULT_TOKEN&#34;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">ENV</span><span style="color:#f92672">[</span><span style="color:#e6db74">&#34;CONSUL_VAULT_TOKEN&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;c1&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>c1<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>    c1<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>hostname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;consul1&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;c2&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>c2<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>    c2<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>hostname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;consul2&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;c3&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>c3<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>    c3<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>hostname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;consul3&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>The provisioning script just reads a certificate from Vault, and writes out pretty much the same configuration as in the last post on <a href="/2019/09/14/consul-tls-cluster">creating a TLS enabled Consul Cluster</a>, but you can view it in the <a href="https://github.com/Pondidum/vault-consul-bootstrap-demo">repository</a> for this demo too.</p>
</li>
<li>
<p>Create a local Consul server to communicate with the cluster:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>./local_consul.sh
</span></span></code></pre></div><p>This is done so that the Vault instance can always communicate with the Consul cluster, no matter which Consul node we are reprovisioning later.  In a production environment, you would have this Consul server running on each machine that Vault is running on.</p>
</li>
<li>
<p>Stop the temporary Vault instance now that all nodes have a certificate</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>kill <span style="color:#66d9ef">$(</span>cat vault.pid<span style="color:#66d9ef">)</span>
</span></span></code></pre></div></li>
<li>
<p>Start the persistent Vault instance, using the local Consul agent</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">storage &#34;consul&#34; {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  address = &#34;localhost:8501&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  scheme = &#34;https&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">listener &#34;tcp&#34; {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  address = &#34;0.0.0.0:8200&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  tls_disable = 1
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">}&#39;</span> &gt; <span style="color:#e6db74">&#34;</span>$config_dir<span style="color:#e6db74">/persistent_vault.hcl&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault server -config<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$config_dir<span style="color:#e6db74">/persistent_vault.hcl&#34;</span> &gt; /dev/null &amp;
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;</span>$!<span style="color:#e6db74">&#34;</span> &gt; vault.pid
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>export VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>./configure_vault.sh | tail -n 1<span style="color:#66d9ef">)</span>
</span></span></code></pre></div></li>
<li>
<p>Generate a new Vault token for the Consul machines to use to authenticate with Vault (same as step 2)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export CONSUL_VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>vault write -field<span style="color:#f92672">=</span>token -force auth/token/create<span style="color:#66d9ef">)</span>
</span></span></code></pre></div></li>
<li>
<p>Reprovision the Consul nodes with new certificates</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vagrant provision c1 --provision-with consul
</span></span><span style="display:flex;"><span>vagrant provision c2 --provision-with consul
</span></span><span style="display:flex;"><span>vagrant provision c3 --provision-with consul
</span></span></code></pre></div></li>
<li>
<p>Profit</p>
<p>To clean up the host&rsquo;s copy of Vault and Consul, you can run this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>kill <span style="color:#66d9ef">$(</span>cat vault.pid<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>kill <span style="color:#66d9ef">$(</span>cat consul.pid<span style="color:#66d9ef">)</span>
</span></span></code></pre></div></li>
</ol>
<h2 id="summary--further-actions">Summary &amp; Further Actions</h2>
<p>Luckily, this is the kind of thing that should only need doing once (or once per isolated environment).  When running in a real environment, you will also want to set up:</p>
<ul>
<li>ACL in Consul which locks down the KV storage Vault uses to only be visible/writeable by Vault</li>
<li>Provisioning the <code>VAULT_TOKEN</code> to the machines in a secure fashion</li>
<li>Periodic refresh of the Certificates uses in the Consul cluster</li>
</ul>
]]></content:encoded></item><item><title>Consul DNS Fowarding in Ubuntu, revisited</title><link>https://andydote.co.uk/2019/09/24/consul-ubuntu-dns-revisited/</link><pubDate>Tue, 24 Sep 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/09/24/consul-ubuntu-dns-revisited/</guid><description>I was recently using my Hashibox for a test, and I noticed the DNS resolution didn&amp;rsquo;t seem to work. This was a bit worrying, as I have written about how to do DNS resolution with Consul forwarding in Ubuntu, and apparently something is wrong with how I do it. Interestingly, the Alpine version works fine, so it appears there is something not quite working with how I am configuring Systemd-resolved.</description><content:encoded><![CDATA[<p>I was recently using my <a href="https://github.com/pondidum/hashibox">Hashibox</a> for a test, and I noticed the DNS resolution didn&rsquo;t seem to work.  This was a bit worrying, as I have written about how to do <a href="/2019/05/29/consul-dns-forwarding/">DNS resolution with Consul forwarding in Ubuntu</a>, and apparently something is wrong with how I do it.  Interestingly, the <a href="/2019/05/31/consul-dns-forwarding-alpine/">Alpine version</a> works fine, so it appears there is something not quite working with how I am configuring Systemd-resolved.</p>
<p>So this post is how I figured out what was wrong, and how to do DNS resolution with Consul forwarding on Ubuntu properly!</p>
<h2 id="the-problem">The Problem</h2>
<p>If Consul is running on the host, I can only resolve <code>.consul</code> domains, and if Consul is not running, I can resolve anything else.  Clearly I have configured something wrong!</p>
<p>To summarise, I want to be able to resolve 3 kinds of address:</p>
<ul>
<li><code>*.consul</code> addresses should be handled by the local Consul instance</li>
<li><code>$HOSTNAME.mshome.net</code> should be handled by the Hyper-V DNS server (running on the Host machine)</li>
<li><code>reddit.com</code> public DNS should be resolved properly</li>
</ul>
<h2 id="discovery">Discovery</h2>
<p>To make sure that hostname resolution even works by default, I create a blank Ubuntu box in Hyper-V, using <a href="https://www.vagrantup.com/">Vagrant</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">Vagrant</span><span style="color:#f92672">.</span>configure(<span style="color:#ae81ff">2</span>) <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>config<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>box <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;bento/ubuntu-16.04&#34;</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>hostname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;test&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>I set the hostname so that I can test that dns resolution works from the host machine to the guest machines too.  I next bring up the machine, SSH into it, and try to <code>dig</code> my hostmachine&rsquo;s DNS name (<code>spectre.mshome.net</code>):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>&gt; vagrant up
</span></span><span style="display:flex;"><span>&gt; vagrant ssh
</span></span><span style="display:flex;"><span>&gt; dig spectre.mshome.net
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>; &lt;&lt;&gt;&gt; DiG 9.10.3-P4-Ubuntu &lt;&lt;&gt;&gt; spectre.mshome.net
</span></span><span style="display:flex;"><span>;; global options: +cmd
</span></span><span style="display:flex;"><span>;; Got answer:
</span></span><span style="display:flex;"><span>;; -&gt;&gt;HEADER<span style="color:#e6db74">&lt;&lt;- opco</span>de: QUERY, status: NOERROR, id: <span style="color:#ae81ff">12333</span>
</span></span><span style="display:flex;"><span>;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>;; QUESTION SECTION:
</span></span><span style="display:flex;"><span>;spectre.mshome.net.            IN      A
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>;; ANSWER SECTION:
</span></span><span style="display:flex;"><span>Spectre.mshome.net.     <span style="color:#ae81ff">0</span>       IN      A       192.168.181.161
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>;; Query time: <span style="color:#ae81ff">0</span> msec
</span></span><span style="display:flex;"><span>;; SERVER: 192.168.181.161#53<span style="color:#f92672">(</span>192.168.181.161<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>;; WHEN: Mon Sep <span style="color:#ae81ff">23</span> 21:57:26 UTC <span style="color:#ae81ff">2019</span>
</span></span><span style="display:flex;"><span>;; MSG SIZE  rcvd: <span style="color:#ae81ff">70</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&gt; exit
</span></span><span style="display:flex;"><span>&gt; vagrant destroy -f
</span></span></code></pre></div><p>As you can see, the host machine&rsquo;s DNS server responds with the right address.  Now that I know that this should work, we can tweak the <code>Vagrantfile</code> to start an instance of my Hashibox:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">Vagrant</span><span style="color:#f92672">.</span>configure(<span style="color:#ae81ff">2</span>) <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>config<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>box <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;pondidum/hashibox&#34;</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>hostname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;test&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>When I run the same command sin this box, I get a slighty different response:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>; &lt;&lt;&gt;&gt; DiG 9.10.3-P4-Ubuntu &lt;&lt;&gt;&gt; spectre.mshome.net
</span></span><span style="display:flex;"><span>;; global options: +cmd
</span></span><span style="display:flex;"><span>;; Got answer:
</span></span><span style="display:flex;"><span>;; -&gt;&gt;HEADER<span style="color:#e6db74">&lt;&lt;- opco</span>de: QUERY, status: NXDOMAIN, id: <span style="color:#ae81ff">57216</span>
</span></span><span style="display:flex;"><span>;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>;; WARNING: recursion requested but not available
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>;; OPT PSEUDOSECTION:
</span></span><span style="display:flex;"><span>; EDNS: version: 0, flags:; udp: <span style="color:#ae81ff">4096</span>
</span></span><span style="display:flex;"><span>;; QUESTION SECTION:
</span></span><span style="display:flex;"><span>;spectre.mshome.net.            IN      A
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>;; AUTHORITY SECTION:
</span></span><span style="display:flex;"><span>consul.                 <span style="color:#ae81ff">0</span>       IN      SOA     ns.consul. hostmaster.consul. <span style="color:#ae81ff">1569276784</span> <span style="color:#ae81ff">3600</span> <span style="color:#ae81ff">600</span> <span style="color:#ae81ff">86400</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>;; Query time: <span style="color:#ae81ff">1</span> msec
</span></span><span style="display:flex;"><span>;; SERVER: 127.0.0.1#53<span style="color:#f92672">(</span>127.0.0.1<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>;; WHEN: Mon Sep <span style="color:#ae81ff">23</span> 22:13:04 UTC <span style="color:#ae81ff">2019</span>
</span></span><span style="display:flex;"><span>;; MSG SIZE  rcvd: <span style="color:#ae81ff">103</span>
</span></span></code></pre></div><p>As intended, the DNS server on localhost responded&hellip;but it looks like Consul answered, not the inbuilt dns server (<code>systemd-resolved</code>), as I intended.</p>
<p>The reason for this is that I am running Consul&rsquo;s DNS endpoint on <code>8600</code>, and Systemd-Resolved cannot send requests to anything other than port <code>53</code>, so I use <code>iptables</code> to redirect the traffic from port <code>53</code> to <code>8600</code>, which means any local use of DNS will always be sent to Consul.</p>
<p>The reason it works when Consul is not running is that we have both <code>127.0.0.1</code> specified as a nameserver, and a fallback set to be the <code>eth0</code>&rsquo;s Gateway, so when Consul doesn&rsquo;t respond, the request hits the default DNS instead.</p>
<h2 id="the-solution-dnsmasq">The Solution: Dnsmasq.</h2>
<p>Basically, stop using <code>systemd-resolved</code> and use something that has a more flexible configuration.  Enter Dnsmasq.</p>
<p>Starting from the blank Ubuntu box, I install dnsmasq, and disable systemd-resolved.  Doing this might prevent any DNS resolutio working for a while&hellip;</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt-get install -yq dnsmasq
</span></span><span style="display:flex;"><span>sudo systemctl disable systemd-resolved.service
</span></span></code></pre></div><p>If you would rather not disable <code>systemd-resolved</code> entirely, you can use these two lines instead to just switch off the local DNS stub:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;DNSStubListener=no&#34;</span> | sudo tee --append /etc/systemd/resolved.conf
</span></span><span style="display:flex;"><span>sudo systemctl restart systemd-resolved
</span></span></code></pre></div><p>Next I update <code>/etc/resolv.conf</code> to not be managed by Systemd, and point to where dnsmasq will be running:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo rm /etc/resolv.conf
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;nameserver 127.0.0.1&#34;</span> | sudo tee /etc/resolv.conf
</span></span></code></pre></div><p>The reason for deleting the file is that it was symlinked to the Systemd-Resolved managed file, so that link needed to be broken first to prevent Systemd interfering.</p>
<p>Lastly a minimal configuration for dnsmasq:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">port=53
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">resolv-file=/var/run/dnsmasq/resolv.conf
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">bind-interfaces
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">listen-address=127.0.0.1
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">server=/consul/127.0.0.1#8600
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">&#39;</span> | sudo tee /etc/dnsmasq.d/default
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo systemctl restart dnsmasq
</span></span></code></pre></div><p>This config does a few things, the two most important lines are:</p>
<ul>
<li>
<p><code>resolv-file=/var/run/dnsmasq/resolv.conf</code> which is pointing to the default <code>resolv.conf</code> written by dnsmasq.  This file contains the default nameserver supplied by the default network connection, and I want to use this as a fallback for anything dnsmasq cannot resolve directly (which will be everything, except <code>.consul</code>).  In my case, the content of this file is just <code>nameserver 192.168.181.161</code>.</p>
</li>
<li>
<p><code>server=/consul/127.0.0.1#8600</code> specifies that any address ending in <code>.consul</code> should be forwarded to Consul, running at <code>127.0.0.1</code> on port <code>8600</code>.  No more <code>iptables</code> rules!</p>
</li>
</ul>
<h2 id="testing">Testing</h2>
<p>Now that I have a (probably) working DNS system, let&rsquo;s look at testing it properly this time.  There are 3 kinds of address I want to test:</p>
<ul>
<li>Consul resolution, e.g. <code>consul.service.consul</code> should return the current Consul instance address.</li>
<li>Hostname resolution, e.g. <code>spectre.mshome.net</code> should resolve to the machine hosting the VM.</li>
<li>Public resolution, e.g. <code>reddit.com</code> should resolve to&hellip;reddit.</li>
</ul>
<p>I also want to test that the latter two cases work when Consul is <strong>not</strong> running too.</p>
<p>So let&rsquo;s write a simple script to make sure these all work.  This way I can reuse the same script on other machines, and also with other VM providers to check DNS works as it should.  The entire script is here:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>local_domain<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>1<span style="color:#66d9ef">:-</span>mshome.net<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>host_machine<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>2<span style="color:#66d9ef">:-</span>spectre<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>consul agent -dev -client 0.0.0.0 -bind <span style="color:#e6db74">&#39;{{ GetInterfaceIP &#34;eth0&#34; }}&#39;</span> &gt; /dev/null &amp;
</span></span><span style="display:flex;"><span>sleep <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>consul_ip<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>dig consul.service.consul +short<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>self_ip<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>dig $HOSTNAME.$local_domain +short | tail -n 1<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>host_ip<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>dig $host_machine.$local_domain +short | tail -n 1<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>reddit_ip<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>dig reddit.com +short | tail -n 1<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>kill %1
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$consul_ip<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Didn&#39;t get consul ip&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span> <span style="color:#f92672">&amp;&amp;</span> exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$self_ip<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Didn&#39;t get self ip&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span> <span style="color:#f92672">&amp;&amp;</span> exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$host_ip<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Didn&#39;t get host ip&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span> <span style="color:#f92672">&amp;&amp;</span> exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$reddit_ip<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Didn&#39;t get reddit ip&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span> <span style="color:#f92672">&amp;&amp;</span> exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;==&gt; Consul Running: Success!&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>consul_ip<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>dig consul.service.consul +short | tail -n 1<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>self_ip<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>dig $HOSTNAME.$local_domain +short | tail -n 1<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>host_ip<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>dig $host_machine.$local_domain +short | tail -n 1<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>reddit_ip<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>dig reddit.com +short | tail -n 1<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[[</span> <span style="color:#e6db74">&#34;</span>$consul_ip<span style="color:#e6db74">&#34;</span> !<span style="color:#f92672">=</span> *<span style="color:#e6db74">&#34;;; connection timed out;&#34;</span>* <span style="color:#f92672">]]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Got a consul ip (</span>$consul_ip<span style="color:#e6db74">)&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span> <span style="color:#f92672">&amp;&amp;</span> exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$self_ip<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Didn&#39;t get self ip&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span> <span style="color:#f92672">&amp;&amp;</span> exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$host_ip<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Didn&#39;t get host ip&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span> <span style="color:#f92672">&amp;&amp;</span> exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$reddit_ip<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Didn&#39;t get reddit ip&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span> <span style="color:#f92672">&amp;&amp;</span> exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;==&gt; Consul Stopped: Success!&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>exit <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><p>What this does is:</p>
<ol>
<li>Read two command line arguments, or use defaults if not specified</li>
<li>Start Consul as a background job</li>
<li>Query 4 domains, storing the results</li>
<li>Stop Consul (<code>kill %1</code>)</li>
<li>Check an IP address came back for each domain</li>
<li>Query the same 4 domains, storing the results</li>
<li>Check that a timeout was received for <code>consul.service.consul</code></li>
<li>Check an IP address came back for the other domains</li>
</ol>
<p>To further prove that dnsmasq is forwarding requests correctly, I can include two more lines to <code>/etc/dnsmasq.d/default</code> to enable logging, and restart dnsmasq</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;log-queries&#34;</span> | sudo tee /etc/dnsmasq.d/default
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;log-facility=/var/log/dnsmasq.log&#34;</span> | sudo tee /etc/dnsmasq.d/default
</span></span><span style="display:flex;"><span>sudo systemctl restart dnsmasq
</span></span><span style="display:flex;"><span>dig consul.service.consul
</span></span></code></pre></div><p>Now I can view the log file and check that it received the DNS query and did the right thing.  In this case, it recieved the <code>consul.service.consul</code> query, and forwarded it to the local Consul instance:</p>
<pre tabindex="0"><code>Sep 24 06:30:50 dnsmasq[13635]: query[A] consul.service.consul from 127.0.0.1
Sep 24 06:30:50 dnsmasq[13635]: forwarded consul.service.consul to 127.0.0.1
Sep 24 06:30:50 dnsmasq[13635]: reply consul.service.consul is 192.168.181.172
</code></pre><p>I don&rsquo;t tend to keep DNS logging on in my Hashibox as the log files can grow very quickly.</p>
<h2 id="wrapping-up">Wrapping Up</h2>
<p>Now that I have proven my DNS resolution works (I think), I have rolled it back into my Hashibox, and can now use machine names for setting up clusters, rather than having to specify IP addresses initially.</p>
]]></content:encoded></item><item><title>Creating a TLS enabled Consul cluster</title><link>https://andydote.co.uk/2019/09/14/consul-tls-cluster/</link><pubDate>Sat, 14 Sep 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/09/14/consul-tls-cluster/</guid><description>This post is going to go through how to set up a Consul cluster to communicate over TLS. I will be using Vagrant to create three machines locally, which will form my cluster, and in the provisioning step will use Vault to generate the certificates needed.
How to securely communicate with Vault to get the TLS certificates is out of scope for this post.
Host Configuration Unless you already have Vault running somewhere on your network, or have another mechanism to generate TLS certificates for each machine, you&amp;rsquo;ll need to start and configure Vault on the Host machine.</description><content:encoded><![CDATA[<p>This post is going to go through how to set up a <a href="https://www.consul.io/">Consul</a> cluster to communicate over TLS.  I will be using <a href="https://www.vagrantup.com/">Vagrant</a> to create three machines locally, which will form my cluster, and in the provisioning step will use Vault to generate the certificates needed.</p>
<p>How to securely communicate with Vault to get the TLS certificates is out of scope for this post.</p>
<h2 id="host-configuration">Host Configuration</h2>
<p>Unless you already have Vault running somewhere on your network, or have another mechanism to generate TLS certificates for each machine, you&rsquo;ll need to start and configure Vault on the Host machine.  I am using my <a href="https://andydote.co.uk/2019/08/25/vault-development-ca/#creating-a-vault-intermediate-ca">Vault Dev Intermediate CA script from my previous post</a>.</p>
<p>To set this up, all I need to do is run this on the host machine, which starts Vault in a docker container, and configures it as an intermediate certificate authority:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>./run_int.sh
</span></span></code></pre></div><p>I also have DNS on my network setup for the <code>tecra.xyz</code> domain so will be using that to test with.</p>
<h2 id="consul-machine-configuration">Consul Machine Configuration</h2>
<p>The <code>Vagrantfile</code> is very minimal - I am using my <a href="https://app.vagrantup.com/pondidum/boxes/hashibox">Hashibox</a> (be aware the <code>libvirt</code> provider for this might not work, for some reason <code>vagrant package</code> with libvirt produces a non-bootable box).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">Vagrant</span><span style="color:#f92672">.</span>configure(<span style="color:#ae81ff">2</span>) <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>config<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>box <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;pondidum/hashibox&#34;</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provision <span style="color:#e6db74">&#34;consul&#34;</span>, <span style="color:#e6db74">type</span>: <span style="color:#e6db74">&#34;shell&#34;</span>, <span style="color:#e6db74">path</span>: <span style="color:#e6db74">&#34;./provision.sh&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;c1&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>c1<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>    c1<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>hostname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;consul1&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;c2&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>c2<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>    c2<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>hostname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;consul2&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;c3&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>c3<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>    c3<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>hostname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;consul3&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>The hashibox script already has all the tools we&rsquo;ll need installed already: Consul, Vault, and jq.</p>
<p>First up, we request a certificate from Vault to use for Consul - How you get this certificate in a secure manner in a production environment is up to you.  There is a catch-22 here for me, in that in a production environment I use Vault with Consul as it&rsquo;s backing store&hellip;but Consul needs Vault to start!  I&rsquo;ll go over how I get around this in a future post.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export VAULT_ADDR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://vault.tecra.xyz:8200&#34;</span>
</span></span><span style="display:flex;"><span>export VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;vault&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>response<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>vault write pki/issue/cert -format<span style="color:#f92672">=</span>json common_name<span style="color:#f92672">=</span>$HOSTNAME.tecra.xyz alt_names<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;server.dc1.consul&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>config_dir<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;/etc/consul.d&#34;</span>
</span></span></code></pre></div><p>The first thing to note is that we have specified an <code>alt_names</code> for the certificate - you <em>must</em> have a SAN of <code>server.$DC.$DOMAIN</code> so either <code>server.dc1.consul</code> or <code>server.euwest1.tecra.xyz</code>, and the <code>server</code> prefix is required!.</p>
<p>Next, we need to take all the certificates from the response and write them to the filesystem.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>mkdir -p <span style="color:#e6db74">&#34;</span>$config_dir<span style="color:#e6db74">/ca&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> <span style="color:#f92672">((</span> i<span style="color:#f92672">=</span>0; i&lt;<span style="color:#66d9ef">$(</span>echo <span style="color:#e6db74">&#34;</span>$response<span style="color:#e6db74">&#34;</span> | jq <span style="color:#e6db74">&#39;.data.ca_chain | length&#39;</span><span style="color:#66d9ef">)</span>; i++ <span style="color:#f92672">))</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>  cert<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>echo <span style="color:#e6db74">&#34;</span>$response<span style="color:#e6db74">&#34;</span> | jq -r <span style="color:#e6db74">&#34;.data.ca_chain[</span>$i<span style="color:#e6db74">]&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>  name<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>echo <span style="color:#e6db74">&#34;</span>$cert<span style="color:#e6db74">&#34;</span> | openssl x509 -noout -subject -nameopt multiline | sed -n <span style="color:#e6db74">&#39;s/ *commonName *= //p&#39;</span> | sed <span style="color:#e6db74">&#39;s/\s//g&#39;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;</span>$cert<span style="color:#e6db74">&#34;</span> &gt; <span style="color:#e6db74">&#34;</span>$config_dir<span style="color:#e6db74">/ca/</span>$name<span style="color:#e6db74">.pem&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;</span>$response<span style="color:#e6db74">&#34;</span> | jq -r .data.private_key &gt; $config_dir/consul.key
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;</span>$response<span style="color:#e6db74">&#34;</span> | jq -r .data.certificate &gt; $config_dir/consul.crt
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;</span>$response<span style="color:#e6db74">&#34;</span> | jq -r .data.issuing_ca &gt;&gt; $config_dir/consul.crt
</span></span></code></pre></div><p>The <code>for</code> loop iterates through all of the certificates returned in the <code>ca_chain</code> and writes them into a <code>ca</code> directory.  We use <code>openssl</code> to get the name of the certificate, so the files are named nicely!</p>
<p>Finally, it writes the <code>private_key</code> for the node&rsquo;s certificate to <code>consul.key</code>, and both the <code>certificate</code> and <code>issuing_ca</code> to  the <code>consul.crt</code> file.</p>
<p>Now for the <code>consul.json</code>.  To setup a secure cluster, first of all we need to add the certificate configuration, pointing to the files we wrote earlier:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span><span style="color:#e6db74">&#34;ca_path&#34;</span><span style="color:#960050;background-color:#1e0010">:</span> <span style="color:#e6db74">&#34;$config_dir/ca/&#34;</span><span style="color:#960050;background-color:#1e0010">,</span>
</span></span><span style="display:flex;"><span><span style="color:#e6db74">&#34;cert_file&#34;</span><span style="color:#960050;background-color:#1e0010">:</span> <span style="color:#e6db74">&#34;$config_dir/consul.crt&#34;</span><span style="color:#960050;background-color:#1e0010">,</span>
</span></span><span style="display:flex;"><span><span style="color:#e6db74">&#34;key_file&#34;</span><span style="color:#960050;background-color:#1e0010">:</span> <span style="color:#e6db74">&#34;$config_dir/consul.key&#34;</span><span style="color:#960050;background-color:#1e0010">,</span>
</span></span></code></pre></div><p>We will also disable the HTTP port, and enable the HTTPS port:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span><span style="color:#e6db74">&#34;ports&#34;</span><span style="color:#960050;background-color:#1e0010">:</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;http&#34;</span>: <span style="color:#ae81ff">-1</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;https&#34;</span>: <span style="color:#ae81ff">8501</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Finally, we need to add some security settings.  First is <code>encrypt</code>, which sets that the key that all Consul nodes will use to encrypt their communications.  It must match on all nodes.  The easiest way to generate this is just run <code>consul keygen</code> and use the value that produces.</p>
<ul>
<li>
<p><code>&quot;encrypt&quot;: &quot;oNMJiPZRlaP8RnQiQo9p8MMK5RSJ+dXA2u+GjFm1qx8=&quot;</code>:</p>
<p>The key the cluster will use to encrypt all it&rsquo;s traffic.  It must be the same on all nodes, and the easiest way to generate the value is to use the output of <code>consul keygen</code>.</p>
</li>
<li>
<p><code>&quot;verify_outgoing&quot;: true</code>:</p>
<p>All the traffic leaving this node will be encrypted with the TLS certificates.  However, the node will still accept non-TLS traffic.</p>
</li>
<li>
<p><code>&quot;verify_incoming_rpc&quot;: true</code>:</p>
<p>All the gossip traffic arriving at this node must be signed with an authority in the <code>ca_path</code>.</p>
</li>
<li>
<p><code>&quot;verify_incoming_https&quot;: false</code>:</p>
<p>We are going to use the Consul Web UI, so we want to allow traffic to hit the API without a client certificate.  If you are using the UI from a non-server node, you can set this to <code>true</code>.</p>
</li>
<li>
<p><code>&quot;verify_server_hostname&quot;: true</code>:</p>
<p>Set Consul to verify <strong>outgoing</strong> connections have a hostname in the format of <code>server.&lt;datacenter&gt;.&lt;domain&gt;</code>.  From the <a href="https://www.consul.io/docs/agent/options.html#verify_server_hostname">docs</a>: &ldquo;This setting is critical to prevent a compromised client from being restarted as a server and having all cluster state including all ACL tokens and Connect CA root keys replicated to it&rdquo;</p>
</li>
</ul>
<p>The complete config we will use is listed here:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>
</span></span><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt;-EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">{
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;bootstrap_expect&#34;: 3,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;client_addr&#34;: &#34;0.0.0.0&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;data_dir&#34;: &#34;/var/consul&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;leave_on_terminate&#34;: true,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;rejoin_after_leave&#34;: true,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;retry_join&#34;: [&#34;consul1&#34;, &#34;consul2&#34;, &#34;consul3&#34;],
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;server&#34;: true,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;ui&#34;: true,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;encrypt&#34;: &#34;oNMJiPZRlaP8RnQiQo9p8MMK5RSJ+dXA2u+GjFm1qx8=&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;verify_incoming_rpc&#34;: true,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;verify_incoming_https&#34;: false,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;verify_outgoing&#34;: true,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;verify_server_hostname&#34;: true,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;ca_path&#34;: &#34;$config_dir/ca/&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;cert_file&#34;: &#34;$config_dir/consul.crt&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;key_file&#34;: &#34;$config_dir/consul.key&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;ports&#34;: {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;http&#34;: -1,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;https&#34;: 8501
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    }
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">)</span> | sudo tee $config_dir/consul.json
</span></span></code></pre></div><p>Lastly, we&rsquo;ll make a systemd service unit to start consul:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>
</span></span><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt;-EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">[Unit]
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Description=consul agent
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Requires=network-online.target
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">After=network-online.target
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">[Service]
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Restart=on-failure
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">ExecStart=/usr/bin/consul agent -config-file=$config_dir/consul.json -bind &#39;{{ GetInterfaceIP &#34;eth0&#34; }}&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">ExecReload=/bin/kill -HUP $MAINPID
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">[Install]
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">WantedBy=multi-user.target
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">)</span> | sudo tee /etc/systemd/system/consul.service
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo systemctl daemon-reload
</span></span><span style="display:flex;"><span>sudo systemctl enable consul.service
</span></span><span style="display:flex;"><span>sudo systemctl start consul
</span></span></code></pre></div><p>As the machines we are starting also have docker networks (and potentially others), our startup line specifies to bind to the <code>eth0</code> network, using a Consul Template.</p>
<h2 id="running">Running</h2>
<p>First, we need to run our intermediate CA, then provision our three machines:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>./run_int.sh
</span></span><span style="display:flex;"><span>vagrant up
</span></span></code></pre></div><p>After a few moments, you should be able to <code>curl</code> the consul ui (<code>curl https://consul1.tecra.xyz:8501</code>) or open <code>https://consul1.tecra.xyz:8501</code> in your browser.</p>
<p>Note, however, the if your root CA is self-signed, like mine is, some browsers (such as FireFox) won&rsquo;t trust it, as they won&rsquo;t use your machine&rsquo;s Trusted Certificate Store, but their own in built store.  You can either accept the warning or add your root certificate to the browser&rsquo;s store.</p>
<h2 id="testing">Testing</h2>
<p>Now that we have our cluster seemingly running with TLS, what happens if we try to connect a Consul client <em>without</em> TLS to it?  On the host machine, I just run a single node, and tell it to connect to one of the cluster nodes:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>consul agent <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -join consul1.tecra.xyz <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -bind <span style="color:#e6db74">&#39;{{ GetInterfaceIP &#34;eth0&#34; }}&#39;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -data-dir /tmp/consul
</span></span></code></pre></div><p>The result of this is a refusal to connect, as the cluster has TLS configured, but this instance does not:</p>
<pre tabindex="0"><code>==&gt; Starting Consul agent...
==&gt; Log data will now stream in as it occurs:
==&gt; Joining cluster...
==&gt; 1 error occurred:
  * Failed to join 192.168.121.231: Remote state is encrypted and encryption is not configured
</code></pre><p>Success!</p>
<p>In the next post, I&rsquo;ll go through how we can set up a Vault cluster which stores its data in Consul, but also provision that same Consul cluster with certificates from the Vault instance!</p>
]]></content:encoded></item><item><title>Using Vault as a Development CA</title><link>https://andydote.co.uk/2019/08/25/vault-development-ca/</link><pubDate>Sun, 25 Aug 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/08/25/vault-development-ca/</guid><description>Often when developing or testing some code, I need (or want) to use SSL, and one of the easiest ways to do that is to use Vault. However, it gets pretty annoying having to generate a new CA for each project, and import the CA cert into windows (less painful in Linux, but still annoying), especially as I forget which cert is in use, and accidentally clean up the wrong ones.</description><content:encoded><![CDATA[<p>Often when developing or testing some code, I need (or want) to use SSL, and one of the easiest ways to do that is to use <a href="https://www.vaultproject.io/">Vault</a>.  However, it gets pretty annoying having to generate a new CA for each project, and import the CA cert into windows (less painful in Linux, but still annoying), especially as I forget which cert is in use, and accidentally clean up the wrong ones.</p>
<p>My solution has been to generate a single CA certificate and PrivateKey, import this into my Trusted Root Certificate Store, and then whenever I need a Vault instance, I just setup Vault to use the existing certificate and private key.  The documentation for how to do this seems somewhat lacking, so here&rsquo;s how I do it.</p>
<p>Things you&rsquo;ll need:</p>
<ul>
<li>Docker</li>
<li>Vault cli</li>
<li>JQ</li>
</ul>
<h2 id="generating-the-root-certificate">Generating the Root Certificate</h2>
<p>First we need to create a Certificate, which we will do using the Vault docker container, and our local Vault CLI.  We start the docker container in the background, and mark it for deletion when it stops (<code>--rm</code>):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>container<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>docker run -d --rm  --cap-add<span style="color:#f92672">=</span>IPC_LOCK -p 8200:8200 -e <span style="color:#e6db74">&#34;VAULT_DEV_ROOT_TOKEN_ID=vault&#34;</span> vault:latest<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>export VAULT_ADDR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://localhost:8200&#34;</span>
</span></span><span style="display:flex;"><span>export VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;vault&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>certs_dir<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;./ca&#34;</span>
</span></span><span style="display:flex;"><span>max_ttl<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;87600h&#34;</span> <span style="color:#75715e"># 10 years why not</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mkdir -p $certs_dir
</span></span><span style="display:flex;"><span>rm -rf $certs_dir/*.*
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault secrets enable pki
</span></span><span style="display:flex;"><span>vault secrets tune -max-lease-ttl<span style="color:#f92672">=</span>$max_ttl pki
</span></span></code></pre></div><p>Finally, we generate a certificate by writing to the <code>pki/root/generate/exported</code> path.  If the path ends with <code>exported</code> the Private Key is returned too.  If you specify <code>/internal</code> then the Private Key is stored internally to Vault, and never accessible.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>result<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>vault write -format <span style="color:#e6db74">&#34;json&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  pki/root/generate/exported <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  common_name<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Local Dev CA&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  alt_names<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;localhost,mshome.net&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  ttl<span style="color:#f92672">=</span>$max_ttl<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;</span>$result<span style="color:#e6db74">&#34;</span> &gt; $certs_dir/response.json
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;</span>$result<span style="color:#e6db74">&#34;</span> | jq -r .data.certificate &gt; $certs_dir/ca.crt
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;</span>$result<span style="color:#e6db74">&#34;</span> | jq -r .data.private_key &gt; $certs_dir/private.key
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker stop $container
</span></span></code></pre></div><p>We put the entire response into a <code>json</code> file just incase there is something interesting we want out of it later, and store the certificate and private key into the same directory too.  Note for the certificate&rsquo;s <code>alt_names</code> I have specified both <code>localhost</code> and <code>mshome.net</code>, which is the domain that Hyper-V machines use.</p>
<p>Lastly, we can now import the root CA into our machine/user&rsquo;s Trusted Root Certification Authorities store, meaning our later uses of this certificate will be trusted by our local machine.</p>
<h2 id="creating-a-vault-ca">Creating a Vault CA</h2>
<p>As before, we use a Docker container to run the Vault instance, except this time we import the existing CA certificate into the PKI backend.  The first half of the script (<code>run_ca.sh</code>) is pretty much the same as before, except we don&rsquo;t delete the contents of the <code>./ca</code> directory, and our certificate <code>max_ttl</code> is much lower:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker run -d --rm  --cap-add<span style="color:#f92672">=</span>IPC_LOCK -p 8200:8200 -e <span style="color:#e6db74">&#34;VAULT_DEV_ROOT_TOKEN_ID=vault&#34;</span> vault:latest
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>export VAULT_ADDR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://localhost:8200&#34;</span>
</span></span><span style="display:flex;"><span>export VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;vault&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>certs_dir<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;./ca&#34;</span>
</span></span><span style="display:flex;"><span>max_ttl<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;72h&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault secrets enable pki
</span></span><span style="display:flex;"><span>vault secrets tune -max-lease-ttl<span style="color:#f92672">=</span>$max_ttl pki
</span></span></code></pre></div><p>The last part is to read in the certificate and private key, bundle them together, and configure the <code>pki</code> backend to use them, and add a single role to use for issuing certificates:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>pem<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>cat $certs_dir/ca.crt $certs_dir/private.key<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault write pki/config/ca pem_bundle<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$pem<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault write pki/roles/cert <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  allowed_domains<span style="color:#f92672">=</span>localhost,mshome.net <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  allow_subdomains<span style="color:#f92672">=</span>true <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  max_ttl<span style="color:#f92672">=</span>$max_ttl
</span></span></code></pre></div><p>Also note how we don&rsquo;t stop the docker container either.  Wouldn&rsquo;t be much of a CA if it stopped the second it was configured&hellip;</p>
<h2 id="creating-a-vault-intermediate-ca">Creating a Vault Intermediate CA</h2>
<p>Sometimes, I want to test that a piece of software works when I have issued certificates from an Intermediate CA, rather than directly from the root.  We can configure Vault to do this too, with a modified script which this time we start two PKI secret backends, one to act as the root, and onc as the intermediate:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>set -e
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker run -d --rm  --cap-add<span style="color:#f92672">=</span>IPC_LOCK -p 8200:8200 -e <span style="color:#e6db74">&#34;VAULT_DEV_ROOT_TOKEN_ID=vault&#34;</span> vault:latest
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>export VAULT_ADDR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://localhost:8200&#34;</span>
</span></span><span style="display:flex;"><span>export VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;vault&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># create root ca</span>
</span></span><span style="display:flex;"><span>certs_dir<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;./ca&#34;</span>
</span></span><span style="display:flex;"><span>pem<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>cat $certs_dir/ca.crt $certs_dir/private.key<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault secrets enable -path<span style="color:#f92672">=</span>pki_root pki
</span></span><span style="display:flex;"><span>vault secrets tune -max-lease-ttl<span style="color:#f92672">=</span>87600h pki_root
</span></span><span style="display:flex;"><span>vault write pki_root/config/ca pem_bundle<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$pem<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># create the intermediate</span>
</span></span><span style="display:flex;"><span>vault secrets enable pki
</span></span><span style="display:flex;"><span>vault secrets tune -max-lease-ttl<span style="color:#f92672">=</span>43800h pki
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>csr<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>vault write pki/intermediate/generate/internal <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -format<span style="color:#f92672">=</span>json common_name<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Spectre Dev Intermdiate CA&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  | jq -r .data.csr<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>intermediate<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>vault write pki_root/root/sign-intermediate <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -format<span style="color:#f92672">=</span>json csr<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$csr<span style="color:#e6db74">&#34;</span> format<span style="color:#f92672">=</span>pem_bundle ttl<span style="color:#f92672">=</span>43800h <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  | jq -r .data.certificate<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>chained<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>echo -e <span style="color:#e6db74">&#34;</span>$intermediate<span style="color:#e6db74">\n</span><span style="color:#66d9ef">$(</span>cat $certs_dir/ca.crt<span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault write pki/intermediate/set-signed certificate<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$chained<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;</span>$intermediate<span style="color:#e6db74">&#34;</span> &gt; intermediate.crt
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault write pki/roles/cert <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  allowed_domains<span style="color:#f92672">=</span>localhost,mshome.net <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  allow_subdomains<span style="color:#f92672">=</span>true <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  max_ttl<span style="color:#f92672">=</span>43800h
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># destroy the temp root</span>
</span></span><span style="display:flex;"><span>vault secrets disable pki_root
</span></span></code></pre></div><p>We use the <code>pki_root</code> backend to sign a CSR from the <code>pki</code> (intermediate) backend, and once the signed response is stored in <code>pki</code>, we delete the <code>pki_root</code> backend, as it is no longer needed for our Development Intermediate CA.</p>
<h2 id="issuing-certificates">Issuing Certificates</h2>
<p>We can now use the <code>cert</code> role to issue certificates for our applications, which I have in a script called <code>issue.sh</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>export VAULT_ADDR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://localhost:8200&#34;</span>
</span></span><span style="display:flex;"><span>export VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;vault&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault write <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -format<span style="color:#f92672">=</span>json <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  pki/issue/cert <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  common_name<span style="color:#f92672">=</span>$1.mshome.net
</span></span></code></pre></div><p>This script I usually use with <code>jq</code> to do something useful with:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>response<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>./issue.sh consul<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>cert<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>echo <span style="color:#e6db74">&#34;</span>$response<span style="color:#e6db74">&#34;</span> | jq -r .data.certificate<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>key<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>echo <span style="color:#e6db74">&#34;</span>$response<span style="color:#e6db74">&#34;</span> | jq -r .data.private_key<span style="color:#66d9ef">)</span>
</span></span></code></pre></div><h2 id="cleaning-up">Cleaning Up</h2>
<p>When I have finished with an application or demo, I can just stop the Vault container, and run the <code>run_ca.sh</code> script again if I need Vault for another project.</p>
]]></content:encoded></item><item><title>Architecture Decision Records</title><link>https://andydote.co.uk/2019/06/29/architecture-decision-records/</link><pubDate>Sat, 29 Jun 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/06/29/architecture-decision-records/</guid><description>This is a text version of a short talk (affectionately known as a &amp;ldquo;Coffee Bag&amp;rdquo;) I gave at work this week, on Architecture Design Records. You can see the slides here, but there isn&amp;rsquo;t a recording available, unfortunately.
It should be noted; these are not to replace full architecture diagrams; you should definitely still write C4 Models to cover the overall architecture. ADRs are for the details, such as serializer formats, convention-over-configuration details, number precisions for timings, or which metrics library is used and why.</description><content:encoded><![CDATA[<p>This is a text version of a short talk (affectionately known as a &ldquo;Coffee Bag&rdquo;) I gave at work this week, on Architecture Design Records.  You can see the <a href="/presentations/index.html?adr">slides here</a>, but there isn&rsquo;t a recording available, unfortunately.</p>
<p>It should be noted; these are not to replace full architecture diagrams; you should definitely still write <a href="https://c4model.com">C4 Models</a> to cover the overall architecture.  ADRs are for the details, such as serializer formats, convention-over-configuration details, number precisions for timings, or which metrics library is used and why.</p>
<h2 id="what">What?</h2>
<p>Architecture Design Records are there to solve the main question people repeatedly ask when they view a new codebase or look at an older part of their current codebase:</p>
<blockquote>
<p>Why on earth was it done like this?!</p>
</blockquote>
<p>Generally speaking, architectural decisions have been made in good faith at the time, but as time marches on, things change, and the reasoning gets lost.  The reasoning might be discoverable through the commit history, or some comments in a type somewhere, and every once in a while, people remember the Wiki exists, and hope that someone else remembered and put some docs there.  They didn&rsquo;t by the way.</p>
<p>Architecture Design Records are aiming to solve all of this, with three straightforward attributes: Easy to Write, Easy to Read, and Easy to Find.  Let&rsquo;s look at these on their own, and then have a look at an example.</p>
<h2 id="easy-to-find">Easy to Find</h2>
<p>As I alluded to earlier, &ldquo;easy to find&rdquo; doesn&rsquo;t mean &ldquo;hidden in confluence&rdquo; (or any other wiki, for that matter.)  The best place to put records of architecture decisions is in the repository.  If you want them elsewhere, that&rsquo;s fine, but the copy in the repository should be the source of truth.</p>
<p>As long as the location is consistent (and somewhat reasonable), it doesn&rsquo;t matter too much where they go.  I like to put them in the <code>docs/arch</code> path, but a common option is <code>docs/adr</code> too:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ tree ~/dev/projects/awesome-api
</span></span><span style="display:flex;"><span>|-- docs
</span></span><span style="display:flex;"><span>|   <span style="color:#e6db74">`</span>-- arch
</span></span><span style="display:flex;"><span>|       |-- api-error-codes.md
</span></span><span style="display:flex;"><span>|       |-- controller-convention.md
</span></span><span style="display:flex;"><span>|       <span style="color:#e6db74">`</span>-- serialization-format.md
</span></span><span style="display:flex;"><span>|-- src
</span></span><span style="display:flex;"><span>|-- test
</span></span><span style="display:flex;"><span><span style="color:#e6db74">`</span>-- readme.md
</span></span></code></pre></div><p>The file names for each architecture decision are imperative - e.g. &ldquo;serialization format&rdquo;, rather than &ldquo;figure out what format to use&rdquo;, much like your commit messages are (right?)  You might also note that the files are Markdown.  Because what else would they be really?</p>
<h2 id="easy-to-write">Easy to Write</h2>
<p>As just mentioned, I usually use Markdown for writing all documents, but as long as you are consistent (notice a pattern here?) and that it is plain-text viewable (i.e. in a terminal), it doesn&rsquo;t matter too much.  Try and pick a format that doesn&rsquo;t add much mental overhead to writing the documents, and if it can be processed by tools easily, that&rsquo;s a bonus, as we will look into later.</p>
<h2 id="easy-to-read">Easy to Read</h2>
<p>There are two components to this:  Rendering and Format.</p>
<p>Rendering is covering how we actually read it - plain text in a terminal, syntax highlighting in an editor, or rendered into a web page.  Good ADRs can handle all three, and Markdown is a good fit for all of them!  By using Markdown, not only can we render to HTML, we can even use Confluences&rsquo;s questionable &ldquo;Insert Markdown Markup&rdquo; support to write them into a wiki location if desired.</p>
<p>Format is covering what the content of the document is.  There are <a href="https://github.com/joelparkerhenderson/architecture_decision_record">many different templates you can use</a>, which have different levels of detail, and are aimed at different levels of decisions.  I like to use a template based off <a href="https://github.com/joelparkerhenderson/architecture_decision_record/blob/master/adr_template_by_michael_nygard.md">Michael Nygard&rsquo;s</a>, which I modified a little bit to have the following sections:</p>
<ul>
<li>Title</li>
<li>Status</li>
<li>Context</li>
<li>Considered Options</li>
<li>Chosen Decision</li>
<li>Consequences</li>
</ul>
<p>Let&rsquo;s have a look at these in an example.</p>
<h2 id="example">Example</h2>
<p>We have a new API we are developing, and we need to figure out which serialization format we should use for all the requests and responses it will handle.</p>
<p>We&rsquo;ll start off with our empty document and add in the Title, and Status:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span># Serialization Format
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## Status
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>In Progress
</span></span></code></pre></div><p>The Title is <em>usually</em> the same as the file name, but not necessarily.  The Status indicates where the document is in its lifespan.  What statuses you choose is up to you, but I usually have:</p>
<ul>
<li>In Progress</li>
<li>Accepted</li>
<li>Rejected</li>
<li>Superseded</li>
<li>Deprecated</li>
</ul>
<p>Once an ADR is Accepted (or Rejected), the content won&rsquo;t change again.  Any subsequent changes will be a new ADR, and the previous one will be marked as either Deprecated or Superseded, along with a link to the ADR which replaces it, for example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span><span style="color:#75715e">## Status
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>Superseded by [<span style="color:#f92672">Api Transport Mechanisms</span>](<span style="color:#a6e22e">api-transport-mechanisms.md</span>)
</span></span></code></pre></div><p>Next, we need to add some context for the decision being made.  In our serialization example, this will cover what area of the codebase we are covering (the API, rather than storage), and any key points, such as message volume, compatibilities etc.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span><span style="color:#75715e">## Context
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>We need to have a consistent serialization scheme for the API.  It needs to be backwards and forwards compatible, as we don&#39;t control all of the clients.  Messages will be fairly high volume and don&#39;t <span style="font-style:italic">*need*</span> to be human readable.
</span></span></code></pre></div><p>{: .wrap }</p>
<p>Now that we have some context, we need to explain what choices we have available.  This will help when reading past decisions, as it will let us answer the question &ldquo;was xxxx or yyyy considered?&rdquo;.  In our example, we consider JSON, Apache Avro, the inbuilt binary serializer, and a custom built serializer (and others, such as Thrift, ProtoBufs, etc.)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span><span style="color:#75715e">## Considered Options
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">1.</span> <span style="font-weight:bold">**Json**</span>: Very portable, and with serializers available for all languages.  We need to agree on a date format, and numeric precision, however.  The serialization should not include white space to save payload size.  Forwards and Backwards compatibility exists but is the developer&#39;s responsibility.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">2.</span> <span style="font-weight:bold">**Apache Avro**</span>: Binary format which includes the schema with the data, meaning no need for schema distribution.  No code generator to run, and libraries are available for most languages.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">3.</span> <span style="font-weight:bold">**Inbuilt Binary**</span>: The API is awkward to use, and its output is not portable to other programming languages, so wouldn&#39;t be easy to consume for other teams, as well as some of our internal services.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">4.</span> <span style="font-weight:bold">**Custom Built**</span>: A lot of overhead for little to no benefit over Avro/gRPC etc.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">5.</span> <span style="font-weight:bold">**Thrift**</span>: ...
</span></span></code></pre></div><p>{: .wrap }</p>
<p>The second to last section is our Chosen Decision, which will not only list which one we picked (Avro, in this case) but also why it was chosen over other options.  All this helps reading older decisions, as it lets you know what was known at the time the decision was made - and you will always know less at the time of the decision than you do now.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span><span style="color:#75715e">## Chosen Decision
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">**2. Apache Avro**</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Avro was chosen because it has the best combination of message size and schema definition.  No need to have a central schema repository set up is also a huge benefit.
</span></span></code></pre></div><p>{: .wrap }</p>
<p>In this example, we have selected Avro and listed that our main reasons were message size, and the fact that Avro includes the schema with each message, meaning we don&rsquo;t need a central (or distributed) schema repository to be able to read messages.</p>
<p>The final section is for Consequences of the decision.  This is <strong>not</strong> to list reasons that we could have picked other decisions, but to explain things that we need to start doing or stop doing because of this decision.  Let&rsquo;s see what our example has:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span><span style="color:#75715e">## Consequences
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>As the messages are binary format, we cannot directly view them on the wire.  However, a small CLI will be built to take a message and pretty print it to aid debugging.
</span></span></code></pre></div><p>{: .wrap }</p>
<p>As we have selected a binary message format, the messages can&rsquo;t be easily viewed any more, so we will build a small CLI which when given a message (which as noted, contains the schema), renders a human-readable version of the message.</p>
<h2 id="dates">Dates</h2>
<p>You might notice that the record doesn&rsquo;t contain any dates so far.  That is because it&rsquo;s tracked in source control, which means we can pull all the relevant information from the commit history.  For example, a full list of changes to any ADR could be fetched from Git with this command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git log --format<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;%ci %s&#39;</span> -- docs/arch/
</span></span></code></pre></div><p>Likewise, when you&rsquo;re running your build process, you could extract the commit history which effects a single ADR:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git log --reverse --format<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;%ci %s&#39;</span> -- docs/arch/serialization-format.md
</span></span></code></pre></div><p>And then take that list and insert it into the rendered output so people can see what changed, and when:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">style</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;float: right&#34;</span>&gt;
</span></span><span style="display:flex;"><span>&lt;<span style="color:#f92672">h2</span>&gt;History&lt;/<span style="color:#f92672">h2</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">ul</span>&gt;
</span></span><span style="display:flex;"><span>        &lt;<span style="color:#f92672">li</span>&gt;&lt;<span style="color:#f92672">strong</span>&gt;2018-09-26&lt;/<span style="color:#f92672">strong</span>&gt; start serialization format docs&lt;/<span style="color:#f92672">li</span>&gt;
</span></span><span style="display:flex;"><span>        &lt;<span style="color:#f92672">li</span>&gt;&lt;<span style="color:#f92672">strong</span>&gt;2018-09-26&lt;/<span style="color:#f92672">strong</span>&gt; consider json&lt;/<span style="color:#f92672">li</span>&gt;
</span></span><span style="display:flex;"><span>        &lt;<span style="color:#f92672">li</span>&gt;&lt;<span style="color:#f92672">strong</span>&gt;2018-09-26&lt;/<span style="color:#f92672">strong</span>&gt; consider avro, inbuilt binary and custom binary&lt;/<span style="color:#f92672">li</span>&gt;
</span></span><span style="display:flex;"><span>        &lt;<span style="color:#f92672">li</span>&gt;&lt;<span style="color:#f92672">strong</span>&gt;2018-09-27&lt;/<span style="color:#f92672">strong</span>&gt; should consider thrift too&lt;/<span style="color:#f92672">li</span>&gt;
</span></span><span style="display:flex;"><span>        &lt;<span style="color:#f92672">li</span>&gt;&lt;<span style="color:#f92672">strong</span>&gt;2018-09-28&lt;/<span style="color:#f92672">strong</span>&gt; select Avro&lt;/<span style="color:#f92672">li</span>&gt;
</span></span><span style="display:flex;"><span>        &lt;<span style="color:#f92672">li</span>&gt;&lt;<span style="color:#f92672">strong</span>&gt;2018-09-28&lt;/<span style="color:#f92672">strong</span>&gt; accepted :)&lt;/<span style="color:#f92672">li</span>&gt;
</span></span><span style="display:flex;"><span>        &lt;<span style="color:#f92672">li</span>&gt;&lt;<span style="color:#f92672">strong</span>&gt;2019-03-12&lt;/<span style="color:#f92672">strong</span>&gt; accept api transport mechanisms&lt;/<span style="color:#f92672">li</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;/<span style="color:#f92672">ul</span>&gt;
</span></span><span style="display:flex;"><span>&lt;/<span style="color:#f92672">div</span>&gt;
</span></span></code></pre></div><p>Note how that last log entry is the deprecation of this ADR.  You can, of course, expand your log parsing only to detect Status changes etc.</p>
<h2 id="end">End</h2>
<p>Hopefully, this gives you a taste of how easily useful documentation can be written, read and found.  I&rsquo;m interested to hear anyone else&rsquo;s thoughts on whether they find this useful, or any other alternatives.</p>
]]></content:encoded></item><item><title>Canary Routing with Traefik in Nomad</title><link>https://andydote.co.uk/2019/06/23/nomad-traefik-canary/</link><pubDate>Sun, 23 Jun 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/06/23/nomad-traefik-canary/</guid><description>I wanted to implement canary routing for some HTTP services deployed via Nomad the other day, but rather than having the traffic split by weighting to the containers, I wanted to direct the traffic based on a header.
My first choice of tech was to use Fabio, but it only supports routing by URL prefix, and additionally with a route weight. While I was at JustDevOps in Poland, I heard about another router/loadbalancer which worked in a similar way to Fabio: Traefik.</description><content:encoded><![CDATA[<p>I wanted to implement canary routing for some HTTP services deployed via <a href="https://www.nomadproject.io/">Nomad</a> the other day, but rather than having the traffic split by weighting to the containers, I wanted to direct the traffic based on a header.</p>
<p>My first choice of tech was to use <a href="https://fabiolb.net/">Fabio</a>, but it only supports routing by URL prefix, and additionally with a route weight.  While I was at <a href="https://justdevops.org/">JustDevOps</a> in Poland, I heard about another router/loadbalancer which worked in a similar way to Fabio: <a href="https://traefik.io/">Traefik</a>.</p>
<p>While Traefik also doesn&rsquo;t directly support canary routing, it is much more flexible than Fabio, also allowing request filtering based on HTTP headers.  Traefik integrates with a number of container schedulers directly, but Nomad is not one of them.  It does however also support using the Consul Service Catalog so that you can use it as an almost drop-in replacement for Fabio.</p>
<p>So let&rsquo;s get to the setup.  As usual, there is a complete repository on GitHub: <a href="https://github.com/Pondidum/nomad-traefik-canary-demo">Nomad Traefik Canary Routing</a>.</p>
<h2 id="nomad">Nomad</h2>
<p>As usual, I am using my <a href="https://github.com/Pondidum/hashibox">Hashibox</a> <a href="https://vagrantup.com/">Vagrant</a> base image, and provisioning it as a single Nomad server and client node, using <a href="https://github.com/Pondidum/nomad-traefik-canary-demo/blob/master/scripts/server.sh">this script</a>.  I won&rsquo;t dig into all the setup in that, as I&rsquo;ve written it a few times now.</p>
<h2 id="consul">Consul</h2>
<p>Consul is already running on the Hashibox base, so we have no further configuration to do.</p>
<h2 id="traefik">Traefik</h2>
<p>Traefik can be deployed as a Docker container, and either configured through a TOML file (yay, <a href="https://noyaml.com/">not yaml!</a>) or with command line switches.  As we only need a minimal configuration, I opted to use the command line.</p>
<p>The container exposes two ports we need to care about: <code>80</code> for incoming traffic to be routed, and <code>8080</code> for the UI, which are statically allocated to the host as <code>8000</code> and <code>8080</code> for this demo.</p>
<p>The command line configuration used is as follows:</p>
<ul>
<li><code>--api</code> - enable the UI.</li>
<li><code>--consulcatalog</code> - Traefik has two ways to use Consul - <code>--consul</code> uses the KV store for service definitions, and <code>--consulcatalog</code> makes use Consul&rsquo;s service catalogue.</li>
<li><code>--consulcatalog.endpoint=consul.service.consul:8500</code> as Consul is not running in the same container as Traefik, we need to tell it where Consul is listening, and as we have <a href="">DNS Forwarding for <code>*.consul</code> domains</a>, we use the address <code>consul.service.consul</code>.  If DNS forwarding was not available, you could use the Nomad variable <code>${attr.unique.network.ip-address}</code> to get the current task&rsquo;s host&rsquo;s IP.</li>
<li><code>--consulcatalog.frontEndRule</code> disable the default rule - each service needs to specify <code>traefik.frontend.rule</code>.</li>
<li><code>--consulcatalog.exposedByDefault=false</code> - lastly, we stop Traefik showing all services registered into consul, the will need to have the <code>traefik.enable=true</code> tag to be processed.</li>
</ul>
<p>The entire job file is listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>job <span style="color:#e6db74">&#34;traefik&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  datacenters <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;dc1&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>  type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;service&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  group <span style="color:#e6db74">&#34;loadbalancers&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    count <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    task <span style="color:#e6db74">&#34;traefik&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>      driver <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;docker&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      config <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>        image <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;traefik:1.7.12&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        args <span style="color:#f92672">=</span> <span style="color:#f92672">[</span>
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;--api&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;--consulcatalog&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;--consulcatalog.endpoint=consul.service.consul:8500&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;--consulcatalog.frontEndRule=&#39;&#39;&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;--consulcatalog.exposedByDefault=false&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        port_map <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>          http <span style="color:#f92672">=</span> <span style="color:#ae81ff">80</span>
</span></span><span style="display:flex;"><span>          ui <span style="color:#f92672">=</span> <span style="color:#ae81ff">8080</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      resources <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>        network <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>          port <span style="color:#e6db74">&#34;http&#34;</span> <span style="color:#f92672">{</span> static <span style="color:#f92672">=</span> <span style="color:#ae81ff">8000</span> <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>          port <span style="color:#e6db74">&#34;ui&#34;</span> <span style="color:#f92672">{</span> static <span style="color:#f92672">=</span> <span style="color:#ae81ff">8080</span> <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        memory <span style="color:#f92672">=</span> <span style="color:#ae81ff">50</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>We register the job into Nomad, and then start on the backend services we will route to:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>nomad job run jobs/traefik.nomad
</span></span></code></pre></div><h2 id="the-backend-services">The Backend Services</h2>
<p>To demonstrate the services can be routed to correctly, we can use the <code>containersol/k8s-deployment-strategies</code> docker container.  This image exposes an HTTP service which responds with the container&rsquo;s hostname and the content of the <code>VERSION</code> environment variable, something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ curl http://echo.service.consul:8080
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Host: 23351e48dc98, Version: 1.0.0</span>
</span></span></code></pre></div><p>We&rsquo;ll start by making a standard nomad job for this container, and then update it to support canarying.  The entire job is listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>job <span style="color:#e6db74">&#34;echo&#34;</span> {
</span></span><span style="display:flex;"><span>  datacenters <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;dc1&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>  type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;service&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  group <span style="color:#e6db74">&#34;apis&#34;</span> {
</span></span><span style="display:flex;"><span>    count <span style="color:#f92672">=</span> <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    task <span style="color:#e6db74">&#34;echo&#34;</span> {
</span></span><span style="display:flex;"><span>      driver <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;docker&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      config {
</span></span><span style="display:flex;"><span>        image <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;containersol/k8s-deployment-strategies&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        port_map {
</span></span><span style="display:flex;"><span>          http <span style="color:#f92672">=</span> <span style="color:#ae81ff">8080</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      env {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">VERSION</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;1.0.0&#34;</span>
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      resources {
</span></span><span style="display:flex;"><span>        network {
</span></span><span style="display:flex;"><span>          port <span style="color:#e6db74">&#34;http&#34;</span> { }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      service {
</span></span><span style="display:flex;"><span>        name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;echo&#34;</span>
</span></span><span style="display:flex;"><span>        port <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        tags <span style="color:#f92672">=</span> <span style="color:#f92672">[</span>
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;traefik.enable=true&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;traefik.frontend.rule=Host:api.localhost&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        check {
</span></span><span style="display:flex;"><span>          type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http&#34;</span>
</span></span><span style="display:flex;"><span>          path <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/&#34;</span>
</span></span><span style="display:flex;"><span>          interval <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;5s&#34;</span>
</span></span><span style="display:flex;"><span>          timeout <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;1s&#34;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The only part of interest in this version of the job is the <code>service</code> stanza, which is registering our echo service into consul, with a few tags to control how it is routed by Traefik:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>service {
</span></span><span style="display:flex;"><span>  name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;echo&#34;</span>
</span></span><span style="display:flex;"><span>  port <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  tags <span style="color:#f92672">=</span> <span style="color:#f92672">[</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;traefik.enable=true&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;traefik.frontend.rule=Host:api.localhost&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  check {
</span></span><span style="display:flex;"><span>    type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http&#34;</span>
</span></span><span style="display:flex;"><span>    path <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/&#34;</span>
</span></span><span style="display:flex;"><span>    interval <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;5s&#34;</span>
</span></span><span style="display:flex;"><span>    timeout <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;1s&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>traefik.enabled=true</code> tag allows this service to be handled by Traefik (as we set <code>exposedByDefault=false</code> in Traefik), and <code>traefik.frontend.rule=Host:api.localhost</code> the rule means that any traffic with the <code>Host</code> header set to <code>api.localhost</code> will be routed to the service.</p>
<p>Which we can now run the job in Nomad:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>nomad job run jobs/echo.nomad
</span></span></code></pre></div><p>Once it is up and running, we&rsquo;ll get 3 instances of <code>echo</code> running which will be round-robin routed by Traefik:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ curl http://traefik.service.consul:8080 -H <span style="color:#e6db74">&#39;Host: api.localhost&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#Host: 1ac8a49cbaee, Version: 1.0.0</span>
</span></span><span style="display:flex;"><span>$ curl http://traefik.service.consul:8080 -H <span style="color:#e6db74">&#39;Host: api.localhost&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#Host: 23351e48dc98, Version: 1.0.0</span>
</span></span><span style="display:flex;"><span>$ curl http://traefik.service.consul:8080 -H <span style="color:#e6db74">&#39;Host: api.localhost&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#Host: c2f8a9dcab95, Version: 1.0.0</span>
</span></span></code></pre></div><p>Now that we have working routing for the Echo service let&rsquo;s make it canaryable.</p>
<h2 id="canaries">Canaries</h2>
<p>To show canary routing, we will create a second version of the service to respond to HTTP traffic with a <code>Canary</code> header.</p>
<p>The first change to make is to add in the <code>update</code> stanza, which controls how the containers get updated when Nomad pushes a new version.  The <code>canary</code> parameter controls how many instances of the task will be created for canary purposes (and must be less than the total number of containers).  Likewise, the <code>max_parallel</code> parameter controls how many containers will be replaced at a time when a deployment happens.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span>group &#34;apis&#34; {
</span></span><span style="display:flex;"><span>  count = 3
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">+  update {
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+    max_parallel = 1
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+    canary = 1
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+  }
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>
</span></span><span style="display:flex;"><span>  task &#34;echo&#34; {
</span></span></code></pre></div><p>Next, we need to modify the <code>service</code> stanza to write different tags to Consul when a task is a canary instance so that it does not get included in the &ldquo;normal&rdquo; backend routing group.</p>
<p>If we don&rsquo;t specify at least 1 value in <code>canary_tags</code>, Nomad will use the <code>tags</code> even in the canary version - an empty <code>canary_tags = []</code> declaration is not enough!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span>service {
</span></span><span style="display:flex;"><span>  name = &#34;echo&#34;
</span></span><span style="display:flex;"><span>  port = &#34;http&#34;
</span></span><span style="display:flex;"><span>  tags = [
</span></span><span style="display:flex;"><span>    &#34;traefik.enable=true&#34;,
</span></span><span style="display:flex;"><span>    &#34;traefik.frontend.rule=Host:api.localhost&#34;
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">+  canary_tags = [
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+    &#34;traefik.enable=false&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+  ]
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>  check {
</span></span></code></pre></div><p>Finally, we need to add a separate <code>service</code> stanza to create a second backend group which will contain the canary versions.  Note how this group has a different name, and has no <code>tags</code>, but does have a set of <code>canary_tags</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>service {
</span></span><span style="display:flex;"><span>  name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;echo-canary&#34;</span>
</span></span><span style="display:flex;"><span>  port <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http&#34;</span>
</span></span><span style="display:flex;"><span>  tags <span style="color:#f92672">=</span> <span style="color:#f92672">[]</span>
</span></span><span style="display:flex;"><span>  canary_tags <span style="color:#f92672">=</span> <span style="color:#f92672">[</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;traefik.enable=true&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;traefik.frontend.rule=Host:api.localhost;Headers: Canary,true&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>  check {
</span></span><span style="display:flex;"><span>    type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http&#34;</span>
</span></span><span style="display:flex;"><span>    path <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/&#34;</span>
</span></span><span style="display:flex;"><span>    interval <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;5s&#34;</span>
</span></span><span style="display:flex;"><span>    timeout <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;1s&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The reason we need two <code>service</code> stanzas is that Traefik can only create backends based on the name of the service registered to Consul and not from a tag in that registration.  If we just used one <code>service</code> stanza, then the canary version of the container would be added to both the canary backend and standard backend.  I was hoping for <code>traefik.backend=echo-canary</code> to work, but alas no.</p>
<p>The entire updated jobfile is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>job <span style="color:#e6db74">&#34;echo&#34;</span> {
</span></span><span style="display:flex;"><span>  datacenters <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;dc1&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>  type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;service&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  group <span style="color:#e6db74">&#34;apis&#34;</span> {
</span></span><span style="display:flex;"><span>    count <span style="color:#f92672">=</span> <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    update {
</span></span><span style="display:flex;"><span>      max_parallel <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>      canary <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    task <span style="color:#e6db74">&#34;echo&#34;</span> {
</span></span><span style="display:flex;"><span>      driver <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;docker&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      config {
</span></span><span style="display:flex;"><span>        image <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;containersol/k8s-deployment-strategies&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        port_map {
</span></span><span style="display:flex;"><span>          http <span style="color:#f92672">=</span> <span style="color:#ae81ff">8080</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      env {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">VERSION</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;1.0.0&#34;</span>
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      resources {
</span></span><span style="display:flex;"><span>        network {
</span></span><span style="display:flex;"><span>          port <span style="color:#e6db74">&#34;http&#34;</span> { }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        memory <span style="color:#f92672">=</span> <span style="color:#ae81ff">50</span>
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      service {
</span></span><span style="display:flex;"><span>        name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;echo-canary&#34;</span>
</span></span><span style="display:flex;"><span>        port <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        tags <span style="color:#f92672">=</span> <span style="color:#f92672">[]</span>
</span></span><span style="display:flex;"><span>        canary_tags <span style="color:#f92672">=</span> <span style="color:#f92672">[</span>
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;traefik.enable=true&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;traefik.frontend.rule=Host:api.localhost;Headers: Canary,true&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        check {
</span></span><span style="display:flex;"><span>          type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http&#34;</span>
</span></span><span style="display:flex;"><span>          path <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/&#34;</span>
</span></span><span style="display:flex;"><span>          interval <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;5s&#34;</span>
</span></span><span style="display:flex;"><span>          timeout <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;1s&#34;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      service {
</span></span><span style="display:flex;"><span>        name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;echo&#34;</span>
</span></span><span style="display:flex;"><span>        port <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        tags <span style="color:#f92672">=</span> <span style="color:#f92672">[</span>
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;traefik.enable=true&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;traefik.frontend.rule=Host:api.localhost&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>        canary_tags <span style="color:#f92672">=</span> <span style="color:#f92672">[</span>
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;traefik.enable=false&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        check {
</span></span><span style="display:flex;"><span>          type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http&#34;</span>
</span></span><span style="display:flex;"><span>          path <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/&#34;</span>
</span></span><span style="display:flex;"><span>          interval <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;5s&#34;</span>
</span></span><span style="display:flex;"><span>          timeout <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;1s&#34;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="testing">Testing</h2>
<p>First, we will change the <code>VERSION</code> environment variable so that Nomad sees the job as changed, and we get a different response from HTTP calls to the canary:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span>env {
</span></span><span style="display:flex;"><span><span style="color:#f92672">-  VERSION = &#34;1.0.0&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#f92672"></span><span style="color:#a6e22e">+  VERSION = &#34;2.0.0&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e"></span>}
</span></span></code></pre></div><p>Now we will update the job in Nomad:</p>
<pre tabindex="0"><code>nomad job run jobs/echo.nomad
</code></pre><p>If we run the status command, we can see that the deployment has started, and there is one canary instance running.  Nothing further will happen until we promote it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ nomad status echo
</span></span><span style="display:flex;"><span>ID            <span style="color:#f92672">=</span> echo
</span></span><span style="display:flex;"><span>Status        <span style="color:#f92672">=</span> running
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Latest Deployment
</span></span><span style="display:flex;"><span>ID          <span style="color:#f92672">=</span> 330216b9
</span></span><span style="display:flex;"><span>Status      <span style="color:#f92672">=</span> running
</span></span><span style="display:flex;"><span>Description <span style="color:#f92672">=</span> Deployment is running but requires promotion
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Deployed
</span></span><span style="display:flex;"><span>Task Group  Promoted  Desired  Canaries  Placed  Healthy  Unhealthy  Progress Deadline
</span></span><span style="display:flex;"><span>apis        false     <span style="color:#ae81ff">3</span>        <span style="color:#ae81ff">1</span>         <span style="color:#ae81ff">1</span>       <span style="color:#ae81ff">1</span>        <span style="color:#ae81ff">0</span>          2019-06-19T11:19:31Z
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Allocations
</span></span><span style="display:flex;"><span>ID        Node ID   Task Group  Version  Desired  Status   Created    Modified
</span></span><span style="display:flex;"><span>dcff2555  82f6ea8b  apis        <span style="color:#ae81ff">1</span>        run      running  18s ago    2s ago
</span></span><span style="display:flex;"><span>5b2710ed  82f6ea8b  apis        <span style="color:#ae81ff">0</span>        run      running  6m52s ago  6m26s ago
</span></span><span style="display:flex;"><span>698bd8a7  82f6ea8b  apis        <span style="color:#ae81ff">0</span>        run      running  6m52s ago  6m27s ago
</span></span><span style="display:flex;"><span>b315bcd3  82f6ea8b  apis        <span style="color:#ae81ff">0</span>        run      running  6m52s ago  6m25s ago
</span></span></code></pre></div><p>We can now test that the original containers still work, and that the canary version works:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ curl http://traefik.service.consul:8080 -H <span style="color:#e6db74">&#39;Host: api.localhost&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#Host: 1ac8a49cbaee, Version: 1.0.0</span>
</span></span><span style="display:flex;"><span>$ curl http://traefik.service.consul:8080 -H <span style="color:#e6db74">&#39;Host: api.localhost&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#Host: 23351e48dc98, Version: 1.0.0</span>
</span></span><span style="display:flex;"><span>$ curl http://traefik.service.consul:8080 -H <span style="color:#e6db74">&#39;Host: api.localhost&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#Host: c2f8a9dcab95, Version: 1.0.0</span>
</span></span><span style="display:flex;"><span>$ curl http://traefik.service.consul:8080 -H <span style="color:#e6db74">&#39;Host: api.localhost&#39;</span> -H <span style="color:#e6db74">&#39;Canary: true&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#Host: 496840b438f2, Version: 2.0.0</span>
</span></span></code></pre></div><p>Assuming we are happy with our new version, we can tell Nomad to promote the deployment, which will remove the canary and start a rolling update of the three tasks, one at a time:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>nomad deployment promote 330216b9
</span></span></code></pre></div><h2 id="end">End</h2>
<p>My hope is that the next version of Traefik will have better support for canary by header, meaning I could simplify the Nomad jobs a little, but as it stands, this doesn&rsquo;t add much complexity to the jobs, and can be easily put into an Architecture Decision Record (or documented in a wiki page, never to be seen or read from again!)</p>
]]></content:encoded></item><item><title>Feature Toggles: Reducing Coupling</title><link>https://andydote.co.uk/2019/06/11/feature-toggles-reducing-coupling/</link><pubDate>Tue, 11 Jun 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/06/11/feature-toggles-reducing-coupling/</guid><description>One of the points I make in my Feature Toggles talk is that you shouldn&amp;rsquo;t be querying a toggle&amp;rsquo;s status all over your codebase. Ideally, each toggle gets checked in as few places as possible - preferably only one place. The advantage of doing this is that very little of your codebase needs to be coupled to the toggles (either the toggle itself or the library/system for managing toggles itself).</description><content:encoded><![CDATA[<p>One of the points I make in my <a href="https://www.youtube.com/watch?v=r7VI5x2XKXw">Feature Toggles talk</a> is that you shouldn&rsquo;t be querying a toggle&rsquo;s status all over your codebase.  Ideally, each toggle gets checked in as few places as possible - preferably only one place.  The advantage of doing this is that very little of your codebase needs to be coupled to the toggles (either the toggle itself or the library/system for managing toggles itself).</p>
<p>This post will go over several situations when that seems hard to do, namely: multiple services, multiple distinct areas of a codebase, and multiple times in a complex class or method.  As in the <a href="/2019/06/03/feature-toggles-branch-by-abstraction/">previous post</a> on this, we will be using <a href="https://www.martinfowler.com/bliki/BranchByAbstraction.html">Branch By Abstraction</a> to do most of the heavy lifting.</p>
<h2 id="multiple-services">Multiple Services</h2>
<p>Multiple services interacting with the same feature toggle is a problematic situation to deal with, especially if multiple teams own the different services.</p>
<p>One of the main issues with this is trying to coordinate the two (or more) services.  For example, if one team needs to switch off their implementation due to a problem, should the other services also get turned off too?  To compound on this problem, what happens if one system can react to the toggle change faster than the other?</p>
<p>Services changing configuration at different speeds can also cause issues with handling in-flight requests too: if the message format is different when the toggle is on, will the receiving system be able to process a message produced when the toggle was in one state but consumed in the other state?</p>
<p>We can solve some of this by using separate toggles for each service (and they are not allowed to query the other service&rsquo;s toggle state), and by writing the services so that they can handle both old format and new format requests at the same time.</p>
<p>For example, if we had a sending system which when the toggle is off will send this DTO:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PurchaseOptions</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Address Address { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And when the toggle is enabled, it will send the following DTO instead:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PurchaseOptions</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> BillingAddress Address { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> DeliveryAddress Address { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>To make the receiving system handle this, we deserialize the request into a DTO which contains all possible versions of the address, and then use the best version based on our own toggle state:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PurchaseOptionsRequest</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Address Address { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> BillingAddress Address { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> DeliveryAddress Address { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PurchaseController</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task&lt;PurchaseOptionsResponse&gt; Post(PurchaseOptionsRequest request)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (separateAddresses.Enabled)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">var</span> deliveryAddress = request.DeliveryAddress ?? request.Address;
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">var</span> billingAddress = request.BillingAddress ?? request.Address;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            ConfigureDelivery(deliveryAddress);
</span></span><span style="display:flex;"><span>            CreateInvoice(billingAddress, deliveryAddress);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">var</span> address = request.Address ?? request.DeliveryAddress ?? request.BillingAddress;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            ConfigureDelivery(address)
</span></span><span style="display:flex;"><span>            CreateInvoice(address, address);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note how both sides of the toggle check read all three possible address fields, but try to use different fields first.  This means that no matter whether the sending service has it&rsquo;s toggle on or not, we will use the correct address.</p>
<h2 id="multiple-areas-of-the-codebase">Multiple Areas of the Codebase</h2>
<p>To continue using the address example, we might have a UI, Controller and Handler, which all need to act differently based on the same toggle:</p>
<ul>
<li>The UI needs to display either one or two address editors</li>
<li>The controller needs to have different validation logic for multiple addresses</li>
<li>The Command Handler will need to dispatch different values</li>
</ul>
<p>We can solve this all by utilising <a href="https://www.martinfowler.com/bliki/BranchByAbstraction.html">Branch By Abstraction</a> and Dependency Injection to make most of the codebase unaware that a feature toggle exists.  Even the implementations won&rsquo;t need to know about the toggles.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Startup</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> ConfigureContainer(ServiceRegistry services)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (separateAddresses.Enabled) {
</span></span><span style="display:flex;"><span>            services.Add&lt;IAddressEditor, MultiAddressEditor&gt;();
</span></span><span style="display:flex;"><span>            services.Add&lt;IRequestValidator, MultiAddressValidator&gt;();
</span></span><span style="display:flex;"><span>            services.Add&lt;IDeliveryHandler, MultiAddressDeliveryHandler&gt;();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>            services.Add&lt;IAddressEditor, SingleAddressEditor&gt;();
</span></span><span style="display:flex;"><span>            services.Add&lt;IRequestValidator, SingleAddressValidator&gt;();
</span></span><span style="display:flex;"><span>            services.Add&lt;IDeliveryHandler, SingleAddressDeliveryHandler&gt;();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Let&rsquo;s look at how one of these might work.  The <code>IRequestValidator</code> has a definition like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IRequestValidator</span>&lt;TRequest&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> IEnumerable&lt;<span style="color:#66d9ef">string</span>&gt; Validate(TRequest request);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>There is a middleware in the API request pipeline which will pick the right validator out of the container, based on the request type being processed.  We implement two validators, once for the single address, and one for multiaddress:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">SingleAddressValidator</span> : IRequestValidator&lt;SingleAddressRequest&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> IEnumerable&lt;<span style="color:#66d9ef">string</span>&gt; Validate(SingleAddressRequest request)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//complex validation logic..</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (request.Address == <span style="color:#66d9ef">null</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">yield</span> <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;No Address specified&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (PostCode.Validate(request.Address.PostCode) == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">yield</span> <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Invalid Postcode&#34;</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MultiAddressValidator</span> : IRequestValidator&lt;MultiAddressRequest&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> IEnumerable&lt;<span style="color:#66d9ef">string</span>&gt; Validate(MultiAddressRequest request)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> billingMessages = ValidateAddress(request.BillingAddress);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (billingMessages.Any())
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> billingMessages;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (request.DifferentDeliveryAddress)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> ValidateAddress(request.DeliveryAddress);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The implementations themselves don&rsquo;t need to know about the state of the toggle, as the container and middleware take care of picking the right implementation to use.</p>
<h2 id="multiple-places-in-a-classmethod">Multiple Places in a Class/Method</h2>
<p>If you have a single method (or class) which needs to check the toggle state in multiple places, you can also use the same Branch by Abstraction technique as above, by creating a custom interface and pair of implementations, which contain all the functionality which changes.</p>
<p>For example, if we have a method for finding an offer for a customer&rsquo;s basket, which has a few separate checks that the toggle is enabled in it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> SuggestedBasket CreateOffer(CreateOfferCommand command)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (newFeature.Enabled) {
</span></span><span style="display:flex;"><span>        ExtraPreValidation(command).Throw();
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>        StandardPreValidation(command).Throw();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> offer = SelectBestOffer(command.Items);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (offer == <span style="color:#66d9ef">null</span> &amp;&amp; newFeature.Enabled) {
</span></span><span style="display:flex;"><span>        offer = FindAlternativeOffer(command.Customer, command.Items);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> SuggestedBasket
</span></span><span style="display:flex;"><span>        .From(command)
</span></span><span style="display:flex;"><span>        .With(offer);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We can extract an interface for this, and replace the toggle specific parts with calls to the interface instead:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">ICreateOfferStrategy</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    IThrowable PreValidate(CreateOfferCommand command);
</span></span><span style="display:flex;"><span>    Offer AlternativeOffer(CreateOfferCommand command, Offer existingOffer);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">DefaultOfferStrategy</span> : ICreateOfferStrategy
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> IThrowable PreValidate(CreateOfferCommand command)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> StandardPreValidation(command);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Offer AlternativeOffer(CreateOfferCommand command, Offer existingOffer)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> existingOffer;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">DefaultOfferStrategy</span> : ICreateOfferStrategy
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> IThrowable PreValidate(CreateOfferCommand command)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> ExtraPreValidation(command);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Offer AlternativeOffer(CreateOfferCommand command, Offer existingOffer)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (existingOffer != <span style="color:#66d9ef">null</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> existingOffer;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> TryFindAlternativeOffer(command.Customer, command.Items, offer);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">OfferBuilder</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> ICreateOfferStrategy _strategy;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> OfferBuilder(ICreateOfferStrategy strategy)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        _strategy = strategy;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> SuggestedBasket CreateOffer(CreateOfferCommand command)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        _strategy.PreValidation(command).Throw();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> offer = SelectBestOffer(command.Items);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        offer = _strategy.AlternativeOffer(command, offer);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> SuggestedBasket
</span></span><span style="display:flex;"><span>            .From(command)
</span></span><span style="display:flex;"><span>            .With(offer);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Now that we have done this, our <code>CreateOffer</code> method has shrunk dramatically and no longer needs to know about the toggle state, as like the rest of our DI examples, the toggle can be queried once in the startup of the service and the correct <code>ICreateOfferStrategy</code> implementation registered into the container.</p>
<h2 id="end">End</h2>
<p>Hopefully, this post will give a few insights into different ways of reducing the number of calls to your feature toggling library, and prevent you scattering lots of if statements around the codebase!</p>
]]></content:encoded></item><item><title>Feature Toggles: Branch by Abstraction</title><link>https://andydote.co.uk/2019/06/03/feature-toggles-branch-by-abstraction/</link><pubDate>Mon, 03 Jun 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/06/03/feature-toggles-branch-by-abstraction/</guid><description>Recently, I was asked if I could provide an example of Branch By Abstraction when dealing with feature toggles. As this has come up a few times, I thought a blog post would be a good idea so I can refer others to it later too.
The Context As usual, this is some kind of backend (micro)service, and it will send email messages somehow. We will start with two implementations of message sending: the &amp;ldquo;current&amp;rdquo; version; which is synchronous, and a &amp;ldquo;new&amp;rdquo; version; which is async.</description><content:encoded><![CDATA[<p>Recently, I was asked if I could provide an example of Branch By Abstraction when dealing with feature toggles.  As this has come up a few times, I thought a blog post would be a good idea so I can refer others to it later too.</p>
<h2 id="the-context">The Context</h2>
<p>As usual, this is some kind of backend (micro)service, and it will send email messages somehow.  We will start with two implementations of message sending: the &ldquo;current&rdquo; version; which is synchronous, and a &ldquo;new&rdquo; version; which is async.</p>
<p>We&rsquo;ll do a bit of setup to show how feature toggling can be done in three ways for this feature:</p>
<ol>
<li>Static: Configured on startup</li>
<li>Dynamic: Check the toggle state on each send</li>
<li>Dynamic: Check the toggle for a given message</li>
</ol>
<h2 id="abstractions-and-implementations">Abstractions and Implementations</h2>
<p>We have an interface called <code>IMessageDispatcher</code> which defines a single <code>Send</code> method, which returns a <code>Task</code> (or <code>Promise</code>, <code>Future</code>, etc. depending on your language.)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IMessageDispatcher</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    Task&lt;SendResult&gt; Send(Message message);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The two message sending implementations don&rsquo;t matter, but we need the types to show the other code examples.  Fill in the blanks if you want!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">HttpMessageDispatcher</span> : IMessageDispatcher
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// ...</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">QueueMessageDispatcher</span> : IMessageDispatcher
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// ...</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="1-static-configuration">1. Static Configuration</h2>
<p>The word static in this context means that we check the feature toggle&rsquo;s state once on startup and pick an implementation.  We don&rsquo;t recheck the toggle state unless the service is restarted.</p>
<p>For instance, in an ASP.Net core application, you could change which service is registered into the container at startup like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> ConfigureServices(IServiceCollection services)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> toggleSource = <span style="color:#66d9ef">new</span> ToggleSource(<span style="color:#75715e">/* ... */</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (toggleSource.IsActive(Toggles.AsyncMessageDispatch))
</span></span><span style="display:flex;"><span>        services.AddTransient&lt;IMessageDispatcher, QueueMessageDispatcher&gt;();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>        services.AddTransient&lt;IMessageDispatcher, HttpMessageDispatcher&gt;();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Which means any class which takes in an instance of <code>IMessageDispatcher</code> doesn&rsquo;t need to check the toggle state or worry about which implementation to use.</p>
<h2 id="2-dynamic-configuration">2. Dynamic Configuration</h2>
<p>We can build on this abstraction to enable more flexibility, if we want to be able to change the toggle state while the service is running, without needing to restart it.  To do this, we can implement another version of the <code>IMessageDispatcher</code> interface which will check the toggle state on each invocation of <code>Send()</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ToggleDispatcher</span> : IMessageDispatcher
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Func&lt;<span style="color:#66d9ef">bool</span>&gt; _isToggleActive;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IMessageDispatcher _queueSender;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IMessageDispatcher _httpSender;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> ToggleDispatcher(Func&lt;<span style="color:#66d9ef">bool</span>&gt; isToggleActive, IMessageDispatcher queueSender, IMessageDispatcher httpSender)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        _isToggleActive = isToggleActive;
</span></span><span style="display:flex;"><span>        _queueSender = queueSender;
</span></span><span style="display:flex;"><span>        _httpSender = httpSender;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Task&lt;SendResult&gt; Send(Message message)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> chosen = _isToggleActive()
</span></span><span style="display:flex;"><span>            ? _queueSender
</span></span><span style="display:flex;"><span>            : _httpSender;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> chosen.Send(message);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And in our startup class, we can change the service registration to use the new version.  Note how we are now registering the two concrete versions into the container so that they can be resolved later by the ToggleDispatcher registration:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> ConfigureServices(IServiceCollection services)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> toggleSource = <span style="color:#66d9ef">new</span> ToggleSource(<span style="color:#75715e">/* ... */</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    services.AddTransient&lt;HttpMessageDispatcher&gt;();
</span></span><span style="display:flex;"><span>    services.AddTransient&lt;QueueMessageDispatcher&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    services.AddTransient&lt;IMessageDispatcher&gt;(context =&gt; <span style="color:#66d9ef">new</span> ToggleDispatcher(
</span></span><span style="display:flex;"><span>        () =&gt; toggleSource.IsActive(Toggles.AsyncMessageDispatch),
</span></span><span style="display:flex;"><span>        context.GetService&lt;QueueMessageDispatcher&gt;(),
</span></span><span style="display:flex;"><span>        context.GetService&lt;HttpMessageDispatcher&gt;())
</span></span><span style="display:flex;"><span>    );
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="3-dynamicer-configuration">3. Dynamic(er) Configuration</h2>
<p>We can take this another step further too, if we want to be able to have a phased rollout of this new <code>QueueMessageDispatcher</code>, for example, based on the sender address.  In this case, we can create another decorator which uses the individual message to make the decision.  The only difference to the original <code>ToggleDispatcher</code> is that the first argument now also provides a <code>Message</code> object:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MessageBasedToggleDispatcher</span> : IMessageDispatcher
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Func&lt;Message, <span style="color:#66d9ef">bool</span>&gt; _isToggleActive;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IMessageDispatcher _queueSender;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IMessageDispatcher _httpSender;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> MessageBasedToggleDispatcher(Func&lt;Message, <span style="color:#66d9ef">bool</span>&gt; isToggleActive, IMessageDispatcher queueSender, IMessageDispatcher httpSender)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        _isToggleActive = isToggleActive;
</span></span><span style="display:flex;"><span>        _queueSender = queueSender;
</span></span><span style="display:flex;"><span>        _httpSender = httpSender;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Task&lt;SendResult&gt; Send(Message message)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> chosen = _isToggleActive(message)
</span></span><span style="display:flex;"><span>            ? _queueSender
</span></span><span style="display:flex;"><span>            : _httpSender;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> chosen.Send(message);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The startup registration is modified to pass the message property we care about to the <code>ToggleSource</code>, with the <code>toggleSource.IsActive()</code> call being responsible for what to do with the key we have passed in.  Perhaps it does something like a consistent hash of the address, and if the value is above a certain threshold the toggle is active, or maybe it queries a whitelist of people who the toggle is enabled for.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> ConfigureServices(IServiceCollection services)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> toggleSource = <span style="color:#66d9ef">new</span> ToggleSource(<span style="color:#75715e">/* ... */</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    services.AddTransient&lt;HttpMessageDispatcher&gt;();
</span></span><span style="display:flex;"><span>    services.AddTransient&lt;QueueMessageDispatcher&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    services.AddTransient&lt;IMessageDispatcher&gt;(context =&gt; <span style="color:#66d9ef">new</span> MessageBasedToggleDispatcher(
</span></span><span style="display:flex;"><span>        message =&gt; toggleSource.IsActive(Toggles.AsyncMessageDispatch, message.SenderAddress),
</span></span><span style="display:flex;"><span>        context.GetService&lt;QueueMessageDispatcher&gt;(),
</span></span><span style="display:flex;"><span>        context.GetService&lt;HttpMessageDispatcher&gt;())
</span></span><span style="display:flex;"><span>    );
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="conclusion">Conclusion</h2>
<p>This method of branching is extremly flexible, as it allows us to use toggles to replace feature implementations, but also gives us lots of places where we can add other decorators to add functionality to the pipeline.  For example, we could add an auditing decorator or one which implements the outbox pattern - and the calling code which depends only on <code>IMessageDispatcher</code> doesn&rsquo;t need to care.</p>
]]></content:encoded></item><item><title>Configuring Consul DNS Forwarding in Alpine Linux</title><link>https://andydote.co.uk/2019/05/31/consul-dns-forwarding-alpine/</link><pubDate>Fri, 31 May 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/05/31/consul-dns-forwarding-alpine/</guid><description>DEPRECATED - This has a race condition! Please see this post for an updated version which works!
Following on from the post the other day on setting up DNS forwarding to Consul with SystemD, I wanted also to show how to get Consul up and running under Alpine Linux, as it&amp;rsquo;s a little more awkward in some respects.
To start with, I am going to setup Consul as a service - I didn&amp;rsquo;t do this in the Ubuntu version, as there are plenty of useful articles about that already, but that is not the case with Alpine.</description><content:encoded><![CDATA[<h1 id="deprecated---this-has-a-race-condition">DEPRECATED - This has a race condition!</h1>
<p><a href="/2019/12/30/consul-alpine-dns-revisited/">Please see this post for an updated version which works!</a></p>
<p>Following on from the post the other day on setting up <a href="/2019/05/29/consul-dns-forwarding/">DNS forwarding to Consul with SystemD</a>, I wanted also to show how to get Consul up and running under <a href="https://www.alpinelinux.org/">Alpine Linux</a>, as it&rsquo;s a little more awkward in some respects.</p>
<p>To start with, I am going to setup Consul as a service - I didn&rsquo;t do this in the Ubuntu version, as there are plenty of useful articles about that already, but that is not the case with Alpine.</p>
<h2 id="run-consul">Run Consul</h2>
<p>First, we need to get a version of Consul and install it into our system.  This script downloads <code>1.5.1</code> from Hashicorp&rsquo;s releases site, installs it to <code>/usr/bin/consul</code>, and creates a <code>consul</code> user and group to run the daemon with:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>CONSUL_VERSION<span style="color:#f92672">=</span>1.5.1
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>curl -sSL https://releases.hashicorp.com/consul/<span style="color:#e6db74">${</span>CONSUL_VERSION<span style="color:#e6db74">}</span>/consul_<span style="color:#e6db74">${</span>CONSUL_VERSION<span style="color:#e6db74">}</span>_linux_amd64.zip -o /tmp/consul.zip
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>unzip /tmp/consul.zip
</span></span><span style="display:flex;"><span>sudo install consul /usr/bin/consul
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo addgroup -S consul
</span></span><span style="display:flex;"><span>sudo adduser -S -D -h /var/consul -s /sbin/nologin -G consul -g consul consul
</span></span></code></pre></div><p>Next, we need to create the directories for the configuration and data to live in, and copy the init script and configuration file to those directories:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>consul_dir<span style="color:#f92672">=</span>/etc/consul
</span></span><span style="display:flex;"><span>data_dir<span style="color:#f92672">=</span>/srv/consul
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo mkdir $consul_dir
</span></span><span style="display:flex;"><span>sudo mkdir $data_dir
</span></span><span style="display:flex;"><span>sudo chown consul:consul $data_dir
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo mv /tmp/consul.sh /etc/init.d/consul
</span></span><span style="display:flex;"><span>sudo chmod +x /etc/init.d/consul
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo mv /tmp/consul.json $consul_dir/consul.json
</span></span></code></pre></div><p>The init script is pretty straight forward, but note that I am running the agent in this example in <code>dev</code> mode; <strong>don&rsquo;t do this in production</strong>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#75715e">#!/sbin/openrc-run
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>CONSUL_LOG_FILE<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;/var/log/</span><span style="color:#e6db74">${</span>SVCNAME<span style="color:#e6db74">}</span><span style="color:#e6db74">.log&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>name<span style="color:#f92672">=</span>consul
</span></span><span style="display:flex;"><span>description<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;A tool for service discovery, monitoring and configuration&#34;</span>
</span></span><span style="display:flex;"><span>description_checkconfig<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Verify configuration file&#34;</span>
</span></span><span style="display:flex;"><span>daemon<span style="color:#f92672">=</span>/usr/bin/$name
</span></span><span style="display:flex;"><span>daemon_user<span style="color:#f92672">=</span>$name
</span></span><span style="display:flex;"><span>daemon_group<span style="color:#f92672">=</span>$name
</span></span><span style="display:flex;"><span>consul_dir<span style="color:#f92672">=</span>/etc/consul
</span></span><span style="display:flex;"><span>extra_commands<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;checkconfig&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>start_pre<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    checkpath -f -m <span style="color:#ae81ff">0644</span> -o <span style="color:#e6db74">${</span>SVCNAME<span style="color:#e6db74">}</span>:<span style="color:#e6db74">${</span>SVCNAME<span style="color:#e6db74">}</span> <span style="color:#e6db74">&#34;</span>$CONSUL_LOG_FILE<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>depend<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    need net
</span></span><span style="display:flex;"><span>    after firewall
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>checkconfig<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    consul validate $consul_dir
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>start<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    checkconfig <span style="color:#f92672">||</span> <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    ebegin <span style="color:#e6db74">&#34;Starting </span><span style="color:#e6db74">${</span>name<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>        start-stop-daemon --start --quiet <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>            -m --pidfile /var/run/<span style="color:#e6db74">${</span>name<span style="color:#e6db74">}</span>.pid <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>            --user <span style="color:#e6db74">${</span>daemon_user<span style="color:#e6db74">}</span> --group <span style="color:#e6db74">${</span>daemon_group<span style="color:#e6db74">}</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>            -b --stdout $CONSUL_LOG_FILE --stderr $CONSUL_LOG_FILE <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>            -k <span style="color:#ae81ff">027</span> --exec <span style="color:#e6db74">${</span>daemon<span style="color:#e6db74">}</span> -- agent -dev -config-dir<span style="color:#f92672">=</span>$consul_dir
</span></span><span style="display:flex;"><span>    eend $?
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>stop<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    ebegin <span style="color:#e6db74">&#34;Stopping </span><span style="color:#e6db74">${</span>name<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>        start-stop-daemon --stop --quiet <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>            --pidfile /var/run/<span style="color:#e6db74">${</span>name<span style="color:#e6db74">}</span>.pid <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>            --exec <span style="color:#e6db74">${</span>daemon<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    eend $?
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>Finally, a basic config file to launch consul is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;data_dir&#34;</span>: <span style="color:#e6db74">&#34;/srv/consul/data&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;client_addr&#34;</span>: <span style="color:#e6db74">&#34;0.0.0.0&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Now that all our scripts are in place, we can register Consul into the service manager, and start it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>sudo rc-update add consul
</span></span><span style="display:flex;"><span>sudo rc-service consul start
</span></span></code></pre></div><p>You can check consul is up and running by using <code>dig</code> to get the address of the consul service itself:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>dig @localhost -p <span style="color:#ae81ff">8600</span> consul.service.consul
</span></span></code></pre></div><h2 id="setup-local-dns-with-unbound">Setup Local DNS with Unbound</h2>
<p>Now that Consul is running, we need to configure a local DNS resolver to forward requests for the <code>.consul</code> domain to Consul.  We will use <a href="https://nlnetlabs.nl/projects/unbound/about/">Unbound</a> as it works nicely on Alpine.  It also has the wonderful feature of being able to send queries to a specific port, so no <code>iptables</code> rules needed this time!</p>
<p>The config file (<code>/etc/unbound/unbound.conf</code>) is all default values, with the exception of the last 5 lines, which let us forward DNS requests to a custom, and insecure, location:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#75715e">#! /bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>sudo apk add unbound
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>
</span></span><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt;-EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">server:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    verbosity: 1
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    root-hints: /etc/unbound/root.hints
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    trust-anchor-file: &#34;/usr/share/dnssec-root/trusted-key.key&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    do-not-query-localhost: no
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    domain-insecure: &#34;consul&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">stub-zone:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    name: &#34;consul&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    stub-addr: 127.0.0.1@8600
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">)</span> | sudo tee /etc/unbound/unbound.conf
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo rc-update add unbound
</span></span><span style="display:flex;"><span>sudo rc-service unbound start
</span></span></code></pre></div><p>We can validate this works again by using <code>dig</code>, but this time removing the port specification to hit <code>53</code> instead:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>dig @localhost consul.service.consul
</span></span></code></pre></div><h2 id="configure-dns-resolution">Configure DNS Resolution</h2>
<p>Finally, we need to update <code>/etc/resolv.conf</code> so that other system tools such as <code>ping</code> and <code>curl</code> can resolve <code>.consul</code> addresses.  This is a little more hassle on Alpine, as there are no <code>head</code> files we can push our nameserver entry into.  Instead, we use <code>dhclient</code> which will let us prepend a custom nameserver (or multiple) when the interface is brought up, even when using DHCP:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#75715e">#! /bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>sudo apk add dhclient
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>
</span></span><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt;-EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">send host-name = gethostname();
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">request subnet-mask, broadcast-address, time-offset, routers,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        domain-name, domain-name-servers, domain-search, host-name,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        dhcp6.name-servers, dhcp6.domain-search, dhcp6.fqdn, dhcp6.sntp-servers,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        netbios-name-servers, netbios-scope, interface-mtu,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        rfc3442-classless-static-routes, ntp-servers;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">prepend domain-name-servers 127.0.0.1;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">)</span> | sudo tee /etc/dhcp/dhclient.conf
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo rm /etc/resolv.conf <span style="color:#75715e"># hack due to it dhclient making an invalid `chown` call.</span>
</span></span><span style="display:flex;"><span>sudo rc-service networking restart
</span></span></code></pre></div><p>The only thing of interest here is the little hack: we delete the <code>/etc/resolv.conf</code> before restarting the networking service, as if you don&rsquo;t do this, you get errors about &ldquo;chmod invalid option resource=&hellip;&rdquo;.</p>
<p>We can varify everything works in the same way we did on Ubuntu; <code>curl</code> to both a <code>.consul</code> and a public address:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ curl -s -o /dev/null -w <span style="color:#e6db74">&#34;%{http_code}\n&#34;</span> http://consul.service.consul:8500/ui/
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">200</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>$ curl -s -o /dev/null -w <span style="color:#e6db74">&#34;%{http_code}\n&#34;</span> http://google.com
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">301</span>
</span></span></code></pre></div><h2 id="end">End</h2>
<p>This was a bit easier to get started with than the Ubuntu version as I knew what I was trying to accomplish this time - however making a good <code>init.d</code> script was a bit more hassle, and the error from <code>chmod</code> took some time to track down.</p>
]]></content:encoded></item><item><title>Configuring Consul DNS Forwarding in Ubuntu 16.04</title><link>https://andydote.co.uk/2019/05/29/consul-dns-forwarding/</link><pubDate>Wed, 29 May 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/05/29/consul-dns-forwarding/</guid><description>DEPRECATED - This doesn&amp;rsquo;t work properly Please see this post for an updated version which works!
One of the advantages of using Consul for service discovery is that besides an HTTP API, you can also query it by DNS.
The DNS server is listening on port 8600 by default, and you can query both A records or SRV records from it. SRV records are useful as they contain additional properties (priority, weight and port), and you can get multiple records back from a single query, letting you do load balancing client side:</description><content:encoded><![CDATA[<h1 id="deprecated---this-doesnt-work-properly">DEPRECATED - This doesn&rsquo;t work properly</h1>
<p><a href="/2019/09/24/consul-ubuntu-dns-revisited/">Please see this post for an updated version which works!</a></p>
<hr>
<p>One of the advantages of using <a href="https://www.consul.io/">Consul</a> for service discovery is that besides an HTTP API, you can also query it by DNS.</p>
<p>The DNS server is listening on port <code>8600</code> by default, and you can query both A records or SRV records from it.  <a href="https://en.wikipedia.org/wiki/SRV_record">SRV</a> records are useful as they contain additional properties (<code>priority</code>, <code>weight</code> and <code>port</code>), and you can get multiple records back from a single query, letting you do load balancing client side:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ dig @localhost -p <span style="color:#ae81ff">8600</span> consul.service.consul SRV +short
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span> <span style="color:#ae81ff">10</span> <span style="color:#ae81ff">8300</span> vagrant1.node.dc1.consul.
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span> <span style="color:#ae81ff">14</span> <span style="color:#ae81ff">8300</span> vagrant2.node.dc1.consul.
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span> <span style="color:#ae81ff">100</span> <span style="color:#ae81ff">8300</span> vagrant3.node.dc1.consul.
</span></span></code></pre></div><p>A Records are also useful, as it means we should be able to treat services registered to Consul like any other domain - but it doesn&rsquo;t work:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ curl http://consul.service.consul:8500
</span></span><span style="display:flex;"><span>curl: <span style="color:#f92672">(</span>6<span style="color:#f92672">)</span> Could not resolve host: consul.service.consul
</span></span></code></pre></div><p>The reason for this is that the system&rsquo;s built-in DNS resolver doesn&rsquo;t know how to query Consul.  We can, however, configure it to forward any <code>*.consul</code> requests to Consul.</p>
<h2 id="solution---forward-dns-queries-to-consul">Solution - Forward DNS queries to Consul</h2>
<p>As I usually target Ubuntu based machines, this means configuring <code>systemd-resolved</code> to forward to Consul.  However, we want to keep Consul listening on it&rsquo;s default port (<code>8600</code>), and <code>systemd-resolved</code> can only forward requests to port <code>53</code>, so we need also to configure <code>iptables</code> to redirect the requests.</p>
<p>The steps are as follows:</p>
<ol>
<li>Configure <code>systemd-resolved</code> to forward <code>.consul</code> TLD queries to the local consul agent</li>
<li>Configure <code>iptables</code> to redirect <code>53</code> to <code>8600</code></li>
</ol>
<p>So let&rsquo;s get to it!</p>
<h3 id="1-make-iptables-persistent">1. Make iptables persistent</h3>
<p>IPTables configuration changes don&rsquo;t persist through reboots, so the easiest way to solve this is with the <code>iptables-persistent</code> package.</p>
<p>Typically I am scripting machines (using [Packer] or [Vagrant]), so I configure the install to be non-interactive:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo iptables-persistent iptables-persistent/autosave_v4 boolean false | sudo debconf-set-selections
</span></span><span style="display:flex;"><span>echo iptables-persistent iptables-persistent/autosave_v6 boolean false | sudo debconf-set-selections
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo DEBIAN_FRONTEND<span style="color:#f92672">=</span>noninteractive apt install -yq iptables-persistent
</span></span></code></pre></div><h3 id="2-update-systemd-resolved">2. Update Systemd-Resolved</h3>
<p>The file to change is <code>/etc/systemd/resolved.conf</code>.  By default it looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-conf" data-lang="conf"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">[</span>Resolve<span style="color:#960050;background-color:#1e0010">]</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#DNS=
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#FallbackDNS=8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#Domains=
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#LLMNR=yes
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#DNSSEC=no
</span></span></span></code></pre></div><p>We need to change the <code>DNS</code> and <code>Domains</code> lines - either editing the file by hand, or scripting a replacement with <code>sed</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo sed -i <span style="color:#e6db74">&#39;s/#DNS=/DNS=127.0.0.1/g; s/#Domains=/Domains=~consul/g&#39;</span> /etc/systemd/resolved.conf
</span></span></code></pre></div><p>The result of which is the file now reading like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-conf" data-lang="conf"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">[</span>Resolve<span style="color:#960050;background-color:#1e0010">]</span>
</span></span><span style="display:flex;"><span>DNS<span style="color:#f92672">=</span><span style="color:#ae81ff">127.0.0.1</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#FallbackDNS=8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>Domains<span style="color:#f92672">=</span><span style="color:#960050;background-color:#1e0010">~</span>consul
</span></span><span style="display:flex;"><span><span style="color:#75715e">#LLMNR=yes
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#DNSSEC=no
</span></span></span></code></pre></div><p>By specifying the <code>Domains</code> as <code>~consul</code>, we are telling resolvd to forward requests for the <code>consul</code> TLD to the server specified in the <code>DNS</code> line.</p>
<h3 id="3-configure-resolvconf-too">3. Configure Resolvconf too</h3>
<p>For compatibility with some applications (e.g. <code>curl</code> and <code>ping</code>), we also need to update <code>/etc/resolv.conf</code> to specify our local nameserver.  You do this <strong>not</strong> by editing the file directly!</p>
<p>Instead, we need to add <code>nameserver 127.0.0.1</code> to <code>/etc/resolvconf/resolv.conf.d/head</code>.  Again, I will script this, and as we need <code>sudo</code> to write to the file, the easiest way is to use <code>tee</code> to append the line and then run <code>resolvconf -u</code> to apply the change:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;nameserver 127.0.0.1&#34;</span> | sudo tee --append /etc/resolvconf/resolv.conf.d/head
</span></span><span style="display:flex;"><span>sudo resolvconf -u
</span></span></code></pre></div><h3 id="configure-iptables">Configure iptables</h3>
<p>Finally, we need to configure iptables so that when <code>systemd-resolved</code> sends a DNS query to localhost on port <code>53</code>, it gets redirected to port <code>8600</code>.  We&rsquo;ll do this for both TCP and UDP requests, and then use <code>netfilter-persistent</code> to make the rules persistent:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo iptables -t nat -A OUTPUT -d localhost -p udp -m udp --dport <span style="color:#ae81ff">53</span> -j REDIRECT --to-ports <span style="color:#ae81ff">8600</span>
</span></span><span style="display:flex;"><span>sudo iptables -t nat -A OUTPUT -d localhost -p tcp -m tcp --dport <span style="color:#ae81ff">53</span> -j REDIRECT --to-ports <span style="color:#ae81ff">8600</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo netfilter-persistent save
</span></span></code></pre></div><h2 id="verification">Verification</h2>
<p>First, we can test that both Consul and Systemd-Resolved return an address for a consul service:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ dig @localhost -p <span style="color:#ae81ff">8600</span> consul.service.consul +short
</span></span><span style="display:flex;"><span>10.0.2.15
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>$ dig @localhost consul.service.consul +short
</span></span><span style="display:flex;"><span>10.0.2.15
</span></span></code></pre></div><p>And now we can try using <code>curl</code> to verify that we can resolve consul domains and normal domains still:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ curl -s -o /dev/null -w <span style="color:#e6db74">&#34;%{http_code}\n&#34;</span> http://consul.service.consul:8500/ui/
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">200</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>$ curl -s -o /dev/null -w <span style="color:#e6db74">&#34;%{http_code}\n&#34;</span> http://google.com
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">301</span>
</span></span></code></pre></div><h2 id="end">End</h2>
<p>There are also guides available on how to do this on <a href="https://learn.hashicorp.com/consul/security-networking/forwarding">Hashicorp&rsquo;s website</a>, covering other DNS resolvers too (such as BIND, Dnsmasq, Unbound).</p>
]]></content:encoded></item><item><title>Running a Secure RabbitMQ Cluster in Nomad</title><link>https://andydote.co.uk/2019/04/06/nomad-rabbitmq-secure/</link><pubDate>Sat, 06 Apr 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/04/06/nomad-rabbitmq-secure/</guid><description>Last time I wrote about running a RabbitMQ cluster in Nomad, one of the main pieces of feedback I received was about the (lack) of security of the setup, so I decided to revisit this, and write about how to launch as secure RabbitMQ node in Nomad.
The things I want to cover are:
Username and Password for the management UI Secure value for the Erlang Cookie SSL for Management and AMQP As usual, the demo repository with all the code is available if you&amp;rsquo;d rather just jump into that.</description><content:encoded><![CDATA[<p>Last time I wrote about running a RabbitMQ cluster in Nomad, one of the main pieces of feedback I received was about the (lack) of security of the setup, so I decided to revisit this, and write about how to launch as secure RabbitMQ node in Nomad.</p>
<p>The things I want to cover are:</p>
<ul>
<li>Username and Password for the management UI</li>
<li>Secure value for the Erlang Cookie</li>
<li>SSL for Management and AMQP</li>
</ul>
<p>As usual, the <a href="https://github.com/Pondidum/Nomad-RabbitMQ-Demo">demo repository</a> with all the code is available if you&rsquo;d rather just jump into that.</p>
<h2 id="configure-nomad-to-integrate-with-vault">Configure Nomad To Integrate With Vault</h2>
<p>To manage the certificates and credentials I will use another Hashicorp tool called <a href="https://vaultproject.io/">Vault</a>, which provides Secrets As A Service.  It can be configured for High Availability, but for the demo, we will just use a single instance on one of our Nomad machines.</p>
<h3 id="vault">Vault</h3>
<p>We&rsquo;ll update the Vagrant script used in the <a href="/2019/01/28/nomad-rabbitmq-consul-cluster/">last post about Nomad Rabbitmq Clustering</a> to add in a single Vault node.  <strong>This is not suitable for using Vault in production;</strong> for that there should be a separate Vault cluster running somewhere, but as this post is focusing on how to integrate with Vault, a single node will suffice.</p>
<p>Once we have Vault installed (<a href="https://github.com/Pondidum/Nomad-RabbitMQ-Demo/blob/master/provision.sh#L50">see the <code>provision.sh</code> script</a>), we need to set up a few parts.  First is a PKI (public key infrastructure), better known as a Certificate Authority (CA).  We will generate a single root certificate and have our client machines (and optionally the host machine) trust that one certificate.</p>
<p>As this the machines are running in Hyper-V with the Default Switch, we can use the inbuilt domain name, <code>mshome.net</code>, and provide our own certificates.  This script is run as part of the Server (<code>nomad1</code>) provisioning script, but in a production environment would be outside of this scope.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>domain<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;mshome.net&#34;</span>
</span></span><span style="display:flex;"><span>vault secrets enable pki
</span></span><span style="display:flex;"><span>vault secrets tune -max-lease-ttl<span style="color:#f92672">=</span>87600h pki
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault write -field<span style="color:#f92672">=</span>certificate pki/root/generate/internal common_name<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$domain<span style="color:#e6db74">&#34;</span> ttl<span style="color:#f92672">=</span>87600h <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    &gt; /vagrant/vault/mshome.crt
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault write pki/config/urls <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    issuing_certificates<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$VAULT_ADDR<span style="color:#e6db74">/v1/pki/ca&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    crl_distribution_points<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$VAULT_ADDR<span style="color:#e6db74">/v1/pki/crl&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault write pki/roles/rabbit <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    allowed_domains<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$domain<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    allow_subdomains<span style="color:#f92672">=</span>true <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    generate_lease<span style="color:#f92672">=</span>true <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    max_ttl<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;720h&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo cp /vagrant/vault/mshome.crt /usr/local/share/ca-certificates/mshome.crt
</span></span><span style="display:flex;"><span>sudo update-ca-certificates
</span></span></code></pre></div><p>If you don&rsquo;t want scary screens in FireFox and Chrome, you&rsquo;ll need to install the <code>mshome.crt</code> certificate into your trust store.</p>
<p>Next up, we have some policies we need in Vault.  The first deals with what the Nomad Server(s) are allowed to do - namely to handle tokens for itself, and anything in the <code>nomad-cluster</code> role.  <a href="https://github.com/Pondidum/Nomad-RabbitMQ-Demo/blob/master/vault/nomad-server-policy.hcl">A full commented version of this policy is available here</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>path <span style="color:#e6db74">&#34;auth/token/create/nomad-cluster&#34;</span> {
</span></span><span style="display:flex;"><span>  capabilities <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;update&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>path <span style="color:#e6db74">&#34;auth/token/roles/nomad-cluster&#34;</span> {
</span></span><span style="display:flex;"><span>  capabilities <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;read&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>path <span style="color:#e6db74">&#34;auth/token/lookup-self&#34;</span> {
</span></span><span style="display:flex;"><span>  capabilities <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;read&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>path <span style="color:#e6db74">&#34;auth/token/lookup&#34;</span> {
</span></span><span style="display:flex;"><span>  capabilities <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;update&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>path <span style="color:#e6db74">&#34;auth/token/revoke-accessor&#34;</span> {
</span></span><span style="display:flex;"><span>  capabilities <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;update&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>path <span style="color:#e6db74">&#34;sys/capabilities-self&#34;</span> {
</span></span><span style="display:flex;"><span>  capabilities <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;update&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>path <span style="color:#e6db74">&#34;auth/token/renew-self&#34;</span> {
</span></span><span style="display:flex;"><span>  capabilities <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;update&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As this policy mentions the <code>nomad-cluster</code> role a few times, let&rsquo;s have a look at that also:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;disallowed_policies&#34;</span>: <span style="color:#e6db74">&#34;nomad-server&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;explicit_max_ttl&#34;</span>: <span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;nomad-cluster&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;orphan&#34;</span>: <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;period&#34;</span>: <span style="color:#ae81ff">259200</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;renewable&#34;</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This allows a fairly long-lived token to be created, which can be renewed.  It is also limiting what the tokens are allowed to do, which can be done as either a block list (<code>disallowed_policies</code>) or an allow list (<code>allowed_policies</code>).  In this case, I am letting the Clients access any policies except the <code>nomad-server</code> policy.</p>
<p>We can install both of these into Vault:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault policy write nomad-server /vagrant/vault/nomad-server-policy.hcl
</span></span><span style="display:flex;"><span>vault write auth/token/roles/nomad-cluster @/vagrant/vault/nomad-cluster-role.json
</span></span></code></pre></div><h3 id="nomad">Nomad</h3>
<p>Now that Vault is up and running, we should configure Nomad to talk to it.  This is done in two places - the Server configuration, and the Client configuration.</p>
<p>To configure the <strong>Nomad Server</strong>, we update it&rsquo;s configuration file to include a <code>vault</code> block, which contains a role name it will use to generate tokens (for itself and for the Nomad Clients), and an initial token.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>vault {
</span></span><span style="display:flex;"><span>    enabled <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>    address <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http://localhost:8200&#34;</span>
</span></span><span style="display:flex;"><span>    task_token_ttl <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;1h&#34;</span>
</span></span><span style="display:flex;"><span>    create_from_role <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;nomad-cluster&#34;</span>
</span></span><span style="display:flex;"><span>    token <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;some_token_here&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The initial token is generated by the <a href="https://github.com/Pondidum/Nomad-RabbitMQ-Demo/blob/master/server.sh"><code>./server.sh</code></a> script - how you go about doing this in production will vary greatly depending on how you are managing your machines.</p>
<p>The <strong>Nomad Clients</strong> also need the Vault integration enabling, but in their case, it only needs the location of Vault, as the Server node(s) will provide tokens for the clients to use.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>vault {
</span></span><span style="display:flex;"><span>    enabled <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>    address <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http://nomad1.mshome.net:8200&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="job-requirements">Job Requirements</h2>
<p>Before we go about changing the job itself, we need to write some data into Vault for the job to use:</p>
<ul>
<li>Credentials: Username and password for the RabbitMQ Management UI, and the <code>RABBITMQ_ERLANG_COOKIE</code></li>
<li>A policy for the job allowing Certificate Generation and Credentials access</li>
</ul>
<h3 id="credentials">Credentials</h3>
<p>First off, we need to create a username and password to use with the Management UI.  This can be done via the Vault CLI:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault kv put secret/rabbit/admin <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    username<span style="color:#f92672">=</span>administrator <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    password<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>cat /proc/sys/kernel/random/uuid<span style="color:#66d9ef">)</span>
</span></span></code></pre></div><p>For the Erlang Cookie, we will also generate a Guid, but this time we will store it under a separate path in Vault so that it can be locked down separately to the admin username and password if needed:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault kv put secret/rabbit/cookie <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    cookie<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>cat /proc/sys/kernel/random/uuid<span style="color:#66d9ef">)</span>
</span></span></code></pre></div><h3 id="job-policy">Job Policy</h3>
<p>Following the principle of <a href="https://en.wikipedia.org/wiki/Principle_of_least_privilege">Least Privilege</a>, we will create a policy for our <code>rabbit</code> job which only allows certificates to be generated, and rabbit credentials to be read.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>path <span style="color:#e6db74">&#34;pki/issue/rabbit&#34;</span> {
</span></span><span style="display:flex;"><span>  capabilities <span style="color:#f92672">=</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;create&#34;</span>, <span style="color:#e6db74">&#34;read&#34;</span>, <span style="color:#e6db74">&#34;update&#34;</span>, <span style="color:#e6db74">&#34;delete&#34;</span>, <span style="color:#e6db74">&#34;list&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>path <span style="color:#e6db74">&#34;secret/data/rabbit/*&#34;</span> {
</span></span><span style="display:flex;"><span>  capabilities <span style="color:#f92672">=</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;read&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This is written into Vault in the same way as the other policies were:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault policy write rabbit /vagrant/vault/rabbit-policy.hcl
</span></span></code></pre></div><h2 id="rabbit-job-configuration">Rabbit Job Configuration</h2>
<p>The first thing we need to do to the job is specify what policies we want to use with Vault, and what to do when a token or credential expires:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>task <span style="color:#e6db74">&#34;rabbit&#34;</span> {
</span></span><span style="display:flex;"><span>  driver <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;docker&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  vault {
</span></span><span style="display:flex;"><span>    policies <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;default&#34;</span>, <span style="color:#e6db74">&#34;rabbit&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    change_mode <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;restart&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">#...</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="certificates">Certificates</h3>
<p>To configure RabbitMQ to use SSL, we need to provide it with values for 3 environment variables:</p>
<ul>
<li><code>RABBITMQ_SSL_CACERTFILE</code> - The CA certificate</li>
<li><code>RABBITMQ_SSL_CERTFILE</code> - The Certificate for RabbitMQ to use</li>
<li><code>RABBITMQ_SSL_KEYFILE</code> - the PrivateKey for the RabbitMQ certificate</li>
</ul>
<p>So let&rsquo;s add a <code>template</code> block to the job to generate and write out a certificate.  It&rsquo;s worth noting that <strong>line endings matter</strong>.  You either need your <code>.nomad</code> file to use LF line endings, or make the <code>template</code> a single line and use <code>\n</code> to add the correct line endings in.  I prefer to have the file with LF line endings.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>template <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  data <span style="color:#f92672">=</span> <span style="color:#e6db74">&lt;&lt;EOH
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">{{ $host := printf &#34;common_name=%s.mshome.net&#34; (env &#34;attr.unique.hostname&#34;) }}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">{{ with secret &#34;pki/issue/rabbit&#34; $host &#34;format=pem&#34; }}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">{{ .Data.certificate }}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">{{ .Data.private_key }}{{ end }}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOH</span>
</span></span><span style="display:flex;"><span>  destination <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;secrets/rabbit.pem&#34;</span>
</span></span><span style="display:flex;"><span>  change_mode <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;restart&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>As we want to use the Nomad node&rsquo;s hostname within the <code>common_name</code> parameter of the secret, we need to use a variable to fetch and format the value:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>{{ $host :<span style="color:#f92672">=</span> printf <span style="color:#e6db74">&#34;common_name=%s.mshome.net&#34;</span> (env <span style="color:#e6db74">&#34;attr.unique.hostname&#34;</span>) }}
</span></span></code></pre></div><p>This can then be used by the <code>with secret</code> block to fetch a certificate for the current host:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>{{ with secret <span style="color:#e6db74">&#34;pki/issue/rabbit&#34;</span> $host <span style="color:#e6db74">&#34;format=pem&#34;</span> }}
</span></span></code></pre></div><p>Now that we have a certificate in the <code>./secrets/</code> directory, we can add a couple of volume mounts to the container, and set the environment variables with the container paths to the certificates.  Note how the root certificate is coming from the <code>/vagrant</code> directory, not from Vault itself.  Depending on how you are provisioning your machines to trust your CA, you will have a different path here!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>config {
</span></span><span style="display:flex;"><span>  image <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;pondidum/rabbitmq:consul&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># ...</span>
</span></span><span style="display:flex;"><span>  volumes <span style="color:#f92672">=</span> <span style="color:#f92672">[</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/vagrant/vault/mshome.crt:/etc/ssl/certs/mshome.crt&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;secrets/rabbit.pem:/etc/ssl/certs/rabbit.pem&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;secrets/rabbit.pem:/tmp/rabbitmq-ssl/combined.pem&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>env {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">RABBITMQ_SSL_CACERTFILE</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/etc/ssl/certs/mshome.crt&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">RABBITMQ_SSL_CERTFILE</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/etc/ssl/certs/rabbit.pem&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">RABBITMQ_SSL_KEYFILE</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/etc/ssl/certs/rabbit.pem&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">#...</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>You should also notice that we are writing the <code>secrets/rabbit.pem</code> file into the container twice:  The second write is to a file in <code>/tmp</code> as a workaround for the <code>docker-entrypoint.sh</code> script.  If we don&rsquo;t create this file ourselves, the container script will create it by combining the <code>RABBITMQ_SSL_CERTFILE</code> file and <code>RABBITMQ_SSL_KEYFILE</code> file, which will result in an invalid certificate, and a nightmare to figure out&hellip;</p>
<p>If the Vault integration in Nomad could write a single generated secret to two separate files, we wouldn&rsquo;t need this workaround.  Alternatively, you could make a custom container with a customised startup script to deal with this for you.</p>
<p>You can see the version of this file with <a href="https://github.com/Pondidum/Nomad-RabbitMQ-Demo/blob/a588d7c2483c999b2fa0f47433403dfe1838fd50/rabbit/secure.nomad">only these changes here</a></p>
<h3 id="credentials-1">Credentials</h3>
<p>Now that we have things running with a certificate, it would be a great idea to start using the Erlang Cookie value and Management UI credentials we stored in Vault earlier.  This is a super easy change to support in the Nomad file - we need to add another <code>template</code> block, but this time set <code>env = true</code> which will instruct nomad that the key-values in the template should be loaded as environment variables:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>template <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    data <span style="color:#f92672">=</span> <span style="color:#e6db74">&lt;&lt;EOH
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    {{ with secret &#34;secret/data/rabbit/cookie&#34; }}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    RABBITMQ_ERLANG_COOKIE=&#34;{{ .Data.data.cookie }}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    {{ end }}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    {{ with secret &#34;secret/data/rabbit/admin&#34; }}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    RABBITMQ_DEFAULT_USER={{ .Data.data.username }}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    RABBITMQ_DEFAULT_PASS={{ .Data.data.password }}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    {{ end }}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOH</span>
</span></span><span style="display:flex;"><span>    destination <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;secrets/rabbit.env&#34;</span>
</span></span><span style="display:flex;"><span>    env <span style="color:#f92672">=</span> true
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>The complete nomad file with <a href="https://github.com/Pondidum/Nomad-RabbitMQ-Demo/blob/a78736cac3a93a43a96cbe84492089fca29d15e1/rabbit/secure.nomad">both certificates and credentials can be seen here</a>.</p>
<h2 id="running">Running!</h2>
<p>Now, all we need to do is start our new secure cluster:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>nomad job run rabbit/secure.nomad
</span></span></code></pre></div><h2 id="client-libraries">Client Libraries</h2>
<p>Now that you have a secure version of RabbitMQ running, there are some interesting things which can be done with the client libraries.  While you can just use the secure port, RabbitMQ also supports <a href="https://www.rabbitmq.com/ssl.html#peer-verification">Peer Verification</a>, which means that the client has to present a certificate for itself, and RabbitMQ will validate that both certificates are signed by a common CA.</p>
<p>This process can be controlled with two environment variables:</p>
<ul>
<li><code>RABBITMQ_SSL_VERIFY</code> set to either <code>verify_peer</code> or <code>verify_none</code></li>
<li><code>RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT</code> set to <code>true</code> to require client certificates, <code>false</code> to make them optional</li>
</ul>
<p>In .net land, if you are using MassTransit, the configuration looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> bus = Bus.Factory.CreateUsingRabbitMq(c =&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    c.UseSerilog(logger);
</span></span><span style="display:flex;"><span>    c.Host(<span style="color:#e6db74">&#34;rabbitmq://nomad1.mshome.net:5671&#34;</span>, r =&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        r.Username(<span style="color:#e6db74">&#34;some_application&#34;</span>);
</span></span><span style="display:flex;"><span>        r.Password(<span style="color:#e6db74">&#34;some_password&#34;</span>);
</span></span><span style="display:flex;"><span>        r.UseSsl(ssl =&gt;
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            ssl.CertificatePath = <span style="color:#e6db74">@&#34;secrets/app.crt&#34;</span>;
</span></span><span style="display:flex;"><span>        });
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>There are also lots of other interesting things you can do with SSL and RabbitMQ, such as using the certificate as authentication rather than needing a username and password per app.  But you should be generating your app credentials dynamically with Vault too&hellip;</p>
<h1 id="wrapping-up">Wrapping Up</h1>
<p>Finding all the small parts to make this work was quite a challenge.  The <a href="https://gitter.im/hashicorp-nomad/Lobby">Nomad gitter</a> was useful when trying to figure out the certificates issue, and being able to read the <a href="https://github.com/docker-library/rabbitmq/blob/4b2b11c59ee65c2a09616b163d4572559a86bb7b/3.7/alpine/docker-entrypoint.sh#L363">source code</a> of the Docker image for RabbitMQ was invaluable to making the Certificate work.</p>
<p>If anyone sees anything I&rsquo;ve done wrong, or could be improved, I&rsquo;m happy to hear it!</p>
]]></content:encoded></item><item><title>Hyper-V, Docker, and Networking Drama</title><link>https://andydote.co.uk/2019/03/22/hyperv-networking/</link><pubDate>Fri, 22 Mar 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/03/22/hyperv-networking/</guid><description>I had a major problem a few hours before giving my Nomad: Kubernetes Without the Complexity talk this morning: the demo stopped working.
Now, the first thing to note is the entire setup of the demo is scripted, and the scripts hadn&amp;rsquo;t changed. The only thing I had done was restart the machine, and now things were breaking.
The Symptoms A docker container started inside the guest VMs with a port mapped to the machine&amp;rsquo;s public IP wasn&amp;rsquo;t resolvable outside the host.</description><content:encoded><![CDATA[<p>I had a major problem a few hours before giving my <a href="https://andydote.co.uk/presentations/index.html?nomad">Nomad: Kubernetes Without the Complexity</a> talk this morning: the demo stopped working.</p>
<p>Now, the first thing to note is the entire setup of the demo <a href="https://github.com/pondidum/nomad-demo">is scripted</a>, and the scripts hadn&rsquo;t changed.  The only thing I had done was restart the machine, and now things were breaking.</p>
<h2 id="the-symptoms">The Symptoms</h2>
<p>A docker container started inside the guest VMs with a port mapped to the machine&rsquo;s public IP wasn&rsquo;t resolvable outside the host.</p>
<p>For example, using a machine based off the <code>bento/ubuntu-16.04</code> base box, provisioned with docker, running this from inside an SSH connection to the machine would work:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vagrant ssh
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># launch a container which can respond to a http get</span>
</span></span><span style="display:flex;"><span>docker run -d --rm -p 172.127.48.105:5000:5000 registry:latest
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># curl by public ip</span>
</span></span><span style="display:flex;"><span>curl http://172.127.48.105:5000 --silent -w <span style="color:#e6db74">&#34;%{http_code}&#34;</span>   <span style="color:#75715e"># 200</span>
</span></span></code></pre></div><p>But running the same <code>curl</code> command on the host would fail:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># container is still running</span>
</span></span><span style="display:flex;"><span>curl http://172.127.48.105:5000 --silent -w <span style="color:#e6db74">&#34;%{http_code}&#34;</span>   <span style="color:#75715e"># timeout</span>
</span></span></code></pre></div><h2 id="investigation">Investigation</h2>
<p>So it&rsquo;s 5 hours before the demo (thankfully it&rsquo;s not 10 minutes before), so let&rsquo;s start digging into what could be causing this.</p>
<h2 id="docker-networking">Docker Networking</h2>
<p>I also was searching for Nomad and Docker networking issues - as I figured I could change the Nomad job to bind the container to all interfaces (e.g. <code>-p 5000:5000</code>) instead of just the one IP.  <a href="https://github.com/hashicorp/nomad/issues/209#issuecomment-145313928">This reply</a> mentioned the <code>docker0</code> network, and when I checked the guest machines, I saw that this network is also in the <code>172.*</code> range.</p>
<p>So my guest machines had public addresses which happened to fall in the same range as a separate network adaptor on that machine.</p>
<h2 id="hyper-v-ip-addresses">Hyper-V IP Addresses</h2>
<p>While I was checking the Windows Firewall to see if anything was weird in there, I stumbled across a rule I&rsquo;d added to allow exposure of a NodeJS service from my host to Hyper-v guests (but not anywhere else).  I noticed that the IP range it defined was <code>192.168.*</code>, and I now had machines with <code>172.*</code> addresses.</p>
<p>So the IP address range for guest machines had changed.</p>
<h2 id="the-solution">The Solution</h2>
<p>Luckily, there is a straightforward solution to this:</p>
<p><strong>Reboot until you get the range you want</strong></p>
<p>Really.</p>
<p>The other solution is to use an External Switch in Hyper-V and bridge it with your host&rsquo;s internet connection, which doesn&rsquo;t really help me, as I am on a laptop, on different WiFi networks, and sometimes I use a thunderbolt based network adaptor too.  And having to update/rebuild machines on every network change would be an absolute pain.</p>
<p>So I rebooted — a lot.</p>
<p>So if anyone from Microsoft is reading this: Please let us configure the Default Switch.  Or have a way to recreate it without rebooting at least.</p>
]]></content:encoded></item><item><title>RabbitMQ clustering with Consul in Nomad</title><link>https://andydote.co.uk/2019/01/28/nomad-rabbitmq-consul-cluster/</link><pubDate>Mon, 28 Jan 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/01/28/nomad-rabbitmq-consul-cluster/</guid><description>Update If you want a secure version of this cluster, see Running a Secure RabbitMQ Cluster in Nomad.
RabbitMQ is the centre of a lot of micros service architectures, and while you can cluster it manually, it is a lot easier to use some of the auto clustering plugins, such as AWS (EC2), Consul, Etcd, or Kubernetes. As I like to use Nomad for container orchestration, I thought it would be a good idea to show how to cluster RabbitMQ when it is running in a Docker container, on an unknown host (i.</description><content:encoded><![CDATA[<p><strong>Update</strong> If you want a secure version of this cluster, see <a href="/2019/04/06/nomad-rabbitmq-secure/">Running a Secure RabbitMQ Cluster in Nomad</a>.</p>
<p>RabbitMQ is the centre of a lot of micros service architectures, and while you can cluster it manually, it is a lot easier to use some of the <a href="https://www.rabbitmq.com/clustering.html#cluster-formation-options">auto clustering plugins</a>, such as AWS (EC2), Consul, Etcd, or Kubernetes. As I like to use <a href="https://www.nomadproject.io/">Nomad</a> for container orchestration, I thought it would be a good idea to show how to cluster RabbitMQ when it is running in a Docker container, on an unknown host (i.e. one picked by Nomad.)</p>
<p>I ran into a few problems trying to get this working, but a lot of searching and some help from the <a href="https://groups.google.com/forum/#!forum/rabbitmq-users">RabbitMQ mailing list</a> (thanks Luke!) got me through all the issues, so hopefully, this will be easier next time and for other people too.</p>
<p>It is also worth noting that this is only going to be covering how to make a cluster work, not how to make it secure (setting up TLS etc.) for production usage.  There is a lot of <a href="https://www.rabbitmq.com/production-checklist.html#security-considerations">documentation on the RabbitMQ website</a> for further reading on this!</p>
<p>The full repository with all of the <a href="https://github.com/Pondidum/Nomad-RabbitMQ-Demo">demo code is available on my Github</a>.</p>
<h2 id="nomad-cluster">Nomad Cluster</h2>
<p>As this post is mostly about running RabbitMQ on Nomad, and not setting up Nomad, I&rsquo;ll give the basics here - the full scripts are in the repository, and linked below too.</p>
<p>Vagrant is used to create us a three node cluster.  As I use Hyper-V for VMs, I can&rsquo;t set static IPs from the Vagrant file, so I have used another Vagrant feature: triggers.</p>
<p>Triggers let us specify scripts to run after Vagrant actions, so in this case, we run a script after machine1 comes up which writes out it&rsquo;s IP to the <code>/vagrant</code> share.  The other machines can then read this same file to join the cluster:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">Vagrant</span><span style="color:#f92672">.</span>configure(<span style="color:#ae81ff">2</span>) <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>config<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>box <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;bento/ubuntu-16.04&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provision <span style="color:#e6db74">&#34;shell&#34;</span>, <span style="color:#e6db74">path</span>: <span style="color:#e6db74">&#34;./provision.sh&#34;</span>, <span style="color:#e6db74">privileged</span>: <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;n1&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>n1<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>    n1<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provision <span style="color:#e6db74">&#34;shell&#34;</span>, <span style="color:#e6db74">path</span>: <span style="color:#e6db74">&#34;./server.sh&#34;</span>, <span style="color:#e6db74">privileged</span>: <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    n1<span style="color:#f92672">.</span>trigger<span style="color:#f92672">.</span>after <span style="color:#e6db74">:up</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>trigger<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>      trigger<span style="color:#f92672">.</span>run_remote <span style="color:#f92672">=</span> { <span style="color:#e6db74">inline</span>: <span style="color:#e6db74">&#34;ip route get 1 | awk &#39;{print $NF;exit}&#39; &gt; /vagrant/server_ip&#34;</span> }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;n2&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>n2<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>    n2<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>hostname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;nomad2&#34;</span>
</span></span><span style="display:flex;"><span>    n2<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provision <span style="color:#e6db74">&#34;shell&#34;</span>, <span style="color:#e6db74">path</span>: <span style="color:#e6db74">&#34;./client.sh&#34;</span>, <span style="color:#e6db74">privileged</span>: <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>The <code>provision.sh</code> script downloads and installs both Consul and Nomad, and then the respective <code>server.sh</code> and <code>client.sh</code> scripts set up both services in the right ways.  The server machine also acts as a Nomad client, so that we don&rsquo;t need 4 VMs running.</p>
<p><a href="https://github.com/Pondidum/Nomad-RabbitMQ-Demo/blob/master/vagrantfile">VagrantFile</a>, <a href="https://github.com/Pondidum/Nomad-RabbitMQ-Demo/blob/master/provision.sh">provision.sh</a>, <a href="https://github.com/Pondidum/Nomad-RabbitMQ-Demo/blob/master/server.sh">server.sh</a>, <a href="https://github.com/Pondidum/Nomad-RabbitMQ-Demo/blob/master/client.sh">client.sh</a></p>
<p>All that remains to be done is <code>vagrant up</code>&hellip;and wait.  But while we&rsquo;re waiting for the machines to provision, let&rsquo;s have a look at RabbitMQ clustering, and how we&rsquo;ll define the job in Nomad.</p>
<h2 id="rabbitmq-cluster">RabbitMQ Cluster</h2>
<p>A few things to note about clustering RabbitMQ:</p>
<ul>
<li>All nodes must be listening on the same port for clustering (<code>4369</code> by default)</li>
<li>The <code>ERL_EPMD_PORT</code> variable doesn&rsquo;t work on <code>rabbitmq &lt; 3.7.9</code></li>
<li>The latest Docker image for rabbitmq is <code>3.7.8</code></li>
<li>The rabbit node names must be DNS resolvable</li>
<li>The <code>RABBITMQ_ERLANG_COOKIE</code> must have the same value</li>
</ul>
<p>The <code>rabbitmq_peer_discovery_consul</code> plugin we will use is shipped with RabbitMQ by default but is disabled.  The easiest way to get everything up and running is to create your own docker container, with the plugin enabled, and a small configuration file to set a few options:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-conf" data-lang="conf"><span style="display:flex;"><span>FROM rabbitmq<span style="color:#960050;background-color:#1e0010">:</span>management-alpine
</span></span><span style="display:flex;"><span>COPY rabbitmq.conf <span style="color:#960050;background-color:#1e0010">/</span>etc<span style="color:#960050;background-color:#1e0010">/</span>rabbitmq
</span></span><span style="display:flex;"><span>RUN rabbitmq-plugins enable --offline rabbitmq_peer_discovery_consul
</span></span></code></pre></div><p>The <code>rabbitmq.conf</code> only needs a few lines:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-conf" data-lang="conf"><span style="display:flex;"><span>cluster_formation.peer_discovery_backend <span style="color:#f92672">=</span> rabbit_peer_discovery_consul
</span></span><span style="display:flex;"><span>cluster_formation.consul.svc_addr_auto <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker build -t rabbitmq:consul .
</span></span></code></pre></div><p>An image built from this is also available on <a href="https://hub.docker.com/r/pondidum/rabbitmq">docker hub</a>.</p>
<p>Once we have a custom container built, it&rsquo;s a good idea to test that it actually works, before we start trying to get Nomad to run it.  We&rsquo;ll do this by creating a network in Docker so that all the containers can talk directly to each other on their pre-defined ports.  Don&rsquo;t forget to change <code>CONSUL_HOST</code> to your machine&rsquo;s IP address!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker network create rabbit
</span></span><span style="display:flex;"><span>docker run -d --rm --name consul -p 8500:8500 consul
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker run -d --rm --name rabbit1 -h rabbit1 --network rabbit -p 30001:15672 -e RABBITMQ_ERLANG_COOKIE<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;rabbit&#39;</span> -e <span style="color:#e6db74">&#39;RABBITMQ_DEFAULT_USER=test&#39;</span> -e <span style="color:#e6db74">&#39;RABBITMQ_DEFAULT_PASS=test&#39;</span> -e CONSUL_HOST<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;10.0.75.1&#39;</span> rabbitmq:consul
</span></span><span style="display:flex;"><span>docker run -d --rm --name rabbit2 -h rabbit2 --network rabbit -p 30002:15672 -e RABBITMQ_ERLANG_COOKIE<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;rabbit&#39;</span> -e <span style="color:#e6db74">&#39;RABBITMQ_DEFAULT_USER=test&#39;</span> -e <span style="color:#e6db74">&#39;RABBITMQ_DEFAULT_PASS=test&#39;</span> -e CONSUL_HOST<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;10.0.75.1&#39;</span> rabbitmq:consul
</span></span><span style="display:flex;"><span>docker run -d --rm --name rabbit3 -h rabbit3 --network rabbit -p 30003:15672 -e RABBITMQ_ERLANG_COOKIE<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;rabbit&#39;</span> -e <span style="color:#e6db74">&#39;RABBITMQ_DEFAULT_USER=test&#39;</span> -e <span style="color:#e6db74">&#39;RABBITMQ_DEFAULT_PASS=test&#39;</span> -e CONSUL_HOST<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;10.0.75.1&#39;</span> rabbitmq:consul
</span></span></code></pre></div><p>You can now visit <code>http://localhost:30001</code> (or <code>30002</code> or <code>30003</code>) and see that we have a successful cluster running.  Once you&rsquo;re happy with it, you can kill it all off (as we started the containers with the <code>--rm</code> flag, Docker will delete them for us when they stop):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker stop rabbit1 rabbit2 rabbit3 consul
</span></span><span style="display:flex;"><span>docker network rm rabbit
</span></span></code></pre></div><h2 id="nomad-rabbit-job">Nomad Rabbit Job</h2>
<p>Now that we know our container clusters successfully, we can create a Job definition to do the same thing in Nomad.  Nomad jobs are defined in HCL, a Json-like configuration language.</p>
<p>The jobs require a name, which datacentre it should run in, and what kind of job type it is.  In this case, our job is called <code>rabbit</code> (imaginative I know), we&rsquo;ll run it in <code>dc1</code> (the default value Nomad starts with), and we&rsquo;ll make this job be a <code>service</code>, as opposed to a <code>batch</code> or <code>system</code> job:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>job <span style="color:#e6db74">&#34;rabbit&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  datacenters <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;dc1&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>  type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;service&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  group <span style="color:#e6db74">&#34;cluster&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># tasks ...</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>The <code>group</code> is used to hold a collection of <code>task</code>s, and when allocating a job, Nomad will make sure that all tasks belonging to an instance of a group are on the same node.</p>
<p>So for example, if you had a 2 node Nomad cluster, and 3 instances of a group which contained 3 tasks (e.g. API, varnish, and nginx containers), Nomad might distribute the groups like so:</p>
<p><img loading="lazy" src="nomad-allocation.png" alt="image of several nodes with groups of containers"  />
</p>
<p>Within the group, we can specify the number of instances we want with the <code>count</code> property, and we also specify that for both updates and migrations, only one group can be changed at a time.  This means that if you decide to upgrade the container used by the job, Nomad won&rsquo;t stop all instances at once, destroying your service&rsquo;s availability!</p>
<p>We also specify that we want to use the health checks (defined later on) rather than the state of the task itself to determine what is healthy, and how long the task must be healthy for before we decide it&rsquo;s actually healthy, and how long it has to achieve being healthy.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>group <span style="color:#e6db74">&#34;cluster&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  count <span style="color:#f92672">=</span> <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  update <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    max_parallel <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  migrate <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    max_parallel <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>    health_check <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;checks&#34;</span>
</span></span><span style="display:flex;"><span>    min_healthy_time <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;5s&#34;</span>
</span></span><span style="display:flex;"><span>    healthy_deadline <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;30s&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>The <code>task</code> is our unit of work in Nomad.  In this case, we are using the <code>docker</code> driver, but it also <a href="https://www.nomadproject.io/docs/drivers/index.html">supports many other drivers</a> including <code>exec</code>, <code>rkt</code> and <code>lxc</code>.  We configure which image to use, and importantly that the <code>hostname</code> is the name from Nomad!</p>
<p>The <code>port_map</code> tells nomad which ports of the container we want to expose, and labels them.  We can then refer to the ports by their labels in other parts of the configuration.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>task <span style="color:#e6db74">&#34;rabbit&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  driver <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;docker&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    image <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;pondidum/rabbitmq:consul&#34;</span>
</span></span><span style="display:flex;"><span>    hostname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>attr.unique.hostname<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    port_map <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>      amqp <span style="color:#f92672">=</span> <span style="color:#ae81ff">5672</span>
</span></span><span style="display:flex;"><span>      ui <span style="color:#f92672">=</span> <span style="color:#ae81ff">15672</span>
</span></span><span style="display:flex;"><span>      epmd <span style="color:#f92672">=</span> <span style="color:#ae81ff">4369</span>
</span></span><span style="display:flex;"><span>      clustering <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>The <code>env</code> section is pretty self-explanatory; they are environment variables to pass to the container.  As Consul is running on the Nomad host, we use the Nomad interpolation attribute to specify the IP of the current host, and we also set the <code>RABBITMQ_ERLANG_COOKIE</code> to a specific value.  In a production environment, you should be setting this value to something unguessable, possibly using the <a href="https://www.nomadproject.io/docs/job-specification/vault.html">Vault intergration</a> in Nomad to fetch a token.  We can also add other settings to pass to the container here, such as <code>RABBITMQ_DEFAULT_USER</code> and <code>RABBITMQ_DEFAULT_PASS</code>.  As with the cookie generation, in a production-like environment, you&rsquo;d probably want to use the Vault integration to pull the values for these variables.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>env <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  RABBITMQ_ERLANG_COOKIE <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;rabbitmq&#34;</span>
</span></span><span style="display:flex;"><span>  CONSUL_HOST <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>attr.unique.network.ip-address<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>The <code>resources</code> section lets us constraints on things like CPU, Memory, IOPs, and Network.  In our case, we are only specifying a set of ports to expose on the network, and that we want them to be bound to specific ports on the host:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>resources <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  network <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    port <span style="color:#e6db74">&#34;amqp&#34;</span> <span style="color:#f92672">{</span> static <span style="color:#f92672">=</span> <span style="color:#ae81ff">5672</span> <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>    port <span style="color:#e6db74">&#34;ui&#34;</span> <span style="color:#f92672">{</span> static <span style="color:#f92672">=</span> <span style="color:#ae81ff">15672</span> <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>    port <span style="color:#e6db74">&#34;epmd&#34;</span> <span style="color:#f92672">{</span> static <span style="color:#f92672">=</span> <span style="color:#ae81ff">4369</span> <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>    port <span style="color:#e6db74">&#34;clustering&#34;</span> <span style="color:#f92672">{</span> static <span style="color:#f92672">=</span> <span style="color:#ae81ff">25672</span> <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>We could select different ports to bind the container ports to, or leave out the <code>static</code> pair entirely to have Nomad map the ports to random unused ports on the host.</p>
<p>Finally, the <code>service</code> block integrates with service discovery (so, Consul), and allows us to register ports and health checks for our service.  In the case of our RabbitMQ cluster, we already have service discovery integration via the RabbitMQ Consul plugin, so this registration is only used for the <code>check</code> feature, which is what will also be used by the <code>migrate</code> block to see if a task is healthy:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>service <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  check <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    name     <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;alive&#34;</span>
</span></span><span style="display:flex;"><span>    type     <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;tcp&#34;</span>
</span></span><span style="display:flex;"><span>    port     <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;ui&#34;</span>
</span></span><span style="display:flex;"><span>    interval <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;10s&#34;</span>
</span></span><span style="display:flex;"><span>    timeout  <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;2s&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>The check is using the <code>ui</code> port defined earlier to check if the UI is alive.  We could also change the health check to use the <code>amqp</code> port instead, as that might be a better indication that the actual service can do useful things.  We can define multiple checks, and are not limited to TCP; <code>grpc</code>, <code>http</code>, and <code>script</code> are also supported.</p>
<p>The entire job definition is below, and is <a href="https://github.com/Pondidum/Nomad-RabbitMQ-Demo/blob/master/rabbit/rabbit.nomad">also available in the repository</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>job <span style="color:#e6db74">&#34;rabbit&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  datacenters <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;dc1&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>  type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;service&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  group <span style="color:#e6db74">&#34;cluster&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    count <span style="color:#f92672">=</span> <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    update <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>      max_parallel <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    migrate <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>      max_parallel <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>      health_check <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;checks&#34;</span>
</span></span><span style="display:flex;"><span>      min_healthy_time <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;5s&#34;</span>
</span></span><span style="display:flex;"><span>      healthy_deadline <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;30s&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    task <span style="color:#e6db74">&#34;rabbit&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>      driver <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;docker&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      config <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>        image <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;pondidum/rabbitmq:consul&#34;</span>
</span></span><span style="display:flex;"><span>        hostname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>attr.unique.hostname<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>        port_map <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>          amqp <span style="color:#f92672">=</span> <span style="color:#ae81ff">5672</span>
</span></span><span style="display:flex;"><span>          ui <span style="color:#f92672">=</span> <span style="color:#ae81ff">15672</span>
</span></span><span style="display:flex;"><span>          epmd <span style="color:#f92672">=</span> <span style="color:#ae81ff">4369</span>
</span></span><span style="display:flex;"><span>          clustering <span style="color:#f92672">=</span> <span style="color:#ae81ff">25672</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      env <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>        RABBITMQ_ERLANG_COOKIE <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;generate_a_guid_-_or_something_for_this&#34;</span>
</span></span><span style="display:flex;"><span>        RABBITMQ_DEFAULT_USER <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;test&#34;</span>
</span></span><span style="display:flex;"><span>        RABBITMQ_DEFAULT_PASS <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;test&#34;</span>
</span></span><span style="display:flex;"><span>        CONSUL_HOST <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>attr.unique.network.ip-address<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      resources <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>        network <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>          port <span style="color:#e6db74">&#34;amqp&#34;</span> <span style="color:#f92672">{</span> static <span style="color:#f92672">=</span> <span style="color:#ae81ff">5672</span> <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>          port <span style="color:#e6db74">&#34;ui&#34;</span> <span style="color:#f92672">{</span> static <span style="color:#f92672">=</span> <span style="color:#ae81ff">15672</span> <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>          port <span style="color:#e6db74">&#34;epmd&#34;</span> <span style="color:#f92672">{</span> static <span style="color:#f92672">=</span> <span style="color:#ae81ff">4369</span> <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>          port <span style="color:#e6db74">&#34;clustering&#34;</span> <span style="color:#f92672">{</span> static <span style="color:#f92672">=</span> <span style="color:#ae81ff">25672</span> <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      service <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>        name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;rabbitmq&#34;</span>
</span></span><span style="display:flex;"><span>        port <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;ui&#34;</span>
</span></span><span style="display:flex;"><span>        check <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>          name     <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;alive&#34;</span>
</span></span><span style="display:flex;"><span>          type     <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;tcp&#34;</span>
</span></span><span style="display:flex;"><span>          interval <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;10s&#34;</span>
</span></span><span style="display:flex;"><span>          timeout  <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;2s&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><h2 id="running-the-job">Running The Job</h2>
<p>First, make sure your console can talk to Nomad, which we can do by using the <code>server_ip</code> file again:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export NOMAD_ADDR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://</span><span style="color:#66d9ef">$(</span>cat server_ip<span style="color:#66d9ef">)</span><span style="color:#e6db74">:4646&#34;</span>
</span></span></code></pre></div><p>Now it should be possible to run the job:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>nomad job run rabbit/rabbit.nomad
</span></span></code></pre></div><p>After a few moments, we can visit any of the Nomad hosts, and log in to the RabbitMQ UI (<code>http://SOME_SERVER_IP:15672</code>) and you should be greeted with a running cluster with three nodes:</p>
<p><img loading="lazy" src="rabbitmq-cluster.png" alt="rabbitmq cluster dashboard"  />
</p>
<h2 id="homework">Homework</h2>
<ul>
<li>Kill a container on one of the nodes and see what happens (<code>vagrant ssh n2</code> then <code>docker stop &lt;SOME_CONTAINER_ID&gt;</code>)</li>
<li>Create an Application which you deploy to Nomad which uses service discovery to talk to RabbitMQ</li>
<li>Create some more Nomad clients, and try making a bigger RabbitMQ cluster</li>
</ul>
<p>If you have any questions, feel free to comment below or <a href="https://twitter.com/pondidum">send me a tweet</a>.</p>
]]></content:encoded></item><item><title>Testing Immutable Infrastructure</title><link>https://andydote.co.uk/2019/01/01/immutable-infra/</link><pubDate>Tue, 01 Jan 2019 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2019/01/01/immutable-infra/</guid><description>In my previous post, I glossed over one of the most important and useful parts of Immutable Infrastructure: Testability. There are many kinds of tests we can write for our infrastructure, but they should all be focused on the machine/service and maybe it&amp;rsquo;s nearest dependencies, not the entire system.
While this post focuses on testing a full machine (both locally in a VM, and remotely as an Amazon EC2 instance), it is also possible to do most of the same kind of tests against a Docker container.</description><content:encoded><![CDATA[<p>In my <a href="/2018/12/22/serilog-elk-jaeger/">previous post</a>, I glossed over one of the most important and useful parts of Immutable Infrastructure: Testability.  There are many kinds of tests we can write for our infrastructure, but they should all be focused on the machine/service and <em>maybe</em> it&rsquo;s nearest dependencies, <a href="https://medium.com/@copyconstruct/testing-microservices-the-sane-way-9bb31d158c16">not the entire system</a>.</p>
<p>While this post focuses on testing a full machine (both locally in a VM, and remotely as an Amazon EC2 instance), it is also possible to do most of the same kind of tests against a Docker container.  In fact, one of the tools used in this post supports building Docker containers as an output in parallel to the AMIs, so this can also assist in providing a migration path to/from Docker.</p>
<p>As an example, I will show how I built and tested a LogStash machine, including how to verify that the script to create the production machine is valid, that the machine itself has been provisioned correctly, and that the services inside work as expected.</p>
<p>I have <a href="https://github.com/Pondidum/immutable-infra-testing-demo">published all the source code</a> to GitHub.  The examples in this post are all taken from the repository but might have a few bits removed just for readability.  Check the full source out if you are interested!</p>
<h2 id="repository-structure-and-tools">Repository Structure and Tools</h2>
<p>When it comes to building anything that you will have lots of, consistency is key to making it manageable.  To that end, I have a small selection of tools that I use, and a repository structure I try and stick to.  They are the following:</p>
<p><strong><a href="https://www.vagrantup.com/">Vagrant</a></strong> - This is a tool for building and managing virtual machines.  It can be backed by many different <a href="https://www.vagrantup.com/docs/providers/">providers</a> such as Docker, HyperV and VirtualBox.  We&rsquo;ll use this to build a local Linux machine to develop and test LogStash in.  I use the HyperV provisioner, as that is what Docker For Windows also uses, and HyperV disables other virtualisation tools.</p>
<p><strong><a href="https://packer.io/">Packer</a></strong> - This tool provides a way to build machine images.  Where Vagrant builds running machines, Packer builds the base images for you to boot, and can build multiple different ones (in parallel) from one configuration.  We&rsquo;ll use this to create our AMIs (Amazon Machine Images.)</p>
<p><strong><a href="http://jestjs.io/">Jest</a></strong> - This is a testing framework written in (and for) NodeJS applications.  Whatever testing tool works best for your environment is what you should be using, but I use Jest as it introduces minimal dependencies, is cross-platform, and has some useful libraries for doing things like diffing json.</p>
<p>The repository structure is pretty simple:</p>
<ul>
<li>scripts/</li>
<li>src/</li>
<li>test/</li>
<li>build.sh</li>
<li>logstash.json</li>
<li>package.json</li>
<li>vagrantfile</li>
</ul>
<p>The <code>src</code> directory is where our application code will live.  If the application is compiled, the output goes to the <code>build</code> directory (which is not tracked in source-control.)  The <code>test</code> directory will contain all of our tests, and the <code>scripts</code> directory will contain everything needed for provisioning our machines.</p>
<p>We&rsquo;ll describe what the use of each of these files is as we go through the next section.</p>
<h2 id="local-development">Local Development</h2>
<p>To create our virtual machine locally, we will use <a href="https://www.vagrantup.com">Vagrant</a>.  To tell Vagrant how to build our machine, we need to create a <code>vagrantfile</code> in our repository, which will contain the machine details and provisioning steps.</p>
<p>The machine itself has a name, CPU count, and memory specified.  There is also a setting for Hyper-V which allows us to use a differencing disk, which reduces the startup time for the VM, and how much disk space it uses on the host machine.</p>
<p>For provisioning, we specify to run the relevant two files from the <code>scripts</code> directory.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">Vagrant</span><span style="color:#f92672">.</span>configure(<span style="color:#e6db74">&#34;2&#34;</span>) <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>config<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>    config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>box <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;bento/ubuntu-16.04&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provider <span style="color:#e6db74">&#34;hyperv&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>hv<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>        hv<span style="color:#f92672">.</span>vmname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;LogStash&#34;</span>
</span></span><span style="display:flex;"><span>        hv<span style="color:#f92672">.</span>cpus <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>        hv<span style="color:#f92672">.</span>memory <span style="color:#f92672">=</span> <span style="color:#ae81ff">2048</span>
</span></span><span style="display:flex;"><span>        hv<span style="color:#f92672">.</span>linked_clone <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provision <span style="color:#e6db74">&#34;shell&#34;</span>, <span style="color:#e6db74">path</span>: <span style="color:#e6db74">&#34;./scripts/provision.sh&#34;</span>
</span></span><span style="display:flex;"><span>    config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provision <span style="color:#e6db74">&#34;shell&#34;</span>, <span style="color:#e6db74">path</span>: <span style="color:#e6db74">&#34;./scripts/vagrant.sh&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>To keep things as similar as possible between our development machine and our output AMI, I keep as much of the setup script in one file: <code>scripts/provision.sh</code>.  In the case of our LogStash setup, this means installing Java, LogStash, some LogStash plugins, and enabling the service on reboots:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#! /bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># add elastic&#39;s package repository</span>
</span></span><span style="display:flex;"><span>wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;deb https://artifacts.elastic.co/packages/6.x/apt stable main&#34;</span> | sudo tee -a /etc/apt/sources.list.d/elastic-6.x.list
</span></span><span style="display:flex;"><span>sudo apt-get update
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># install openjdk and set environment variable</span>
</span></span><span style="display:flex;"><span>sudo apt-get install openjdk-8-jre -y
</span></span><span style="display:flex;"><span>JAVA<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>readlink -f <span style="color:#66d9ef">$(</span>which java<span style="color:#66d9ef">)</span> | sed <span style="color:#e6db74">&#34;s:bin/java::&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;JAVA_HOME=</span>$JAVA<span style="color:#e6db74">&#34;</span> | sudo tee --append /etc/environment
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#install logstash and plugins</span>
</span></span><span style="display:flex;"><span>sudo apt-get install logstash -y
</span></span><span style="display:flex;"><span>/usr/share/logstash/bin/logstash-plugin install logstash-filter-uuid
</span></span><span style="display:flex;"><span>/usr/share/logstash/bin/logstash-plugin install logstash-filter-prune
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo systemctl enable logstash.service
</span></span></code></pre></div><p>Vagrant will automatically mount it&rsquo;s working directory into the VM under the path <code>/vagrant</code>.  This means we can add a second provisioning script (<code>scripts/vagrant.sh</code>) to link the <code>/vagrant/src</code> directory to the LogStash configuration directory (<code>/etc/logstash/conf.d</code>), meaning we can edit the files on the host machine, and then restart LogStash to pick up the changes.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#! /bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>sudo rm -rf /etc/logstash/conf.d
</span></span><span style="display:flex;"><span>sudo ln -s /vagrant/src /etc/logstash/conf.d
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo systemctl start logstash.service
</span></span></code></pre></div><p>Now that we have a <code>vagrantfile</code>, we can start the virtual machine with a single command.  Note, Hyper-V requires administrator privileges, so you need to run this command in an admin terminal:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vagrant up
</span></span></code></pre></div><p>After a while, your new LogStash machine will be up and running.  If you want to log into the machine and check files an processes etc., you can run the following command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vagrant ssh
</span></span></code></pre></div><p>An argument can also be provided to the <code>ssh</code> command to be executed inside the VM, which is how I usually trigger LogStash restarts (as it doesn&rsquo;t seem to detect when I save the config files in the <code>src</code> directory):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vagrant ssh -c <span style="color:#e6db74">&#39;sudo systemctl restart logstash&#39;</span>
</span></span></code></pre></div><h2 id="deployment">Deployment</h2>
<p>To create the deployable machine image, I use Packer.  The process is very similar to how Vagrant is used: select a base AMI, create a new EC2 machine, provision it, and save the result as a new AMI.</p>
<p>Packer is configured with a single json file, in this case, named <code>logstash.json</code>.  The file is split into four parts: <code>variables</code>, <code>builders</code>, <code>provisioners</code>, and <code>outputs</code>.  I won&rsquo;t include the <code>outputs</code> section as it&rsquo;s not needed when building AMIs.</p>
<h3 id="variables">Variables</h3>
<p>The <code>variables</code> property is for all configuration that you can pass to Packer.  Their values can come from Environment Variables, CLI parameters, Consul, Vault, <a href="https://www.packer.io/docs/templates/user-variables.html">and others</a>.  In the LogStash example, there are three variables:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;variables&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;aws_access_key&#34;</span>: <span style="color:#e6db74">&#34;&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;aws_secret_key&#34;</span>: <span style="color:#e6db74">&#34;&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;ami_users&#34;</span>: <span style="color:#e6db74">&#34;{{env `AMI_ACCOUNTS`}}&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>aws_access_key</code> and <code>aws_secret_key</code> are known names - unless we specify some value, they will automatically be read from your AWS config (in <code>~/.aws/</code>), or if running on EC2, from the EC2 machine profile.</p>
<p>The <code>ami_users</code> is a custom variable which will read the <code>AMI_ACCOUNTS</code> environment variable by default.  This particular one is used so that I can grant access to the resulting AMI to multiple AWS accounts, which is useful if you&rsquo;re running in an Organisation with multiple Accounts.  For example, if the AMI is built in a <code>common</code> account, and will be deployed into <code>dev</code>, <code>qa</code> and <code>prod</code> accounts, then you would populate the <code>AMI_ACCOUNTS</code> as a CSV of account IDs.</p>
<h3 id="builders">Builders</h3>
<p>Packer can build <a href="https://www.packer.io/docs/builders/index.html">many different kinds</a> of machine image, but for this, we only need one: <code>amazon-ebs</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;builders&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;amazon-ebs&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;access_key&#34;</span>: <span style="color:#e6db74">&#34;{{user `aws_access_key`}}&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;secret_key&#34;</span>: <span style="color:#e6db74">&#34;{{user `aws_secret_key`}}&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;region&#34;</span>: <span style="color:#e6db74">&#34;eu-west-1&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;instance_type&#34;</span>: <span style="color:#e6db74">&#34;t2.micro&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;source_ami_filter&#34;</span>: {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;filters&#34;</span>: {
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;virtualization-type&#34;</span>: <span style="color:#e6db74">&#34;hvm&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;root-device-type&#34;</span>: <span style="color:#e6db74">&#34;ebs&#34;</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;owners&#34;</span>: [<span style="color:#e6db74">&#34;099720109477&#34;</span>],
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;most_recent&#34;</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>      },
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;ssh_username&#34;</span>: <span style="color:#e6db74">&#34;ubuntu&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;ami_name&#34;</span>: <span style="color:#e6db74">&#34;logstash {{timestamp}}&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;ami_users&#34;</span>: <span style="color:#e6db74">&#34;{{user `ami_users`}}&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The two most interesting properties of this are <code>source_ami_filter</code> and <code>ami_users</code>.  The <code>source_ami_filter</code> works in a very similar manner to the AWS CLI&rsquo;s <code>describe-images</code> <code>--filters</code> parameter, albeit in a more readable format.  In this case, I am specifying that I want an <code>ubuntu-xenial</code> base, and I want it to be an official Canonical image, so specify their Account ID as the <code>owner</code>.  I also specify the <code>most_recent</code> property, as this filter will return all versions of this AMI which Canonical publish.</p>
<p>The <code>ami_users</code> is what lets me grant access to the AMI from other accounts (rather than just making it public).  The property&rsquo;s value should be an array, but Packer is smart enough to expand the CSV in the user variable into an array for us.</p>
<h3 id="provisioners">Provisioners</h3>
<p>The <code>provisioners</code> array items are executed in the order they are specified.  To set up the machine, I use the <code>shell</code> provisioner to create a temporary directory, then the <code>file</code> provisioner to upload the files in the <code>src</code> directory to that temporary directory.  Finally a second <code>shell</code> provisioner uploads and runs the <code>scripts/provision.sh</code> and <code>scripts/aws.sh</code> files.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;provisioners&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;shell&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;inline&#34;</span>: <span style="color:#e6db74">&#34;mkdir -p /tmp/src&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;file&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;source&#34;</span>: <span style="color:#e6db74">&#34;./src/&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;destination&#34;</span>: <span style="color:#e6db74">&#34;/tmp/src&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;shell&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;scripts&#34;</span>: [<span style="color:#e6db74">&#34;./scripts/provision.sh&#34;</span>, <span style="color:#e6db74">&#34;./scripts/aws.sh&#34;</span>]
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>aws.sh</code> file is very small and does roughly the same thing as the <code>vagrant.sh</code> script, but rather than symlinking the <code>/vagrant</code> directory, it moves the uploaded <code>src</code> directory into the right location for LogStash:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#! /bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>sudo rm /etc/logstash/conf.d/*
</span></span><span style="display:flex;"><span>sudo cp -r /tmp/src/* /etc/logstash/conf.d
</span></span></code></pre></div><p>Note that this doesn&rsquo;t start the LogStash service - this gets done by the UserData when we launch a new instance, as often we need to pass in additional configuration parameters, and don&rsquo;t want the service running until that has been done.</p>
<h3 id="running">Running</h3>
<p>To create the AMI, we need to invoke packer.  If I am running packer on a remote machine via SSH, I run it inside <code>tmux</code>, so that disconnects don&rsquo;t fail the process:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>packer build -var <span style="color:#e6db74">&#34;ami_users=111,222,333&#34;</span> logstash.json
</span></span></code></pre></div><p>After a while, Packer will finish, leaving you with an output which will include the new AMI ID:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">==</span>&gt; Builds finished. The artifacts of successful builds are:
</span></span><span style="display:flex;"><span>--&gt; amazon-ebs: AMIs were created:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>eu-west-1: ami-123123123
</span></span></code></pre></div><p>We&rsquo;ll get back to this output later when we create a build script that will also run our tests.  Before we get to that, however, let&rsquo;s look at how we can write tests which target both the local Vagrant machine and the AMI too.</p>
<h2 id="testing">Testing</h2>
<p>To test the machines, I am using <a href="https://jestjs.io">Jest</a>.  There isn&rsquo;t anything particularly interesting going on in the <code>package.json</code>, other than a few babel packages being installed so that I can use ES6 syntax:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;scripts&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;watch&#34;</span>: <span style="color:#e6db74">&#34;jest --watch&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;test&#34;</span>: <span style="color:#e6db74">&#34;jest &#34;</span>
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;devDependencies&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;babel-core&#34;</span>: <span style="color:#e6db74">&#34;^6.26.3&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;babel-jest&#34;</span>: <span style="color:#e6db74">&#34;^23.6.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;babel-preset-env&#34;</span>: <span style="color:#e6db74">&#34;^1.7.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;jest&#34;</span>: <span style="color:#e6db74">&#34;^23.6.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;regenerator-runtime&#34;</span>: <span style="color:#e6db74">&#34;^0.13.1&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="packer-configuration-testing">Packer Configuration Testing</h3>
<p>There are a number of tests we can do to make sure our Packer configuration is valid before running it.  This includes things like checking the base AMI is from a whitelisted source (such as our accounts, Amazon and Canonical).  The test has to handle the possibility of multiple builders, and that some builders might not have a <code>source_ami_filter</code>.  It also handles if no owner has been specified at all, which we also consider a &ldquo;bad thing&rdquo;:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">ourAccounts</span> <span style="color:#f92672">=</span> [ <span style="color:#e6db74">&#34;111111&#34;</span>, <span style="color:#e6db74">&#34;222222&#34;</span>, <span style="color:#e6db74">&#34;333333&#34;</span>, <span style="color:#e6db74">&#34;444444&#34;</span> ];
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">otherOwners</span> <span style="color:#f92672">=</span> [ <span style="color:#e6db74">&#34;amazon&#34;</span>, <span style="color:#e6db74">&#34;099720109477&#34;</span> <span style="color:#75715e">/*canonical*/</span> ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">describe</span>(<span style="color:#e6db74">&#34;ami builder&#34;</span>, () =&gt; {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">it</span>(<span style="color:#e6db74">&#34;should be based on a whitelisted owner&#34;</span>, () =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">allOwners</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">ourAccounts</span>.<span style="color:#a6e22e">concat</span>(<span style="color:#a6e22e">otherOwners</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">invalidOwners</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">owners</span> =&gt; <span style="color:#a6e22e">owners</span>.<span style="color:#a6e22e">filter</span>(<span style="color:#a6e22e">owner</span> =&gt; <span style="color:#f92672">!</span><span style="color:#a6e22e">allOwners</span>.<span style="color:#a6e22e">includes</span>(<span style="color:#a6e22e">owner</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">amisWithInvalidOwners</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">packer</span>.<span style="color:#a6e22e">builders</span>
</span></span><span style="display:flex;"><span>      .<span style="color:#a6e22e">filter</span>(<span style="color:#a6e22e">builder</span> =&gt; <span style="color:#a6e22e">builder</span>.<span style="color:#a6e22e">source_ami_filter</span>)
</span></span><span style="display:flex;"><span>      .<span style="color:#a6e22e">map</span>(<span style="color:#a6e22e">builder</span> =&gt; ({
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">name</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">builderName</span>(<span style="color:#a6e22e">builder</span>),
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">invalidOwners</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">invalidOwners</span>(<span style="color:#a6e22e">builder</span>.<span style="color:#a6e22e">source_ami_filter</span>.<span style="color:#a6e22e">owners</span> <span style="color:#f92672">||</span> [ <span style="color:#e6db74">&#34;NO OWNER SPECIFIED&#34;</span> ])
</span></span><span style="display:flex;"><span>      }))
</span></span><span style="display:flex;"><span>      .<span style="color:#a6e22e">filter</span>(<span style="color:#a6e22e">builders</span> =&gt; <span style="color:#a6e22e">builders</span>.<span style="color:#a6e22e">invalidOwners</span>.<span style="color:#a6e22e">length</span> <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">expect</span>(<span style="color:#a6e22e">amisWithInvalidOwners</span>).<span style="color:#a6e22e">toEqual</span>([]);
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>I also test that certain variables (<code>ami_users</code>) have been defined, and have been used in the right place:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">describe</span>(<span style="color:#e6db74">&#34;variables&#34;</span>, () =&gt; {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">it</span>(<span style="color:#e6db74">&#34;should have a variable for who can use the ami&#34;</span>, () =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">expect</span>(<span style="color:#a6e22e">packer</span>.<span style="color:#a6e22e">variables</span>).<span style="color:#a6e22e">toHaveProperty</span>(<span style="color:#e6db74">&#34;ami_users&#34;</span>);
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">it</span>(<span style="color:#e6db74">&#34;should read ami_users from AMI_ACCOUNTS&#34;</span>, () =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">expect</span>(<span style="color:#a6e22e">packer</span>.<span style="color:#a6e22e">variables</span>.<span style="color:#a6e22e">ami_users</span>).<span style="color:#a6e22e">toMatch</span>(
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">/{{\s*env\s*`AMI_ACCOUNTS`\s*}}/</span>
</span></span><span style="display:flex;"><span>    );
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">describe</span>(<span style="color:#e6db74">&#34;ami builder&#34;</span>, () =&gt; {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">it</span>(<span style="color:#e6db74">&#34;should set the ami_user&#34;</span>, () =&gt; {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">invalidUsers</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">packer</span>.<span style="color:#a6e22e">builders</span>
</span></span><span style="display:flex;"><span>      .<span style="color:#a6e22e">map</span>(<span style="color:#a6e22e">builder</span> =&gt; ({
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">name</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">builderName</span>(<span style="color:#a6e22e">builder</span>),
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">users</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">builder</span>.<span style="color:#a6e22e">ami_users</span> <span style="color:#f92672">||</span> <span style="color:#e6db74">&#34;NO USERS SPECIFIED&#34;</span>
</span></span><span style="display:flex;"><span>      }))
</span></span><span style="display:flex;"><span>      .<span style="color:#a6e22e">filter</span>(<span style="color:#a6e22e">ami</span> =&gt; <span style="color:#f92672">!</span><span style="color:#a6e22e">ami</span>.<span style="color:#a6e22e">users</span>.<span style="color:#a6e22e">match</span>(<span style="color:#e6db74">/{{\s*user\s*`ami_users`\s*}}/</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">expect</span>(<span style="color:#a6e22e">invalidUsers</span>).<span style="color:#a6e22e">toEqual</span>([]);
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>})
</span></span></code></pre></div><p>Other tests you might want to add are that the base AMI is under a certain age, or that your AMI has certain tags included, or that it is named in a specific manner.</p>
<h3 id="machine-testing">Machine Testing</h3>
<p>Machine testing is for checking that our provisioning worked successfully.  This is very useful, as subtle bugs can creep in when you don&rsquo;t verify what happens.</p>
<p>For example, a machine I built copied configuration directory to a target location but was missing the <code>-r</code> flag, so when I later added a subdirectory, the machine failed as the referenced files didn&rsquo;t exist.</p>
<p>So that the tests work with both the Vagrant and Packer built versions, we take in their address and key paths from the environment:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">import</span> { <span style="color:#a6e22e">spawnSync</span> } <span style="color:#a6e22e">from</span> <span style="color:#e6db74">&#34;child_process&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">import</span> { <span style="color:#a6e22e">createConnection</span> } <span style="color:#a6e22e">from</span> <span style="color:#e6db74">&#34;net&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// figure out where to look these up
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">host</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">LOGSTASH_ADDRESS</span>; <span style="color:#75715e">// e.g. &#34;172.27.48.28&#34;;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">keyPath</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">LOGSTASH_KEYPATH</span>; <span style="color:#75715e">// &#34;.vagrant/machines/default/hyperv/private_key&#34;;
</span></span></span></code></pre></div><p>We also define two helper methods: one to check if a TCP port is open, and one which uses SSH to execute a command and read the response in the machine:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">execute</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">command</span> =&gt; {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">args</span> <span style="color:#f92672">=</span> [<span style="color:#e6db74">`vagrant@</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">host</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>, <span style="color:#e6db74">`-i`</span>, <span style="color:#a6e22e">keyPath</span>, <span style="color:#a6e22e">command</span>];
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">ssh</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">spawnSync</span>(<span style="color:#e6db74">&#34;ssh&#34;</span>, <span style="color:#a6e22e">args</span>, { <span style="color:#a6e22e">encoding</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;utf8&#34;</span> });
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">lines</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">ssh</span>.<span style="color:#a6e22e">stdout</span>.<span style="color:#a6e22e">split</span>(<span style="color:#e6db74">&#34;\n&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">lines</span>[<span style="color:#a6e22e">lines</span>.<span style="color:#a6e22e">length</span> <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>] <span style="color:#f92672">===</span> <span style="color:#e6db74">&#34;&#34;</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">lines</span>.<span style="color:#a6e22e">slice</span>(<span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">lines</span>.<span style="color:#a6e22e">length</span> <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">lines</span>;
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">testPort</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">port</span> =&gt; <span style="color:#66d9ef">new</span> Promise((<span style="color:#a6e22e">resolve</span>, <span style="color:#a6e22e">reject</span>) =&gt; {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">client</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">createConnection</span>({ <span style="color:#a6e22e">host</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">host</span>, <span style="color:#a6e22e">port</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">port</span> });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">client</span>.<span style="color:#a6e22e">on</span>(<span style="color:#e6db74">&#34;error&#34;</span>, <span style="color:#a6e22e">err</span> =&gt; <span style="color:#a6e22e">reject</span>(<span style="color:#a6e22e">err</span>));
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">client</span>.<span style="color:#a6e22e">on</span>(<span style="color:#e6db74">&#34;connect&#34;</span>, () =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">client</span>.<span style="color:#a6e22e">end</span>();
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">resolve</span>();
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>We can then add some tests which check the files were written to the right place, that port <code>5044</code> is open, and port <code>9600</code> is closed:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">describe</span>(<span style="color:#e6db74">&#34;the machine&#34;</span>, () =&gt; {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">it</span>(<span style="color:#e6db74">&#34;should have the correct configuration&#34;</span>, () =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">files</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">execute</span>(<span style="color:#e6db74">&#34;find /etc/logstash/conf.d/* -type f&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">expect</span>(<span style="color:#a6e22e">files</span>).<span style="color:#a6e22e">toEqual</span>([
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">&#34;/etc/logstash/conf.d/beats.conf&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">&#34;/etc/logstash/conf.d/patterns/custom.txt&#34;</span>
</span></span><span style="display:flex;"><span>    ]);
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">it</span>(<span style="color:#e6db74">&#34;should be listening on 5044 for beats&#34;</span>, () =&gt; <span style="color:#a6e22e">testPort</span>(<span style="color:#ae81ff">5044</span>));
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">it</span>(<span style="color:#e6db74">&#34;should not be listening on 9600&#34;</span>, () =&gt; <span style="color:#a6e22e">expect</span>(<span style="color:#a6e22e">testPort</span>(<span style="color:#ae81ff">9600</span>)).<span style="color:#a6e22e">rejects</span>.<span style="color:#a6e22e">toThrow</span>(<span style="color:#e6db74">&#34;ECONNREFUSED&#34;</span>));
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>Of course, as we can execute any command inside the machine, we can check pretty much anything:</p>
<ul>
<li><code>tail</code> the LogStash log and see if it&rsquo;s got the right contents</li>
<li>check if the service is started</li>
<li>check the service is enabled on boot</li>
<li>check the environment variables been written to the right files</li>
</ul>
<h3 id="application-testing">Application Testing</h3>
<p>There are two styles of Application Testing: white-box and black-box.  White-box will be tests run on the application inside the machine, using minimal external dependencies (preferably none at all), and Black-box will be run on the application from outside the machine, either using direct dependencies, or fakes.</p>
<p>It&rsquo;s worth noting that both white-box and black-box tests are <strong>slow</strong>, mostly down to how slow LogStash is at starting up, although only giving it 1 CPU and 2Gb of RAM probably doesn&rsquo;t help.</p>
<h4 id="whitebox-testing-logstash">Whitebox Testing LogStash</h4>
<p>To white-box test LogStash, I use a technique partially based on the <a href="https://github.com/agolo/logstash-test-runner">Agolo LogStash Test Runner</a>.  The process for the tests is to run LogStash interactively (rather than as a service), send it a single event, record the output events, and compare them to an expected output.</p>
<p>The test cases are kept in separate folders, with two files.  First is the input file, imaginatively called <code>input.log</code>, which will contain one json encoded event per line.  The format needs to match what the result of FileBeat sending an event to LogStash would be.  In this case, it means a few extra fields, and a <code>message</code> property containing a string of json.  Formatted for readability, the object looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;@timestamp&#34;</span>: <span style="color:#e6db74">&#34;2018-12-27T14:08:24.753Z&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;beat&#34;</span>: { <span style="color:#f92672">&#34;hostname&#34;</span>: <span style="color:#e6db74">&#34;Spectre&#34;</span>, <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;Spectre&#34;</span>, <span style="color:#f92672">&#34;version&#34;</span>: <span style="color:#e6db74">&#34;5.3.0&#34;</span> },
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;fields&#34;</span>: { <span style="color:#f92672">&#34;environment&#34;</span>: <span style="color:#e6db74">&#34;local&#34;</span>, <span style="color:#f92672">&#34;log_type&#34;</span>: <span style="color:#e6db74">&#34;application&#34;</span> },
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;input_type&#34;</span>: <span style="color:#e6db74">&#34;log&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;message&#34;</span>: <span style="color:#e6db74">&#34;{\&#34;Timestamp\&#34;: \&#34;2018-12-18T17:06:27.7112297+02:00\&#34;,\&#34;Level\&#34;: \&#34;Information\&#34;,\&#34;MessageTemplate\&#34;: \&#34;This is the {count} message\&#34;,\&#34;Properties\&#34;: {\&#34;count\&#34;: 4,\&#34;SourceContext\&#34;: \&#34;LogLines.GetOpenPurchasesHandler\&#34;,\&#34;ApplicationName\&#34;: \&#34;FileBeatTest\&#34;,\&#34;CorrelationId\&#34;: \&#34;8f341e8e-6b9c-4ebf-816d-d89c014bad90\&#34;,\&#34;TimedOperationElapsedInMs\&#34;: 1000}}&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;offset&#34;</span>: <span style="color:#ae81ff">318</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;source&#34;</span>: <span style="color:#e6db74">&#34;D:\\tmp\\logs\\single.log&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;applicationlog&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I also define an <code>output.log</code>, which contains the expected result(s), again one json encoded event per line.  The example pipeline in the repository will emit two events for a given input, so this file contains two lines of json (again, newlines added for readability here):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;source&#34;</span>: <span style="color:#e6db74">&#34;D:\\tmp\\logs\\single.log&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;@version&#34;</span>: <span style="color:#e6db74">&#34;1&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;fields&#34;</span>: { <span style="color:#f92672">&#34;log_type&#34;</span>: <span style="color:#e6db74">&#34;application&#34;</span>, <span style="color:#f92672">&#34;environment&#34;</span>: <span style="color:#e6db74">&#34;local&#34;</span> },
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;@timestamp&#34;</span>: <span style="color:#e6db74">&#34;2018-12-18T15:06:27.711Z&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;offset&#34;</span>: <span style="color:#ae81ff">318</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;ApplicationName&#34;</span>: <span style="color:#e6db74">&#34;FileBeatTest&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;host&#34;</span>: <span style="color:#e6db74">&#34;ubuntu-16&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;applicationlog&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;CorrelationId&#34;</span>: <span style="color:#e6db74">&#34;8f341e8e-6b9c-4ebf-816d-d89c014bad90&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;MessageTemplate&#34;</span>: <span style="color:#e6db74">&#34;This is the {count} message&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Level&#34;</span>: <span style="color:#e6db74">&#34;Information&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Context&#34;</span>: <span style="color:#e6db74">&#34;LogLines.GetOpenPurchasesHandler&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;TimeElapsed&#34;</span>: <span style="color:#ae81ff">1000</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Properties&#34;</span>: { <span style="color:#f92672">&#34;count&#34;</span>: <span style="color:#ae81ff">4</span> }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;duration&#34;</span>: <span style="color:#ae81ff">1000000</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;timestamp&#34;</span>: <span style="color:#ae81ff">1545145586711000</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;id&#34;</span>: <span style="color:#e6db74">&#34;&lt;generated&gt;&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;traceid&#34;</span>: <span style="color:#e6db74">&#34;8f341e8e6b9c4ebf816dd89c014bad90&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;LogLines.GetOpenPurchasesHandler&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;localEndpoint&#34;</span>: { <span style="color:#f92672">&#34;serviceName&#34;</span>: <span style="color:#e6db74">&#34;FileBeatTest&#34;</span> }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>To enable sending the lines directly to LogStash (rather than needing to use FileBeat), we define an <code>input.conf</code> file, which configures LogStash to read json from stdin:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-conf" data-lang="conf"><span style="display:flex;"><span>input {
</span></span><span style="display:flex;"><span>  stdin { codec <span style="color:#f92672">=</span><span style="color:#960050;background-color:#1e0010">&gt;</span> <span style="color:#e6db74">&#34;json_lines&#34;</span> }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And an <code>ouput.conf</code> file which configures LogStash to write the output as json lines a known file path:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-conf" data-lang="conf"><span style="display:flex;"><span>output {
</span></span><span style="display:flex;"><span>  file {
</span></span><span style="display:flex;"><span>    path <span style="color:#f92672">=</span><span style="color:#960050;background-color:#1e0010">&gt;</span> <span style="color:#e6db74">&#34;/tmp/test/output.log&#34;</span>
</span></span><span style="display:flex;"><span>    codec <span style="color:#f92672">=</span><span style="color:#960050;background-color:#1e0010">&gt;</span> <span style="color:#e6db74">&#34;json_lines&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The tests need to be run inside the machine itself, so I created a script in the <code>./scripts</code> directory which will do all the work, and can be run by the <code>execute</code> method in a Jest test.  The script stops the LogStash service, copies the current configuration from the <code>./src</code> directory and the replacement <code>input.conf</code> and <code>output.conf</code> files to a temporary location, and then runs LogStash once per test case, copying the result file to the test case&rsquo;s directory.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#! /bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>sudo systemctl stop logstash
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>temp_path<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;/tmp/test&#34;</span>
</span></span><span style="display:flex;"><span>test_source<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;/vagrant/test/acceptance&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo rm -rf <span style="color:#e6db74">&#34;</span>$temp_path<span style="color:#e6db74">/*&#34;</span>
</span></span><span style="display:flex;"><span>sudo mkdir -p $temp_path
</span></span><span style="display:flex;"><span>sudo cp -r /vagrant/src/* $temp_path
</span></span><span style="display:flex;"><span>sudo cp $test_source/*.conf $temp_path
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>find $test_source/* -type d | <span style="color:#66d9ef">while</span> read test_path; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Running </span><span style="color:#66d9ef">$(</span>basename $test_path<span style="color:#66d9ef">)</span><span style="color:#e6db74"> tests...&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    sudo /usr/share/logstash/bin/logstash <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>        <span style="color:#e6db74">&#34;--path.settings&#34;</span> <span style="color:#e6db74">&#34;/etc/logstash&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>        <span style="color:#e6db74">&#34;--path.config&#34;</span> <span style="color:#e6db74">&#34;</span>$temp_path<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>        &lt; <span style="color:#e6db74">&#34;</span>$test_path<span style="color:#e6db74">/input.log&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    sudo touch <span style="color:#e6db74">&#34;</span>$temp_path<span style="color:#e6db74">/output.log&#34;</span>   <span style="color:#75715e"># create it if it doesn&#39;t exist (dropped logs etc.)</span>
</span></span><span style="display:flex;"><span>    sudo rm -f <span style="color:#e6db74">&#34;</span>$test_path<span style="color:#e6db74">/result.log&#34;</span>
</span></span><span style="display:flex;"><span>    sudo mv <span style="color:#e6db74">&#34;</span>$temp_path<span style="color:#e6db74">/output.log&#34;</span> <span style="color:#e6db74">&#34;</span>$test_path<span style="color:#e6db74">/result.log&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">$(</span>basename $test_path<span style="color:#66d9ef">)</span><span style="color:#e6db74"> tests done&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo systemctl start logstash
</span></span></code></pre></div><p>To execute this, we use the <code>beforeAll</code> function to run it once - we also pass in <code>Number.MAX_SAFE_INTEGER</code> as by default <code>beforeAll</code> will time out after 5 seconds, and the <code>test.sh</code> is <strong>slow as hell</strong> (as LogStash takes ages to start up).</p>
<p>Once the <code>test.sh</code> script has finished running, we load each test&rsquo;s <code>output.log</code> and <code>result.log</code> files, parse each line as json, compare the objects, and print out the delta if the objects are not considered equal:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">source</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;./test/acceptance&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">isDirectory</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">p</span> =&gt; <span style="color:#a6e22e">fs</span>.<span style="color:#a6e22e">lstatSync</span>(<span style="color:#a6e22e">p</span>).<span style="color:#a6e22e">isDirectory</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">cases</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">fs</span>
</span></span><span style="display:flex;"><span>  .<span style="color:#a6e22e">readdirSync</span>(<span style="color:#a6e22e">source</span>)
</span></span><span style="display:flex;"><span>  .<span style="color:#a6e22e">map</span>(<span style="color:#a6e22e">name</span> =&gt; <span style="color:#a6e22e">path</span>.<span style="color:#a6e22e">join</span>(<span style="color:#a6e22e">source</span>, <span style="color:#a6e22e">name</span>))
</span></span><span style="display:flex;"><span>  .<span style="color:#a6e22e">filter</span>(<span style="color:#a6e22e">isDirectory</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">describe</span>(<span style="color:#e6db74">&#34;logstash&#34;</span>, () =&gt; {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">beforeAll</span>(
</span></span><span style="display:flex;"><span>    () =&gt; <span style="color:#a6e22e">execute</span>(<span style="color:#e6db74">&#34;/vagrant/scripts/test.sh&#34;</span>),
</span></span><span style="display:flex;"><span>    Number.<span style="color:#a6e22e">MAX_SAFE_INTEGER</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">test</span>.<span style="color:#a6e22e">each</span>(<span style="color:#a6e22e">cases</span>)(<span style="color:#e6db74">&#34;%s&#34;</span>, <span style="color:#a6e22e">directoryPath</span> =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">expected</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">readFile</span>(<span style="color:#a6e22e">path</span>.<span style="color:#a6e22e">join</span>(<span style="color:#a6e22e">directoryPath</span>, <span style="color:#e6db74">&#34;output.log&#34;</span>));
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">actual</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">readFile</span>(<span style="color:#a6e22e">path</span>.<span style="color:#a6e22e">join</span>(<span style="color:#a6e22e">directoryPath</span>, <span style="color:#e6db74">&#34;result.log&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">diffpatch</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">DiffPatcher</span>({
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">propertyFilter</span><span style="color:#f92672">:</span> (<span style="color:#a6e22e">name</span>, <span style="color:#a6e22e">context</span>) =&gt; {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">name</span> <span style="color:#f92672">!==</span> <span style="color:#e6db74">&#34;id&#34;</span>) {
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">left</span>.<span style="color:#a6e22e">id</span> <span style="color:#f92672">!==</span> <span style="color:#e6db74">&#34;&lt;generated&gt;&#34;</span>;
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">delta</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">diffpatch</span>.<span style="color:#a6e22e">diff</span>(<span style="color:#a6e22e">expected</span>, <span style="color:#a6e22e">actual</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">output</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">formatters</span>.<span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">format</span>(<span style="color:#a6e22e">delta</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">output</span>.<span style="color:#a6e22e">length</span>) {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">output</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">expect</span>(<span style="color:#a6e22e">output</span>.<span style="color:#a6e22e">length</span>).<span style="color:#a6e22e">toBe</span>(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><h4 id="blackbox-testing-logstash">Blackbox Testing LogStash</h4>
<p>As the machine has ports open for FileBeat and will send it&rsquo;s output to ElasticSearch, we can set up a fake HTTP server, send some log events via FileBeat to the VM and check we receive the right HTTP calls to our fake server.</p>
<p>While looking on how to do this, I came across the <a href="https://www.npmjs.com/package/lumberjack-protocol">lumberjack-protocol</a> package on NPM, but unfortunately, it only supports lumberjack v1, and FileBeat and LogStash are now using v2, so you would have to use a local copy of filebeat to do the sending.</p>
<p>Due to the complexity of implementing this, and the diminished return on investment (the other tests should be sufficient), I have skipped creating the Blackbox tests for the time being.</p>
<h2 id="ami-testing">AMI Testing</h2>
<p>The final phase!  Now that we are reasonably sure everything works locally, we need to build our AMI and test that everything works there too, as it would be a shame to update an Auto Scale Group with the new image which doesn&rsquo;t work!</p>
<p>All that needs to happen to run the tests against an EC2 instance is to set the three environment variables we used with Vagrant, to values for communicating with the EC2 instance. To do this, we&rsquo;ll need the EC2 IP Address, the username for SSH, and the private key for SSH authentication.</p>
<p>The first thing our build script needs to do is create the AMI.  This is done in the same way as <a href="#running">mentioned earlier</a>, but with the slight difference of also piping the output to <code>tee</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>packer_log<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>packer build logstash.json | tee /dev/tty<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>ami_id<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>echo <span style="color:#e6db74">&#34;</span>$packer_log<span style="color:#e6db74">&#34;</span> | tail -n <span style="color:#ae81ff">1</span> | sed <span style="color:#e6db74">&#39;s/.*\(ami.*\)/\1/&#39;</span><span style="color:#66d9ef">)</span>
</span></span></code></pre></div><p>By using <code>tee</code>, we can pipe the build log from Packer to both the real terminal (<code>/dev/tty</code>), and to a variable called <code>packer_log</code>.  The script then takes the last line and uses some regex to grab the AMI ID.</p>
<p>Next up, the script uses the AWS CLI to launch an EC2 instance based on the AMI, and store it&rsquo;s IP Address and Instance ID:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>json<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>aws ec2 run-instances <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --image-id <span style="color:#e6db74">&#34;</span>$ami_id<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --instance-type t2.small <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --key-name <span style="color:#e6db74">&#34;</span>$keypair_name<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --region eu-west-1 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --subnet-id <span style="color:#e6db74">&#34;</span>$subnet_id<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --security-group-ids <span style="color:#e6db74">&#34;</span>$security_group_id<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --tag-specifications <span style="color:#e6db74">&#39;ResourceType=instance,Tags=[{Key=Name,Value=logstash-verification}]&#39;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --user-data <span style="color:#e6db74">&#34;</span>$userdata<span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>instance_id<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>echo <span style="color:#e6db74">&#34;</span>$json<span style="color:#e6db74">&#34;</span> | jq -r .Instances<span style="color:#f92672">[</span>0<span style="color:#f92672">]</span>.InstanceId<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>private_ip<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>echo <span style="color:#e6db74">&#34;</span>$json<span style="color:#e6db74">&#34;</span> | jq -r .Instances<span style="color:#f92672">[</span>0<span style="color:#f92672">]</span>.PrivateIpAddress<span style="color:#66d9ef">)</span>
</span></span></code></pre></div><p>The IP Address is then used to set up the environment variables which the node test scripts use to locate the machine:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>LOGSTASH_ADDRESS<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$private_ip<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>LOGSTASH_SSH<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;ubuntu&#34;</span>
</span></span><span style="display:flex;"><span>LOGSTASH_KEYPATH<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;~/.ssh/id_rsa&#34;</span> build ou
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>npm run test
</span></span></code></pre></div><p>Finally, the script uses the Instance ID to terminate the instance:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>aws ec2 terminate-instances <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --instance-ids <span style="color:#e6db74">&#34;</span>$instance_id<span style="color:#e6db74">&#34;</span>
</span></span></code></pre></div><h2 id="wrapping-up">Wrapping Up</h2>
<p>Hopefully, this (rather long) post is a useful introduction (!) to how I tackle testing Immutable Infrastructure.  All of these techniques for testing the machine and application can be used for testing things like Docker containers too (and handily, Packer can be used to create Docker containers also).</p>
<p>As mentioned earlier <a href="https://github.com/Pondidum/immutable-infra-testing-demo">The Repository is available here</a>.</p>
]]></content:encoded></item><item><title>Code-free tracing with LogStash and Jaeger</title><link>https://andydote.co.uk/2018/12/22/serilog-elk-jaeger/</link><pubDate>Sat, 22 Dec 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/12/22/serilog-elk-jaeger/</guid><description>I wanted to show request charts (similar to the network tab in firefox) for requests across our microservices but wanted to do so in the least invasive way possible.
We already use LogStash to collect logs from multiple hosts (via FileBeat) and forward them on to ElasticSearch, so perhaps I can do something to also output from LogStash to a tracing service.
There are a number of tracing services available (AppDash, Jaeger, Zipkin), but unfortunately LogStash doesn&amp;rsquo;t have plugins for any of them or for OpenTracing.</description><content:encoded><![CDATA[<p>I wanted to show request charts (similar to the network tab in firefox) for requests across our microservices but wanted to do so in the least invasive way possible.</p>
<p><img loading="lazy" src="firefox-network-timeline.png" alt="Firefox network timeline"  />
</p>
<p>We already use <a href="https://www.elastic.co/products/logstash">LogStash</a> to collect logs from multiple hosts (via <a href="https://www.elastic.co/products/beats/filebeat">FileBeat</a>) and forward them on to <a href="https://www.elastic.co/products/elasticsearch">ElasticSearch</a>, so perhaps I can do something to also output from LogStash to a tracing service.</p>
<p><img loading="lazy" src="logstash-jaeger.png" alt="app to filebeat to logstash to elasticsearch and opentracing"  />
</p>
<p>There are a number of tracing services available (<a href="https://github.com/sourcegraph/appdash">AppDash</a>, <a href="https://www.jaegertracing.io/">Jaeger</a>, <a href="https://zipkin.io/">Zipkin</a>), but unfortunately LogStash doesn&rsquo;t have plugins for any of them or for <a href="https://opentracing.io/">OpenTracing</a>.  I picked Jaeger, as it seemed to be the easiest to get up and running, and also had a &ldquo;Zipkin compatible&rdquo; API too if you didn&rsquo;t want to use the Jaeger one.</p>
<p>Setting up and running Jaeger in a production environment is way out of scope for this post, but for testing, I am just using the all-in-one Docker container:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker run -d --nameron jaeger <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -e COLLECTOR_ZIPKIN_HTTP_PORT<span style="color:#f92672">=</span><span style="color:#ae81ff">9411</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -p 5775:5775/udp <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -p 6831:6831/udp <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -p 6832:6832/udp <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -p 5778:5778 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -p 16686:16686 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -p 14268:14268 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -p 9411:9411 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  jaegertracing/all-in-one
</span></span></code></pre></div><p>The tracing APIs work in roughly the same way:  all traces have the same <code>traceid</code>, and are sub-divided into spans.  Spans have a unique id and can have a parent (span) id set.  The trouble with sending data from LogStash is that I don&rsquo;t have any parent IDs available. Well, at least without going and adding it to all our applications, and I&rsquo;m not sure how I would want to propagate it correctly either.</p>
<p>So the first question is: can I push multiple spans without any parent IDs, and have it plot them as I would expect.</p>
<h2 id="is-spanparentid-required">Is span.parentid required?</h2>
<p>As the HTTP API documentation seems to be non-existent (other than &ldquo;there is one!&rdquo;), and most of the other docs mention the Thrift API, I decided to use that to test the theory.  The <a href="https://github.com/jaegertracing/jaeger-client-csharp">Jaeger C# client</a> library has a nice API to use, but I wanted to manually specify things (e.g. <code>traceid</code>, <code>spanid</code>, etc.) and the API has no way to do that, as pretty much everything is marked as <code>internal</code>.</p>
<p>Instead, I cloned the client repository, and added a test (which had access to all the internals I wanted):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Scratch</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> HttpSender _sender;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Tracer _tracer;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> TraceId _id;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Scratch(ITestOutputHelper output)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        _sender = <span style="color:#66d9ef">new</span> HttpSender(<span style="color:#e6db74">&#34;http://localhost:14268/api/traces&#34;</span>);
</span></span><span style="display:flex;"><span>        _tracer = <span style="color:#66d9ef">new</span> Tracer.Builder(<span style="color:#e6db74">&#34;FirstService&#34;</span>).Build();
</span></span><span style="display:flex;"><span>        _id = TraceId.NewUniqueId(<span style="color:#66d9ef">false</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        output.WriteLine(_id.ToString());
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">    [Fact]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task Send()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> start = DateTime.UtcNow;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> Create(start, start.AddSeconds(<span style="color:#ae81ff">5</span>));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> Create(start, start.AddSeconds(<span style="color:#ae81ff">3</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> Create(start.AddSeconds(<span style="color:#ae81ff">5</span>), start.AddSeconds(<span style="color:#ae81ff">10</span>));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> Create(start.AddSeconds(<span style="color:#ae81ff">10</span>), start.AddSeconds(<span style="color:#ae81ff">20</span>));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> Create(start, start.AddSeconds(<span style="color:#ae81ff">20</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> _sender.FlushAsync(CancellationToken.None);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">async</span> Task Create(DateTime start, DateTimeOffset finish)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> context = <span style="color:#66d9ef">new</span> SpanContext(_id, SpanId.NewUniqueId(), <span style="color:#66d9ef">new</span> SpanId(<span style="color:#ae81ff">0</span>), SpanContextFlags.None);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> span = <span style="color:#66d9ef">new</span> Span(_tracer, <span style="color:#e6db74">&#34;test&#34;</span>, context, start, <span style="color:#66d9ef">new</span> Dictionary&lt;<span style="color:#66d9ef">string</span>, <span style="color:#66d9ef">object</span>&gt;(), <span style="color:#66d9ef">null</span>);
</span></span><span style="display:flex;"><span>        span.Finish(finish);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> _sender.AppendAsync(span, CancellationToken.None);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The graph rendered how I hoped, proving that I don&rsquo;t need to set the span&rsquo;s <code>parentid</code> for everything with the same <code>traceid</code> to work correctly!</p>
<h2 id="how-to-generate-a-consistent-traceid">How to generate a consistent TraceID?</h2>
<p>All our services pass along or generate a <code>correlationID</code> for each request, so my idea here was to do some conversion to put it in the <code>traceid</code>, which is an <code>int64</code>.  Our <code>correlationID</code>s are guids, which internally is an <code>int128</code>, so I figured I would take the least significant 8 bytes and use that.  This can be done in C# like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> correlationID = Guid.NewGuid();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> traceID = <span style="color:#66d9ef">new</span> TraceId(BitConverter.ToInt64(correlationID.ToByteArray(), <span style="color:#ae81ff">8</span>));
</span></span></code></pre></div><p>I noticed, however, that the <code>TraceID</code> structure in the Jaeger client can take two values: <code>int64 low</code> and <code>int64 high</code>, so I can use the entire <code>correlationid</code>.</p>
<h2 id="how-to-ship-from-logstash">How to ship from LogStash?</h2>
<p>After reading through the LogStash <a href="https://www.elastic.co/guide/en/logstash/current/output-plugins.html">Output Plugins docs</a> it looked like there were three possible ways to ship the events to Jaeger: writing a command line app; invoked through either <code>exec</code> or <code>pipe</code>, writing a LogStash plugin, or doing something with the <code>http</code> output.</p>
<h3 id="cli-adaptor">CLI adaptor</h3>
<p>The idea of this method would be to write a CLI app which takes an event from LogStash and then sends it to Jaeger using the Thrift API.  The app itself could be invoked using the <code>exec</code> or <code>pipe</code> outputs.  I didn&rsquo;t want to use this method for a few reasons:</p>
<p><strong>Development:</strong> The Jaeger client has things I need hidden from the public surface, such as being able to specify the <code>traceid</code>, rather than generating a new one each time, so I would either have to reimplement the classes I need, use reflection to instantiate things, or try opening Pull Requests to expose more internals of the library.</p>
<p><strong>Maintenance:</strong> I&rsquo;d rather not have yet another thing to maintain if I can avoid it, not to mention all the additional things like repository location, build agents, etc.</p>
<p><strong>Deployment:</strong> Our LogStash box is a plain Ubuntu box with nothing other than Java and LogStash installed on it.  As I would probably end up using C# to write the app, I&rsquo;d need to add even more dependencies.</p>
<p><strong>Throughput:</strong> Jaeger (and the others) support sending traces in batches for better efficiency.  Writing an app which supported that would involve writing the batching and caching, and the likelihood is I would mess it up, and increase the chances of lost messages.</p>
<h3 id="logstash-plugin">LogStash plugin</h3>
<p>Basically has the same problems as above, with the addition of me needing to learn enough about Java to build something reliable, and as this is a test and no one else in my team really knows Java either, so I ruled this out.</p>
<h3 id="http">Http?</h3>
<p>The Jaeger collector process can also expose a Zipkin compatible API, and while the documentation for that API is also terrible, I was able to find a <a href="https://github.com/openzipkin/zipkin/issues/1499">Pull Request on Github</a> with some structure defined.  I figured I could do most of this directly with LogStash&rsquo;s configuration DSL, assuming I can: generate a uuid (<code>logstash-filter-uuid</code> plugin), and remove all extra stuff from the post body (<code>logstash-filter-prune</code>).</p>
<h2 id="building-the-logstash-message">Building the LogStash message</h2>
<p>The first step of my configuration is based on what we need to do to <a href="https://github.com/serilog/serilog">Serilog</a> messages to make them a bit nicer in Kibana:</p>
<h3 id="pre-processing">Pre-processing</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>json {
</span></span><span style="display:flex;"><span>    source <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;message&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>date {
</span></span><span style="display:flex;"><span>    match <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;Timestamp&#34;</span>, <span style="color:#e6db74">&#34;ISO8601&#34;</span>, <span style="color:#e6db74">&#34;yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSSSSSZZ&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    target <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;@timestamp&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mutate {
</span></span><span style="display:flex;"><span>    rename <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;[Properties][ApplicationName]&#34;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;ApplicationName&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;[Properties][CorrelationId]&#34;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;CorrelationId&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;[Properties][SourceContext]&#34;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;Context&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;[Properties][TimedOperationElapsedInMs]&#34;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;TimeElapsed&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>json</code> block tells LogStash that everything in the <code>message</code> property is a json object, rather than a string.</p>
<p>The <code>date</code> block extracts the time the message was recorded by the application and writes it to the special <code>@timestamp</code> field.  This is a good idea as due to queuing, and processing times, the time the message was written and the time it was processed by LogStash will be different.</p>
<p>Lastly, the <code>mutate</code> block is moving a bunch of fields out of the message properties, and up to the top level of the object.  We query by things like <code>ApplicationName</code> a lot, and it&rsquo;s nice not to have to write <code>Properties.ApplicationName:blahblah</code> all the time.</p>
<h3 id="splitting">Splitting</h3>
<p>Our messages contain a lot of data which for the purposes of tracing, we just don&rsquo;t care about.  Not only is it a waste of bandwidth to send all the data to Jaeger, but also there could be clashing fields, and if we ever decide to use a hosted version of Jaeger, I don&rsquo;t want to be sending them all the data either.</p>
<p>So how do we remove everything from the message, but still keep it in the message for the other outputs?</p>
<p>LogStash has an interesting filter called <code>clone</code>.  What it does is copy the message as many times as you specify, and then runs the remaining part of the pipeline once per message, including the original message.  In code, this just looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>clone {
</span></span><span style="display:flex;"><span>    clones <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;jaeger&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>If we wanted to split the message more times, we can just add more types to the <code>clones</code> array; there will be one extra message produced for each entry in the array, which will also be added to the message as the <code>type</code> property so we can filter on it later.</p>
<p>We don&rsquo;t want to send the <code>type</code> field itself to Jaeger (or ElasticSeach), so we move it from the message to the <code>@metadata</code> object, which doesn&rsquo;t get passed to outputs.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>mutate {
</span></span><span style="display:flex;"><span>    rename <span style="color:#f92672">=&gt;</span> { <span style="color:#e6db74">&#34;type&#34;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;[@metadata][type]&#34;</span> }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>To handle the messages differently, we can just use an <code>if</code> statement on the <code>@metadata.type</code> property:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span>@metadata<span style="color:#f92672">][</span>type<span style="color:#f92672">]</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;jaeger&#34;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># do stuff to the jaeger message</span>
</span></span><span style="display:flex;"><span>} <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># process the original message</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="building-the-http-payload">Building the Http Payload</h3>
<p>The hardest part of getting this to work was handling the dates.  Jaeger specifies that timestamps should come in <strong>micro</strong>seconds since epoch, and duration should be in microseconds also.  We need to use the <code>ruby</code> filter so we can run some code to do this, rather than using an inbuilt filter primitive.</p>
<p>The <code>duration</code> is easy enough, as we report <code>TimeElapsed</code> in milliseconds:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>ruby {
</span></span><span style="display:flex;"><span>    code <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;event.set(&#39;duration&#39;, (event.get(&#39;TimeElapsed&#39;) * 1000).floor)&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>To handle the timestamp we need to convert it to epoch milliseconds.  We can get the fractional seconds since the epoch by calling <a href="https://ruby-doc.org/core-1.9.3/Time.html#method-i-to_f"><code>to_f</code></a> on the <code>@timestamp</code> field, and then multiply by <code>1000</code> a couple of times to express it as microseconds.  We also <code>floor</code> it to remove the leftover fraction:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>ruby {
</span></span><span style="display:flex;"><span>    code <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;event.set(&#39;timestamp&#39;, (event.get(&#39;@timestamp&#39;).to_f * 1000 * 1000).floor)&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This on its own will work, but it <strong>won&rsquo;t be right</strong>.  We report log entries when an operation completes, which means our timestamp is the finish of the event, not the start.  To solve this, we subtract the duration off the timestamp:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>ruby {
</span></span><span style="display:flex;"><span>    code <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;event.set(&#39;timestamp&#39;, (event.get(&#39;@timestamp&#39;).to_f * 1000 * 1000).floor - event.get(&#39;duration&#39;))&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Next, we need to create our span id.  We need to generate a random id, consisting of letters and numbers, so the easiest way is to generate a <code>uuid</code>, and then tweak it to fit the Jaeger/Zipkin format.  To do that we need to install the <code>logstash-filter-uuid</code> plugin:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>/usr/share/logstash/bin/logstash-plugin install logstash-filter-uuid
</span></span></code></pre></div><p>There are a few things we need to do to generate a valid span id (for Jaeger):</p>
<ol>
<li>generate a uuid</li>
<li>remove the dashes</li>
<li>make it lowercase</li>
<li>trim it to 16 chars</li>
</ol>
<p>We use four filters to achieve this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>uuid {
</span></span><span style="display:flex;"><span>    target <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;id&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>mutate {
</span></span><span style="display:flex;"><span>    gsub <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;id&#34;</span>, <span style="color:#e6db74">&#34;-&#34;</span>, <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    lowercase <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;id&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>mutate {
</span></span><span style="display:flex;"><span>    gsub <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;id&#34;</span>, <span style="color:#e6db74">&#34;(^.{1,16}).*$&#34;</span>, <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\1</span><span style="color:#e6db74">&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The reason we specify the <code>mutate</code> twice is that order of the same operation (<code>gsub</code> in this case) is not guaranteed within a <code>mutate</code> block.</p>
<p>Next up we need to tweak the <code>traceid</code> from a guid to a uuid:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>mutate {
</span></span><span style="display:flex;"><span>    gsub <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;traceid&#34;</span>, <span style="color:#e6db74">&#34;-&#34;</span>, <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    lowercase <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;traceid&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Next, we can populate some other context into the message, by renaming the other fields we want.  I discovered most of the fields and their formats from a combination of the <a href="https://github.com/jaegertracing/jaeger-idl/blob/master/thrift/zipkincore.thrift">thrift dtos</a> and the <a href="https://github.com/openzipkin/zipkin/issues/1499">this pull request</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>mutate {
</span></span><span style="display:flex;"><span>    rename <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;CorrelationId&#34;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;traceid&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;Context&#34;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;name&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;ApplicationName&#34;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;[localEndpoint][serviceName]&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Finally, we want to trim all the other properties from our message, which we can do by using the <code>logstash-filter-prune</code> plugin:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>prune {
</span></span><span style="display:flex;"><span>    whitelist_names <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;id&#34;</span>, <span style="color:#e6db74">&#34;traceid&#34;</span>, <span style="color:#e6db74">&#34;name&#34;</span>, <span style="color:#e6db74">&#34;timestamp&#34;</span>, <span style="color:#e6db74">&#34;duration&#34;</span>, <span style="color:#e6db74">&#34;localEndpoint&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>mutate {
</span></span><span style="display:flex;"><span>    remove_field <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;@timestamp&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We have to explicitly remove the <code>@timestamp</code> property as the prune plugin seems to ignore it (it also ignores the <code>@metadata</code> property).</p>
<p>The complete filter code can be made a little more efficient by combining several of the <code>mutate</code> blocks, provided we keep things in the right order, as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>ruby {
</span></span><span style="display:flex;"><span>    code <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;event.set(&#39;duration&#39;, (event.get(&#39;TimeElapsed&#39;) * 1000).floor)&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>ruby {
</span></span><span style="display:flex;"><span>    code <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;event.set(&#39;timestamp&#39;, (event.get(&#39;@timestamp&#39;).to_f * 1000 * 1000).floor - event.get(&#39;duration&#39;))&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>uuid {
</span></span><span style="display:flex;"><span>    target <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;id&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mutate {
</span></span><span style="display:flex;"><span>    rename <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;CorrelationId&#34;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;traceid&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;Context&#34;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;name&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;ApplicationName&#34;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;[localEndpoint][serviceName]&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    remove_field <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;@timestamp&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mutate {
</span></span><span style="display:flex;"><span>    gsub <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;id&#34;</span>, <span style="color:#e6db74">&#34;-&#34;</span>, <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    gsub <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;traceid&#34;</span>, <span style="color:#e6db74">&#34;-&#34;</span>, <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    lowercase <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;traceid&#34;</span>, <span style="color:#e6db74">&#34;id&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mutate {
</span></span><span style="display:flex;"><span>    gsub <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;id&#34;</span>, <span style="color:#e6db74">&#34;(^.{1,16}).*$&#34;</span>, <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\1</span><span style="color:#e6db74">&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>prune {
</span></span><span style="display:flex;"><span>    whitelist_names <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;id&#34;</span>, <span style="color:#e6db74">&#34;traceid&#34;</span>, <span style="color:#e6db74">&#34;name&#34;</span>, <span style="color:#e6db74">&#34;timestamp&#34;</span>, <span style="color:#e6db74">&#34;duration&#34;</span>, <span style="color:#e6db74">&#34;localEndpoint&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="publishing-to-jaeger">Publishing to Jaeger</h3>
<p>When publishing to the Jaeger API, you have to send it an array of json objects.  To achieve this in the <code>http</code> output plugin, we can enable the <code>format =&gt; json_batch</code>, which will cause the HTTP client to buffer some events and then send them all at once.  So more efficiency, and no extra code on our part.</p>
<p>To help make testing easier, I publish to two different HTTP endpoints: the Jaeger docker container running on my host machine, and to a <a href="http://requestloggerbin.herokuapp.com/">Request Logger Bin</a>; where I can inspect the response if something is reported as a failure by Jaeger, and replay it (via the <a href="https://insomnia.rest/">Insomnia</a> REST client) and check error messages returned from Jaeger.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>output {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span>@metadata<span style="color:#f92672">][</span>type<span style="color:#f92672">]</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;jaeger&#34;</span> {
</span></span><span style="display:flex;"><span>        http {
</span></span><span style="display:flex;"><span>            url <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;http://192.168.0.115:9411/api/v2/spans&#34;</span>
</span></span><span style="display:flex;"><span>            format <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;json_batch&#34;</span>
</span></span><span style="display:flex;"><span>            http_method <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;post&#34;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        http {
</span></span><span style="display:flex;"><span>            url <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;http://requestloggerbin.herokuapp.com/bin/ff3da5b2-ec57-4611-ada8-b360ab38830c&#34;</span>
</span></span><span style="display:flex;"><span>            format <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;json_batch&#34;</span>
</span></span><span style="display:flex;"><span>            http_method <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#34;post&#34;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># normal message handling: elasticsearch etc.</span>
</span></span><span style="display:flex;"><span>        stdout { codec <span style="color:#f92672">=&gt;</span> rubydebug }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I also used LogStash&rsquo;s log output by tailing the log file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>tail -f /var/log/logstash/logstash-plain.log
</span></span></code></pre></div><p>Eventually, I had a working LogStash configuration and can view application traces in Jaeger.</p>
<h2 id="problems">Problems</h2>
<p>One thing I cannot figure out how to do is sending the <code>tags</code> property to Jaeger.  The Zipkin (and OpenTracing) APIs specify tags to be an object, e.g.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;traceid&#34;</span>: <span style="color:#e6db74">&#34;1ee98d32185e41faba146c151ce8e27d&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;id&#34;</span>: <span style="color:#e6db74">&#34;8377a6dae87947d7&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;timestamp&#34;</span>: <span style="color:#ae81ff">1545321238784000</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;duration&#34;</span>: <span style="color:#ae81ff">409000</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;localEndpoint&#34;</span>: { <span style="color:#f92672">&#34;serviceName&#34;</span>: <span style="color:#e6db74">&#34;PersonInformationService&#34;</span> },
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;SomeOperation&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;tags&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;CorrelationID&#34;</span>: <span style="color:#e6db74">&#34;1ee98d32-185e-41fa-ba14-6c151ce8e27d&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;db.name&#34;</span>: <span style="color:#e6db74">&#34;test-blahblah&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>But LogStash wants the <code>tags</code> property to be an array of strings, and even using the <code>remove_field</code> on <code>tags</code> and then manually populating it doesn&rsquo;t work.  Currently, I don&rsquo;t <em>need</em> anything in the tags, but it would be nice to have it working.  I should ask on the Elastic forums perhaps.</p>
<h2 id="wrapping-up">Wrapping Up</h2>
<p>This post turned out to be a lot longer than I was expecting, but hopefully, it was interesting.  Next time I&rsquo;ll try and go through how I do testing of immutable infrastructure, as well as local development of the base images.</p>
]]></content:encoded></item><item><title>Against SemVer</title><link>https://andydote.co.uk/2018/12/16/against-semver/</link><pubDate>Sun, 16 Dec 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/12/16/against-semver/</guid><description>Well, for Applications &amp;amp; Services at least. For libraries, SemVer is the way to go, assuming you can agree on what a breaking change is defined as.
But when it comes to Applications (or SaaS products, websites, etc.) SemVer starts to break down. The problem starts with the most obvious: What is a breaking change? How about a minor change?
What&amp;rsquo;s in a change? For example, if we were to change the UI of a web application, which caused no backend changes, from the user perspective it is probably a breaking change, but not from the developers perspective.</description><content:encoded><![CDATA[<p>Well, for Applications &amp; Services at least.  For libraries, SemVer is the way to go, assuming you can agree on what a breaking change is defined as.</p>
<p>But when it comes to Applications (or SaaS products, websites, etc.) SemVer starts to break down.  The problem starts with the most obvious:  What is a breaking change? How about a minor change?</p>
<h2 id="whats-in-a-change">What&rsquo;s in a change?</h2>
<p>For example, if we were to change the UI of a web application, which caused no backend changes, from the user perspective it is probably a breaking change, but not from the developers perspective.
What about changing a backend process, for example, the way the service is billed?  How about adding a new step in the middle of an existing process?</p>
<p>These are all hard questions to answer, and I imagine there are many many edge cases and things which are not clear as to what level of change they are.</p>
<h2 id="clash-of-the-versions">Clash of the Versions</h2>
<p>The next problem stems from the fact that we don&rsquo;t (often) do Trunk Based Development for applications.  We have a long-lived (1-2 weeks) feature branch, which might get pushed to a test environment multiple times as tasks are completed.  If we SemVer these deployments, when a bug fix happens on the master branch, we can end up with a version clash, and can&rsquo;t deploy.</p>
<p><img loading="lazy" src="semver-clash.png" alt="branching, showing a clash of SemVer by having concurrent branches"  />
</p>
<p>While this is a problem, we can solve it easily - we can use the <code>-pre</code> or <code>-beta</code> suffix for the feature branch, and then remove the suffix and increment the version number when the feature is fully deployed.  This, however, is adding a little more complexity to the process - mostly on the human side of things this time.</p>
<p>I would rather avoid the complexity (machine and human) entirely so instead opt for a different solution: Dates.</p>
<h2 id="how-about-a-date">How about a Date?</h2>
<p>Date stamps to the rescue! Our builds now use the following format:</p>
<pre tabindex="0"><code>&lt;year&gt;.&lt;month&gt;.&lt;day&gt;.&lt;build_number&gt;
</code></pre><p>We did consider using the time (represented as <code>.hhmm</code>) instead of the <code>build_number</code>, but it would have been possible to clash if two builds triggered at the same minute, and the <code>build_number</code> is guaranteed uniqueness.  By using an automatic format, we gain a few advantages:</p>
<ul>
<li>No confusion on whether a change is a major, minor, or patch</li>
<li>No clashes on multiple branches</li>
<li>No human input required (marking things as <code>pre</code> or <code>beta</code>)</li>
<li>Answers the &ldquo;when was this built&rdquo; question</li>
</ul>
<h2 id="what-about-the-libraries">What about the libraries?</h2>
<p>The libraries have a very different set of requirements, and one versioning scheme doesn&rsquo;t seem to fit both very well, so there is no point trying to force the matter.</p>
]]></content:encoded></item><item><title>Stopping Caring...</title><link>https://andydote.co.uk/2018/12/08/stopping-caring/</link><pubDate>Sat, 08 Dec 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/12/08/stopping-caring/</guid><description>&amp;hellip;about GitHub open source commit streak.
This is, I think, partially triggered by Marc Gravell&amp;rsquo;s post. I currently have had a GitHub commit streak going on 1878 days. The other night I realised, that I don&amp;rsquo;t care about it any more, and more so, I&amp;rsquo;m not sure why I did to start with.
I didn&amp;rsquo;t even mean to start doing it. I just noticed one day that I had done something every day for a couple of weeks, and vaguely wondered how long I could keep that up for.</description><content:encoded><![CDATA[<p>&hellip;about GitHub open source commit streak.</p>
<p>This is, I think, partially triggered by <a href="https://blog.marcgravell.com/2018/12/a-thanksgiving-carol.html">Marc Gravell&rsquo;s post</a>.  I currently <del>have</del> had a GitHub commit streak going on 1878 days.  The other night I realised, that I don&rsquo;t care about it any more, and more so, I&rsquo;m not sure why I did to start with.</p>
<p>I didn&rsquo;t even mean to start doing it.  I just noticed one day that I had done something every day for a couple of weeks, and vaguely wondered how long I could keep that up for.  It turns out the answer is &ldquo;quite a while&rdquo;.  For the most part, it was easy to do - just a small commit a day, it only takes a few minutes right?  But more and more often, I noticed that it was having a negative effect on <em>what</em> I was writing.</p>
<p>For instance, I wanted to learn about <a href="https://www.nomadproject.io/">Nomad</a>, but had been putting it off, as it wouldn&rsquo;t involve making any public commits.  So each time I came to start, I couldn&rsquo;t until I had done a public commit, and once that commit had was done, so was my motivation.  Which meant learning Nomad didn&rsquo;t happen for a long time.</p>
<p>It also affected what I did with old repositories on GitHub -  I wanted to remove some which serve no useful purpose any more, but I couldn&rsquo;t do that either, as that would remove their commits from the streak.  Likewise, I have a new version of my <a href="https://github.com/Pondidum/12factor-demo">TwelveFactor</a> repository, but I really should remove the old version. But doing so would remove the commits from the streak too.  So, as you might have guessed, I haven&rsquo;t done that either.  Maybe soon.  I have a lot of writing to go with it too.</p>
<p>On the subject of writing, that also suffered.  It takes a lot of effort to sit down and start writing a post, but usually, the words flow pretty smoothly once I am going.  But knowing I need to spare some energy for the commit of the day makes it even harder to start writing, so I just haven&rsquo;t been.  There are a lot of drafts with bullet-point lists waiting though, so maybe they will begin to see the light of day soon.</p>
<p>The irony is not lost on me that making this post will increase the commit count (GitHub pages based blog), so I am not committing (or finishing) this post until at least a day has passed.</p>
<p>I decided on the 7th December 2018 not to make any commits.  After that had happened - the act of deciding mind you, not the day itself, I felt a lot better.  I do not need to do anything. I can go and finish the book a friend recommended me.  I can spend my evenings learning about things I want to.  Or just do nothing some evenings.</p>
<p>No more worrying about public commits.  It&rsquo;s just not worth it.</p>
]]></content:encoded></item><item><title>Microservices or Components</title><link>https://andydote.co.uk/2018/10/28/microservices-or-components/</link><pubDate>Sun, 28 Oct 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/10/28/microservices-or-components/</guid><description>One of the reasons people list for using MicroServices is that it helps enforce separation of concerns. This is usually achieved by adding a network boundary between the services. While this is useful, it&amp;rsquo;s not without costs; namely that you&amp;rsquo;ve added a set of new failure modes: the network. We can achieve the same separation of concerns within the same codebase if we put our minds to it. In fact, this is what Simon Brown calls a Modular Monolith, and DHH calls the Majestic Monolith.</description><content:encoded><![CDATA[<p>One of the reasons people list for using MicroServices is that it helps enforce separation of concerns.  This is usually achieved by adding a network boundary between the services.  While this is useful, it&rsquo;s not without costs; namely that you&rsquo;ve added a set of new failure modes: the network. We can achieve the same separation of concerns within the same codebase if we put our minds to it.  In fact, this is what <a href="https://www.simonbrown.je/">Simon Brown</a> calls a <a href="https://www.codingthearchitecture.com/presentations/sa2015-modular-monoliths">Modular Monolith</a>, and <a href="https://twitter.com/dhh">DHH</a> calls the <a href="https://m.signalvnoise.com/the-majestic-monolith-29166d022228">Majestic Monolith</a>.</p>
<p>We recently needed to expand an existing service to have some new functionality.  The current process looks something like this, where the user has done something which will eventually return them a URL which can be clicked to get to a web page to see the results.</p>
<p><img loading="lazy" src="microservice-existing.png" alt="api call does some work, returns a result_url which points to a web interface"  />
</p>
<p>The new process is an additional authentication challenge which the user will need to complete before they can get to the final results page.  The new process looks like this:</p>
<p><img loading="lazy" src="microservice-challenge.png" alt="api call does work, makes a request to challenge API, passing the result_url as an argument.  The challenge-response returns a challenge_url, which is returned to the user instead of the return_url"  />
</p>
<h2 id="design-decisions">Design Decisions</h2>
<p>Currently, the challenge functionality will only be used by this one service, but there is a high probability that we will need it for other services in the future too.  At this point we have a decision to make: do we keep this functionality in-process, or make a separate microservice for it?</p>
<h3 id="time-to-live">Time To Live</h3>
<p>The first trade-off is time:  it is slightly quicker to make it in-process, but if we do want to use this from somewhere else later, we&rsquo;ll need to extract it; which is more work.  The key here is &ldquo;if&rdquo; - we don&rsquo;t know for sure that other services will need this exact functionality.</p>
<p>If we keep the new API and UI within the existing API and UI projects, we can also make some code reuse: there is a data store, data access tooling, permissions, styles that can be reused.  Also, all of our infrastructure such as logging and monitoring is already in place, which will save us some time too.</p>
<h3 id="api-risk">API Risk</h3>
<p>We want to avoid deploying a service which then needs to undergo a lot of rework in the future if the second and third users of it have slightly different requirements.  If we build it as a separate service now, will we be sure we are making something which is generic and reusable by other services?  Typically you only get the answer to this question after the second or third usage, so it seems unlikely that we would get our API design perfect on the first attempt.</p>
<h3 id="technical-risks">Technical Risks</h3>
<p>If we are to go the separate service route, we are introducing new failure modes to the existing API.  What if the challenge API is down? What if the request times out? Are we using HTTP or a Message Broker to communicate with it?</p>
<p>If we keep the service in-process to start with we can eliminate all of these concerns.  Luckily, we tend to have very thin controllers and make use of <a href="https://github.com/jbogard/MediatR">Mediatr</a>, so the actual implementation of how the remote call is made can be hidden in the message handler to a certain extent.</p>
<h3 id="technical-decisions">Technical Decisions</h3>
<p>As alluded to in the Time To Live point, we can reuse the existing data store and data access code, but this is a tradeoff in itself: what if the current storage tech is not quite ideal for the new requirements?</p>
<p>If the current service makes use of a complex Entity Framework model, but the new service is so simple that Dapper makes more sense, do we introduce the new dependency or not?  What if we wanted to migrate away from one datastore to another (e.g. removing all MongoDB usage in favour of Postgres), but this is already using Mongo?  We&rsquo;d be increasing our dependency on a datastore we are explicitly trying to migrate away from.</p>
<p>All this assumes we want to write the service in the same programming language as the existing service!  In our case we do but it&rsquo;s worth considering if you have multiple languages in use already.</p>
<p>Finally on the data storefront, if we decide to extract this as a separate service later, we will have to take into account data migrations, and how we can handle that with little if any, downtime.</p>
<h2 id="the-decision">The Decision</h2>
<p>After weighing up all these points (and a few others), we decided to keep the service inside the existing services.  The Challenge API will live in its own area in the current API, and likewise, the Challenge UI will live in its own area in the existing UI.</p>
<p>How do we go about keeping it all separated though?</p>
<ul>
<li><strong>Communication</strong> we discuss all changes we want to make anyway, so the first line of defence to preventing the code becoming tightly coupled are these discussions.</li>
<li><strong>Pull Requests</strong> someone will notice you are doing something which is reducing the separation, and a discussion about how to avoid this will happen.</li>
<li><strong>Naming Conventions</strong> the Challenge API shares no naming of properties with the existing API.  For example, the current API passes in a <code>results_url</code> and <code>results_id</code>, but the Challenge API stores and refers to these as the <code>redirect_url</code> and <code>external_id</code>.</li>
<li><strong>Readme</strong> it&rsquo;ll go into the repository&rsquo;s readme file, along with any other notes which developers will find useful.  The sequence diagrams we drew (with much more detail) will also go in here.</li>
</ul>
<h2 id="technical-debt">Technical Debt?</h2>
<p>The final question on this decision is &ldquo;Isn&rsquo;t this technical debt we are introducing?&rdquo;.  The answer I feel is &ldquo;no&rdquo;, it feels much closer to applying the YAGNI Principle (You Ain&rsquo;t Gonna Need It).  While there is work in the backlog which can use a Challenge API at the moment, that doesn&rsquo;t necessarily mean it will still be there next week, or if it will be pushed further back or changed later.</p>
<p>In the end, the meeting where we came up with this and drew things on the whiteboard together was productive, and likely much shorter than it took me to write all this down.  We were able to resist the &ldquo;cool hip microservice&rdquo; trend and come up with a design which is pretty contained and composable with other systems in the future.</p>
<p>If after all this discussion we decided to go the MicroService route, I would still be happy with the decision, as we would have all this material to look back on and justify our choice, rather than waving our hands about and shouting &ldquo;but microservices&rdquo; loudly.</p>
<p>How do you go about designing systems?  Microservice all the things? Monolith all the things? Or something in between which makes the most sense for the situation at hand?</p>
]]></content:encoded></item><item><title>SketchNotes: Finding Your Service Boundaries</title><link>https://andydote.co.uk/2018/09/10/sketchnotes-finding-service-boundaries/</link><pubDate>Mon, 10 Sep 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/09/10/sketchnotes-finding-service-boundaries/</guid><description>At NDC Oslo this year, I attended Adam Ralph&amp;rsquo;s talk on Finding Your Service Boundaries. I enjoyed it a lot, and once the video came out, I rewatched it, and decided to have a go at doing a “sketchnotes”, which I shared on Twitter, which people liked!
I’ve never done one before, but it was pretty fun. I made it in OneNote, zoomed out a lot, and took a screenshot.</description><content:encoded><![CDATA[<p>At NDC Oslo this year, I attended <a href="https://twitter.com/adamralph">Adam Ralph&rsquo;s</a> talk on <a href="https://www.youtube.com/watch?v=tVnIUZbsxWI">Finding Your Service Boundaries</a>. I enjoyed it a lot, and once the video came out, I rewatched it, and decided to have a go at doing a “sketchnotes”, which I <a href="https://twitter.com/Pondidum/status/1038807452559532032">shared on Twitter</a>, which people liked!</p>
<p>I’ve never done one before, but it was pretty fun. I made it in OneNote, zoomed out a lot, and took a screenshot.</p>
<p>Click for huuuuge!</p>
<p><a href="sketchnotes-ndc-oslo-2018-serviceboundaries.png"><img loading="lazy" src="sketchnotes-ndc-oslo-2018-serviceboundaries-preview.png" alt="sketchnotes - finding your service boundaries"  />
</a></p>
]]></content:encoded></item><item><title>Semantic Configuration Validation: Earlier</title><link>https://andydote.co.uk/2018/09/08/semantic-configuration-validation-earlier/</link><pubDate>Sat, 08 Sep 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/09/08/semantic-configuration-validation-earlier/</guid><description>After my previous post on Validating Your Configuration, one of my colleagues made an interesting point, paraphrasing:
I want to know if the configuration is valid earlier than that. At build time preferably. I don&amp;rsquo;t want my service to not start if part of it is invalid.
There are two points here, namely when to validate, and what to do with the results of validation.
Handling Validation Results If your configuration is invalid, you&amp;rsquo;d think the service should fail to start, as it might be configured in a dangerous manner.</description><content:encoded><![CDATA[<p>After my previous post on <a href="/2018/08/26/validate-configuration/">Validating Your Configuration</a>, one of my colleagues made an interesting point, paraphrasing:</p>
<blockquote>
<p>I want to know if the configuration is valid earlier than that.  At build time preferably.  I don&rsquo;t want my service to not start if part of it is invalid.</p>
</blockquote>
<p>There are two points here, namely when to validate, and what to do with the results of validation.</p>
<h2 id="handling-validation-results">Handling Validation Results</h2>
<p>If your configuration is invalid, you&rsquo;d think the service should fail to start, as it might be configured in a dangerous manner.  While this makes sense for some service, others might need to work differently.</p>
<p>Say you have an API which supports both writing and reading of a certain type of resource.  The read will return you a resource of some form, and the write side will trigger processing of a resource (and return you <a href="https://httpstatuses.com/202">a 202 Accepted, obviously</a>).</p>
<p>What happens if your configuration just affects the write side of the API? Should you prevent people from reading too?  Probably not, but again it depends on your domain as to what makes sense.</p>
<h2 id="validating-at-build-time">Validating at Build Time</h2>
<p>This is the far more interesting point (to me).  How can we modify our build to validate that the environment&rsquo;s configuration is valid?  We have the code to do the validation: we have automated tests, and we have a configuration validator class (in this example, implemented using <a href="https://github.com/JeremySkinner/FluentValidation">FluentValidation</a>).</p>
<p>Depending on where your master configuration is stored, the next step can get much harder.</p>
<h3 id="local-configuration">Local Configuration</h3>
<p>If your configuration is in the current repository (<a href="/2018/08/07/managing-consul-appsettings/">as it should be</a>) then it will be no problem to read.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ConfigurationTests</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> IEnumerable&lt;<span style="color:#66d9ef">object</span>[]&gt; AvailableEnvironments =&gt; Enum
</span></span><span style="display:flex;"><span>        .GetValues(<span style="color:#66d9ef">typeof</span>(Environments))
</span></span><span style="display:flex;"><span>        .Cast&lt;Environments&gt;()
</span></span><span style="display:flex;"><span>        .Select(e =&gt; <span style="color:#66d9ef">new</span> <span style="color:#66d9ef">object</span>[] { e });
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">    [Theory]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">    [MemberData(nameof(AvailableEnvironments))]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Environment_specific_configuration_is_valid(Environments environment)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> config = <span style="color:#66d9ef">new</span> ConfigurationBuilder()
</span></span><span style="display:flex;"><span>            .AddJsonFile(<span style="color:#e6db74">&#34;config.json&#34;</span>)
</span></span><span style="display:flex;"><span>            .AddJsonFile(<span style="color:#e6db74">$&#34;config.{environment}.json&#34;</span>, optional: <span style="color:#66d9ef">true</span>)
</span></span><span style="display:flex;"><span>            .Build()
</span></span><span style="display:flex;"><span>            .Get&lt;AppConfiguration&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> validator = <span style="color:#66d9ef">new</span> AppConfigurationValidator();
</span></span><span style="display:flex;"><span>        validator.ValidateAndThrow(config);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Given the following two configuration files, we can make it pass and fail:</p>
<p><code>config.json:</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Callback&#34;</span>: <span style="color:#e6db74">&#34;https://localhost&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Timeout&#34;</span>: <span style="color:#e6db74">&#34;00:00:30&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;MaxRetries&#34;</span>: <span style="color:#ae81ff">100</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><code>config.local.json:</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;MaxRetries&#34;</span>: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="remote-configuration">Remote Configuration</h3>
<p>But what if your configuration is not in the local repository, or at least, not completely there?  For example, have a lot of configuration in Octopus Deploy, and would like to validate that at build time too.</p>
<p>Luckily Octopus has a Rest API (and <a href="https://www.nuget.org/packages/Octopus.Client/">acompanying client</a>)  which you can use to query the values.  All we need to do is replace the <code>AddJsonFile</code> calls with an <code>AddInMemoryCollection()</code> and populate a dictionary from somewhere:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#a6e22e">[Theory]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">[MemberData(nameof(AvailableEnvironments))]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task Octopus_environment_configuration_is_valid(Environments environment)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> variables = <span style="color:#66d9ef">await</span> FetchVariablesFromOctopus(
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;MyDeploymentProjectName&#34;</span>,
</span></span><span style="display:flex;"><span>        environment);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> config = <span style="color:#66d9ef">new</span> ConfigurationBuilder()
</span></span><span style="display:flex;"><span>        .AddInMemoryCollection(variables)
</span></span><span style="display:flex;"><span>        .Build()
</span></span><span style="display:flex;"><span>        .Get&lt;AppConfiguration&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> validator = <span style="color:#66d9ef">new</span> AppConfigurationValidator();
</span></span><span style="display:flex;"><span>    validator.ValidateAndThrow(config);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Reading the variables from Octopus&rsquo; API requires a bit of work as you don&rsquo;t appear to be able to ask for all variables which would apply if you deployed to a specific environment, which forces you into building the logic yourself.  However, if you are just using Environment scoping, it shouldn&rsquo;t be too hard.</p>
<h3 id="time-delays">Time Delays</h3>
<p>Verifying the configuration at build time when your state is fetched from a remote store is not going to solve all your problems, as this little diagram illustrates:</p>
<p><img loading="lazy" src="versioning-time.png" alt="test pass, a user changes value, deployment happens, startup fails"  />
</p>
<p>You need to validate in both places: early on in your process, and on startup.  How you handle the configuration being invalid doesn&rsquo;t have to be the same in both places:</p>
<ul>
<li>In the build/test phase, fail the build</li>
<li>On startup, raise an alarm, but start if reasonable</li>
</ul>
<p>Again, how you handle the configuration errors when your application is starting is down to your domain, and what your application does.</p>
]]></content:encoded></item><item><title>Feature Toggles with Consul</title><link>https://andydote.co.uk/2018/09/06/consul-feature-toggles/</link><pubDate>Thu, 06 Sep 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/09/06/consul-feature-toggles/</guid><description>Feature Toggles are a great way of helping to deliver working software, although there are a few things which could go wrong. See my talk Feature Toggles: The Good, The Bad and The Ugly for some interesting stories and insights on it!
I was talking with a colleague the other day about how you could go about implementing Feature Toggles in a centralised manner into an existing system, preferably with a little overhead as possible.</description><content:encoded><![CDATA[<p>Feature Toggles are a great way of helping to deliver working software, although there are a few things which could go wrong.  See my talk <a href="https://www.youtube.com/watch?v=r7VI5x2XKXw">Feature Toggles: The Good, The Bad and The Ugly</a> for some interesting stories and insights on it!</p>
<p>I was talking with a colleague the other day about how you could go about implementing Feature Toggles in a centralised manner into an existing system, preferably with a little overhead as possible.  The most obvious answer is to use a SAAS solution such as <a href="https://launchdarkly.com/">LauchDarkly</a>, but what if you either don&rsquo;t want to or can&rsquo;t use a SAAS solution?</p>
<p>What if we already are using Consul for things such as service discovery, could we use the key-value store as a basic Feature Toggle service?  It has a few advantages:</p>
<ul>
<li>Consul is already in place, so there is no extra infrastructure required and no additional costs</li>
<li>Low stopping cost - If we decide we don&rsquo;t want to use Consul, or not to use Toggles at all, we can stop</li>
<li>Low learning curve - we know how to use Consul already</li>
<li>Security - we can make use of Consul&rsquo;s <a href="https://www.consul.io/docs/guides/acl.html#key-value-rules">ACL</a> to allow services to only read, and operators to write Feature Toggles.</li>
</ul>
<p>There are also some downsides to consider too:</p>
<ul>
<li>We&rsquo;d effectively be reinventing the wheel</li>
<li>There won&rsquo;t be any &ldquo;value protection&rdquo; on the settings (nothing stopping us putting an int into a field which will be parsed as a guid for example)</li>
<li>No statistics - we won&rsquo;t be able to tell if a value is used still</li>
<li>No fine-grained control - unless we build some extra hierarchies, everyone gets the same value for a given key</li>
</ul>
<p>So what would our system look like?</p>
<p><img loading="lazy" src="consul-feature-toggles.png" alt="write to consul kv store, results distributed to other consul instances"  />
</p>
<p>It&rsquo;s pretty straightforward.  We already have a Consul Cluster, and then there are several machines with Consul clients running on them, as well as a Container Host with Consul too.</p>
<p>Any configuration written to a Consul node is replicated to all other nodes, so our user can write values to any node to get it to the rest of the cluster.</p>
<p>As mentioned earlier, we can use the <a href="https://www.consul.io/docs/guides/acl.html#key-value-rules">ACL</a> system to lock things down.  Our services will have a read-only role, and our updating user will have a writeable role.</p>
<h2 id="what-next">What Next?</h2>
<p>Assuming this system covers enough of what we want to do, the next steps might be to make some incremental improvements in functionality, although again I would suggest looking into not reinventing the wheel&hellip;</p>
<h3 id="statistics">Statistics</h3>
<p>While we can&rsquo;t use Consul to collect statistics on what keys are being read, we could provide this functionality by making a small client library which would log the queries and send them somewhere for aggregation.</p>
<p>Most microservice environments have centralised logging or monitoring (and if they don&rsquo;t, they really should), so we can use this to record toggle usage.</p>
<p>This information would be useful to have in the same place you set the feature toggles, which brings us nicely onto the next enhancement.</p>
<h3 id="user-interface">User Interface</h3>
<p>A simple static website could be used to read all the Toggles and their relevant states and statistics and provide a way of setting them.  The UI could further be expanded to give some type safety, such as extra data indicating what type a given key&rsquo;s value should be.</p>
<h3 id="fine-grained-values">FIne Grained Values</h3>
<p>Currently, everyone has the same value for a given key, but the system could be expanded to be more fine-grained.  Rather than storing a feature toggle in the current form:</p>
<pre tabindex="0"><code>/kv/toggles/fast-rendering =&gt; true
</code></pre><p>We could add another level which would indicate a grouping:</p>
<pre tabindex="0"><code>/kv/toggles/fast-rendering/early-access =&gt; true
/kv/toggles/fast-rendering/others =&gt; false
</code></pre><p>At this point though, you are starting to add a lot of complexity.  Think about whether you are solving the right problem! Choose where you are spending your <a href="http://mcfunley.com/choose-boring-technology">Innovation Tokens</a>.</p>
<h2 id="wrapping-up">Wrapping Up</h2>
<p>Should you do this? Maybe. Probably not.  I don&rsquo;t know your system and what infrastructure you have available, so I don&rsquo;t want to give any blanket recommendations.</p>
<p>I will, however, suggest that if you are starting out with Feature Toggles, <strong>go for something simple first</strong>.  My current team&rsquo;s first use of a Feature Toggle was just a setting in the <code>web.config</code>, and we just changed the value of it when we wanted the new functionality to come on.</p>
<p>See what works for you, and if you start needing something more complicated than just simple key-value toggles, have a look into an existing system.</p>
]]></content:encoded></item><item><title>Validate Your Configuration</title><link>https://andydote.co.uk/2018/08/26/validate-configuration/</link><pubDate>Sun, 26 Aug 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/08/26/validate-configuration/</guid><description>As I have written many times before, your application&amp;rsquo;s configuration should be strongly typed and validated that it loads correctly at startup.
This means not only that the source values (typically all represented as strings) can be converted to the target types (int, Uri, TimeSpan etc) but that the values are semantically valid too.
For example, if you have a web.config file with the following AppSetting, and a configuration class to go with it:</description><content:encoded><![CDATA[<p>As I have <a href="/2016/12/06/strong-type-all-the-configurations/">written</a> many <a href="/2017/11/09/configuration-composition/">times</a> before, your application&rsquo;s configuration should be strongly typed and validated that it loads correctly at startup.</p>
<p>This means not only that the source values (typically all represented as strings) can be converted to the target types (<code>int</code>, <code>Uri</code>, <code>TimeSpan</code> etc) but that the values are <strong>semantically valid</strong> too.</p>
<p>For example, if you have a <code>web.config</code> file with the following <code>AppSetting</code>, and a configuration class to go with it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;configuration&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;appSettings&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;add</span> <span style="color:#a6e22e">key=</span><span style="color:#e6db74">&#34;Timeout&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;20&#34;</span> <span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/appSettings&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/configuration&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Configuration</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> TimeSpan Timeout { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We can now load the configuration using <a href="https://github.com/pondidum/stronk">Stronk</a> (or Microsoft.Extensions.Configuration if you&rsquo;re on dotnet core), and inspect the contents of the <code>Timeout</code> property:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> config = <span style="color:#66d9ef">new</span> StronkConfig().Build&lt;Configuration&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Console.WriteLine(config.Timeout); <span style="color:#75715e">// 20 days, 0 hours, 0 minutes, 0 seconds</span>
</span></span></code></pre></div><p>Oops.  <strong>A timeout of 20 days is probably a <em>little</em> on the high side!</strong>  The reason this happened is that to parse the string value we use <code>TimeSpan.Parse(value)</code>, which will interpret it as days if no other units are specified.</p>
<h2 id="how-to-validate">How to validate?</h2>
<p>There are several ways we could go about fixing this, from changing to use <code>TimeSpan.ParseExact</code>, but then we need to provide the format string from somewhere, or force people to use Stronk&rsquo;s own decision on format strings.</p>
<p>Instead, we can just write some validation logic ourselves.  If it is a simple configuration, then writing a few statements inline is probably fine:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> config = <span style="color:#66d9ef">new</span> StronkConfig()
</span></span><span style="display:flex;"><span>    .Validate.Using&lt;Configuration&gt;(c =&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (c.Timeout &lt; TimeSpan.FromSeconds(<span style="color:#ae81ff">60</span>) &amp;&amp; c.Timeout &gt; TimeSpan.Zero)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> ArgumentOutOfRangeException(nameof(c.Timeout), <span style="color:#e6db74">$&#34;Must be greater than 0, and less than 1 minute&#34;</span>);
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>    .Build&lt;Configuration&gt;();
</span></span></code></pre></div><p>But we can make it much clearer by using a validation library such as <a href="https://github.com/JeremySkinner/FluentValidation">FluentValidation</a>, to do the validation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> config = <span style="color:#66d9ef">new</span> StronkConfig()
</span></span><span style="display:flex;"><span>    .Validate.Using&lt;Configuration&gt;(c =&gt; <span style="color:#66d9ef">new</span> ConfigurationValidator().ValidateAndThrow(c))
</span></span><span style="display:flex;"><span>    .Build&lt;Configuration&gt;();
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ConfigurationValidator</span> : AbstractValidator&lt;Configuration&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">readonly</span> HashSet&lt;<span style="color:#66d9ef">string</span>&gt; ValidHosts = <span style="color:#66d9ef">new</span> HashSet&lt;<span style="color:#66d9ef">string</span>&gt;(
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">new</span>[] { <span style="color:#e6db74">&#34;localhost&#34;</span>, <span style="color:#e6db74">&#34;internal&#34;</span> },
</span></span><span style="display:flex;"><span>        StringComparer.OrdinalIgnoreCase);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> ConfigurationValidator()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        RuleFor(x =&gt; x.Timeout)
</span></span><span style="display:flex;"><span>            .GreaterThan(TimeSpan.Zero)
</span></span><span style="display:flex;"><span>            .LessThan(TimeSpan.FromMinutes(<span style="color:#ae81ff">2</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        RuleFor(x =&gt; x.Callback)
</span></span><span style="display:flex;"><span>            .Must(url =&gt; url.Scheme == Uri.UriSchemeHttps)
</span></span><span style="display:flex;"><span>            .Must(url =&gt; ValidHosts.Contains(url.Host));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Here, not only are we checking the <code>Timeout</code> is in a valid range, but that our <code>Callback</code> is HTTPS and that it is going to a domain on an Allow-List.</p>
<h2 id="what-should-i-validate">What should I validate?</h2>
<p>Everything?  If you have properties controlling the number of threads an application uses, probably checking it&rsquo;s a positive number, and less than <code>x * Environment.ProcessorCount</code> (for some value of x) is probably a good idea.</p>
<p>If you are specifying callback URLs in the config file, checking they are in the right domain/scheme would be a good idea (e.g. must be https, must be in a domain allow-list).</p>
<p>How do you check your configuration isn&rsquo;t going to bite you when an assumption turns out to be wrong?</p>
]]></content:encoded></item><item><title>Branching and Red Builds</title><link>https://andydote.co.uk/2018/08/10/red-builds/</link><pubDate>Fri, 10 Aug 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/08/10/red-builds/</guid><description>So this is a bit of a rant&amp;hellip;but hopefully with some solutions and workarounds too. So let&amp;rsquo;s kick things off with a nice statement:
I hate broken builds.
So everyone basically agrees on this point I think. The problem is that I mean all builds, including ones on shared feature branches.
Currently, I work on a number of projects which uses small(ish) feature branches. The way this works is that the team agrees on a new feature to work on creates a branch, and then each developer works on tasks, committing on their own branches, and Pull-Requesting to the feature branch.</description><content:encoded><![CDATA[<p>So this is a bit of a rant&hellip;but hopefully with some solutions and workarounds too. So let&rsquo;s kick things off with a nice statement:</p>
<p>I hate broken builds.</p>
<p>So everyone basically agrees on this point I think.  The problem is that I mean <em>all</em> builds, including ones on shared feature branches.</p>
<p>Currently, I work on a number of projects which uses small(ish) feature branches.  The way this works is that the team agrees on a new feature to work on creates a branch, and then each developer works on tasks, committing on their own branches, and Pull-Requesting to the feature branch.  Once the feature branch is completed, it&rsquo;s deployed and merged to master.  We&rsquo;ll ignore the fact that Trunk Based Development is just better for now.</p>
<p><img loading="lazy" src="branching-features.png" alt="branching, developers working on small tasks being merged into a feature branch"  />
</p>
<p>The problem occurs when one of the first tasks to be completed is writing behaviour (or acceptance) tests.  These are written in something like SpecFlow, and call out to stubbed methods which throw <code>NotImplementedException</code> s.  When this gets merged, the feature branch build goes red and stays red until all other tasks are done.  And probably for a little while afterwards too.  Nothing like &ldquo;red-green-refactor&rdquo; when your light can&rsquo;t change away from red!</p>
<h2 id="the-problems">The Problems</h2>
<ul>
<li>Local tests are failing, no matter how much you implement</li>
<li>PullRequests to the feature branch don&rsquo;t have passing build checks</li>
<li>The failing build is failing because:
<ul>
<li>Not everything is implemented yet</li>
<li>A developer has introduced an error, and no one has noticed yet</li>
<li>The build machine is playing up</li>
</ul>
</li>
</ul>
<p><img loading="lazy" src="branching-features-builds.png" alt="branching, developers working on small tasks being merged into a feature branch showing everything as failed builds"  />
</p>
<h2 id="bad-solutions">Bad Solutions</h2>
<p>The first thing we could do is to not run the acceptance tests on a Task branch&rsquo;s build, and only when a feature branch build runs.  This is a bad idea, as someone will have forgotten to check if their task&rsquo;s acceptance tests pass, and will require effort later to fix the broken acceptance tests.</p>
<p>We could also implement the acceptance file and not call any stubbed methods, making the file a text file and non-executable.  This is also a pretty bad idea - how much would you like to bet that it stays non-executable?</p>
<h2 id="the-solution">The Solution</h2>
<p>Don&rsquo;t have the acceptance tests as a separate task.  Instead, split the criteria among the implementation tasks.  This does mean that your other tasks should be Vertical Slices rather than Horizontal, which can be difficult to do depending on the application&rsquo;s architecture.</p>
<h2 id="an-example">An Example</h2>
<p>So let&rsquo;s dream up a super simple Acceptance Criteria:</p>
<ul>
<li>When a user signs up with a valid email which has not been used, they receive a welcome email with an activation link.</li>
<li>When a user signs up with an invalid email, they get a validation error.</li>
<li>When a user signs up with an in-use email, they get an error</li>
</ul>
<p>Note how this is already pretty close to being the tasks for the feature?  Our tasks are pretty much:</p>
<ul>
<li>implement the happy path</li>
<li>implement other scenarios</li>
</ul>
<p>Of course, this means that not everything can be done in parallel - I imagine you&rsquo;d want the happy path task to be done first, and then the other scenarios are probably parallelisable.</p>
<p>So our trade-off here is that we lose some parallelisation, but gain feedback. While this may seem insignificant, it has a significant impact on the overall delivery rate - everyone knows if their tasks are complete or not, and when the build goes red, you can be sure of what introduced the problem.</p>
<p>Not to mention that features are rarely this small - you probably have various separate acceptance criteria, such as being able to view an account page.</p>
<p>Oh, and once you can split your tasks correctly, there is only a small step to getting to do Trunk Based Development.  Which would make me happy.</p>
<p>And developer happiness is important.</p>
]]></content:encoded></item><item><title>Managing AppSettings in Consul</title><link>https://andydote.co.uk/2018/08/07/managing-consul-appsettings/</link><pubDate>Tue, 07 Aug 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/08/07/managing-consul-appsettings/</guid><description>Consul is a great utility to make running your microservice architecture very simple. Amongst other things, it provides Service Discovery, Health Checks, and Configuration. In this post, we are going to be looking at Configuration; not specifically how to read from Consul, but about how we put configuration data into Consul in the first place.
The usual flow for an application using Consul for configuration is as follows:
App Starts Fetches configuration from Consul Configures itself Registers in Consul for Service Discovery Ready Step 2 is very straightforward - you query the local instance of Consul&amp;rsquo;s HTTP API, and read the response into your configuration object (If you&amp;rsquo;re using Microsoft&amp;rsquo;s Configuration libraries on dotnet core, you can use the Consul.</description><content:encoded><![CDATA[<p><a href="https://www.consul.io/">Consul</a> is a great utility to make running your microservice architecture very simple.  Amongst other things, it provides Service Discovery, Health Checks, and Configuration.  In this post, we are going to be looking at Configuration; not specifically how to read from Consul, but about how we put configuration data into Consul in the first place.</p>
<p>The usual flow for an application using Consul for configuration is as follows:</p>
<ol>
<li>App Starts</li>
<li>Fetches configuration from Consul</li>
<li>Configures itself</li>
<li>Registers in Consul for Service Discovery</li>
<li>Ready</li>
</ol>
<p>Step 2 is very straightforward - you query the local instance of Consul&rsquo;s HTTP API, and read the response into your configuration object (If you&rsquo;re using Microsoft&rsquo;s Configuration libraries on dotnet core, you can use <a href="https://www.nuget.org/packages/Consul.Microsoft.Extensions.Configuration/">the Consul.Microsoft.Extensions.Configuration NuGet package</a>).</p>
<p>The question is though, how does the configuration get into Consul in the first place? Obviously, we don&rsquo;t want this to be a manual process, and as Consul&rsquo;s HTTP API supports writing too, it doesn&rsquo;t have to be!  But where is the master copy of the configuration data stored?  Where it should be! In the repository with your code for the application.</p>
<p><img loading="lazy" src="repository-with-config.png" alt="repository structure, config.json, config.test.json and config.prod.json in the root"  />
</p>
<p>By default, all your configuration values should be going into the base configuration (<code>config.json</code>), and only use the environment specific versions (e.g. <code>config.test.json</code> and <code>config.prod.json</code>) when a value needs to differ in some environments.</p>
<h2 id="why-store-config-in-the-repository">Why store config in the repository?</h2>
<p>There are many reasons for putting your configuration into a repository alongside the code it relates to, mostly around answering these questions:</p>
<ul>
<li>When did this key&rsquo;s value change?</li>
<li>Why did this key&rsquo;s value change?</li>
<li>Who changed this (do they have more context for why)?</li>
<li>What values has this key been over time?</li>
<li>How often is this key changing?</li>
</ul>
<p>If a value is changing often with reasons (commit messages) such as &ldquo;scale the thing due to increased traffic&rdquo; and &ldquo;scale the thing back down now it&rsquo;s quiet&rdquo; that starts to tell you that you should be implementing some kind of autoscaling.</p>
<p>If you find out a key is set incorrectly, you can find out how long it&rsquo;s been wrong, and maybe discover that the value is not &ldquo;wrong&rdquo; but &ldquo;not right anymore&rdquo;.</p>
<p>The final piece of this is that you know the value in production will match the value specified - there are no operators accidentally adding a 0 to the end of the number of threads to run etc.</p>
<h2 id="deployment">Deployment</h2>
<p>Now we just need to get the configuration from the file, and into Consul whenever it changes.  As I use <a href="https://terraform.io/">Terraform</a> for deploying changes, I just need to update it to write to Consul also.</p>
<p><img loading="lazy" src="deployment-pipeline-consul.png" alt="deployment pipeline - git to AppVeyor to Terraform.  Terraform writes to consul and updates ECS cluster"  />
</p>
<p>Terraform supports <a href="https://www.terraform.io/docs/providers/consul/r/key_prefix.html">writing to Consul</a> out of the box, however, Terraform can&rsquo;t directly read parse json files, but we can use the <a href="https://www.terraform.io/docs/providers/external/index.html"><code>external</code></a> provider to get around that limitation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cmake" data-lang="cmake"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">data</span> <span style="color:#960050;background-color:#1e0010">&#34;external&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;config_file&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">program</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">[&#34;cat&#34;,</span> <span style="color:#960050;background-color:#1e0010">&#34;config.json&#34;]
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">resource</span> <span style="color:#960050;background-color:#1e0010">&#34;consul_key_prefix&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;appsettings&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">path_prefix</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;appsettings/testapp/&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">subkeys</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${data.external.config_file.result}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span></code></pre></div><p>If we want to take things a step further, and use our environment specific overrides files, we just need to use the <a href="https://stedolan.github.io/jq/">JQ command line tool</a> to merge the two json files, which can be done like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>jq -s <span style="color:#e6db74">&#39;.[0] * .[1]&#39;</span> config.json config.test.json
</span></span></code></pre></div><p>Unfortunately, the <code>external</code> provider has a very specific syntax to how it is called, and we can&rsquo;t just specify the jq command directly.  So it needs to go into another file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#! /bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>jq -s <span style="color:#e6db74">&#39;.[0] * .[1]&#39;</span> <span style="color:#e6db74">&#34;</span>$@<span style="color:#e6db74">&#34;</span>
</span></span></code></pre></div><p>Finally, we can update the <code>external</code> block to use the new script.  You could replace the second file with a merged string containing the current environment (e.g. <code>&quot;config.${var.environment}.json&quot;</code>)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cmake" data-lang="cmake"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">data</span> <span style="color:#960050;background-color:#1e0010">&#34;external&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;config_file&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">program</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">[&#34;bash&#34;,</span> <span style="color:#960050;background-color:#1e0010">&#34;mergeconfigs.sh&#34;,</span> <span style="color:#960050;background-color:#1e0010">&#34;config.json&#34;,</span> <span style="color:#960050;background-color:#1e0010">&#34;config.test.json&#34;]
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span></code></pre></div><p>The complete version of this is <a href="https://github.com/Pondidum/Terraform-Demos/tree/master/manage-consul-keys">here in my Terraform Demos repository</a> on GitHub.</p>
<h2 id="what-next">What next?</h2>
<p>Have a go managing your settings as part of your deployment pipeline!  Depending on what tools you are using, you might need to implement your own HTTP posts to the Consul API, but the advantages of automating this task far outweigh the cost of writing some <code>curl</code> commands in my opinion!</p>
]]></content:encoded></item><item><title>Locking Vault Down with Policies</title><link>https://andydote.co.uk/2018/06/23/vault-locking-it-down-with-policies/</link><pubDate>Sat, 23 Jun 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/06/23/vault-locking-it-down-with-policies/</guid><description>The final part of my Vault miniseries focuses on permissioning, which is provided by Vault&amp;rsquo;s Policies.
As everything in Vault is represented as a path, the policies DSL (Domain Specific Language) just needs to apply permissions to paths to lock things down. For example, to allow all operations on the cubbyhole secret engine, we would define this policy:
path &amp;#34;cubbyhole/*&amp;#34; { capabilities = [&amp;#34;create&amp;#34;, &amp;#34;read&amp;#34;, &amp;#34;update&amp;#34;, &amp;#34;delete&amp;#34;, &amp;#34;list&amp;#34;] } Vault comes with a default policy which allows token operations (such as looking up its own token info, releasing and renewing tokens), and cubbyhole access.</description><content:encoded><![CDATA[<p>The final part of my Vault miniseries focuses on permissioning, which is provided by Vault&rsquo;s <a href="https://www.vaultproject.io/docs/concepts/policies.html">Policies</a>.</p>
<p>As everything in Vault is represented as a path, the policies DSL (Domain Specific Language) just needs to apply permissions to paths to lock things down.  For example, to allow all operations on the <code>cubbyhole</code> secret engine, we would define this policy:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>path <span style="color:#e6db74">&#34;cubbyhole/*&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    capabilities <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;create&#34;</span>, <span style="color:#e6db74">&#34;read&#34;</span>, <span style="color:#e6db74">&#34;update&#34;</span>, <span style="color:#e6db74">&#34;delete&#34;</span>, <span style="color:#e6db74">&#34;list&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>Vault comes with a default policy which allows token operations (such as looking up its own token info, releasing and renewing tokens), and cubbyhole access.</p>
<p>Let&rsquo;s combine the last two posts (<a href="2018/06/17/secret-management-vault-postgres-connection/">Managing Postgres Connection Strings with Vault</a> and <a href="/2018/06/22/vault-secure-communication/">Secure Communication with Vault</a>) and create a Policy which will allow the use of generated database credentials.  If you want more details on the how/why of the set up phase, see those two posts.</p>
<h2 id="setup">Setup</h2>
<p>First, we&rsquo;ll create two containers which will get removed on exit - a Postgres one and a Vault one.  Vault is being started in <code>dev</code> mode, so we don&rsquo;t need to worry about init and unsealing it.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker run --rm -d -p 5432:5432 -e <span style="color:#e6db74">&#39;POSTGRES_PASSWORD=postgres&#39;</span> postgres:alpine
</span></span><span style="display:flex;"><span>docker run --rm -d -p 8200:8200 --cap-add<span style="color:#f92672">=</span>IPC_LOCK -e VAULT_DEV_ROOT_TOKEN_ID<span style="color:#f92672">=</span>vault vault
</span></span></code></pre></div><p>Next, we&rsquo;ll create our Postgres user account which Vault will use to create temporary credentials:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>psql --username postgres --dbname postgres
</span></span><span style="display:flex;"><span>psql&gt; create role VaultAdmin with Login password <span style="color:#e6db74">&#39;vault&#39;</span> CreateRole;
</span></span><span style="display:flex;"><span>psql&gt; grant connect on database postgres to vaultadmin;
</span></span></code></pre></div><p>Let&rsquo;s also configure the environment to talk to Vault as an administrator, and enable the two Vault plugins we&rsquo;ll need:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export VAULT_ADDR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://localhost:8200&#34;</span>
</span></span><span style="display:flex;"><span>export VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;vault&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault auth enable approle
</span></span><span style="display:flex;"><span>vault secrets enable database
</span></span></code></pre></div><p>We&rsquo;ll also set up our database secret engine, and configure database roll creation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault write database/config/postgres_demo <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    plugin_name<span style="color:#f92672">=</span>postgresql-database-plugin <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    allowed_roles<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;default&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    connection_url<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;postgresql://{{username}}:{{password}}@10.0.75.1:5432/postgres?sslmode=disable&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    username<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;VaultAdmin&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    password<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;vault&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vault write database/roles/reader <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    db_name<span style="color:#f92672">=</span>postgres_demo <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    creation_statements<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;CREATE ROLE \&#34;{{name}}\&#34; WITH LOGIN PASSWORD &#39;{{password}}&#39; VALID UNTIL &#39;{{expiration}}&#39;; \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        GRANT SELECT ON ALL TABLES IN SCHEMA public TO \&#34;{{name}}\&#34;;&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    default_ttl<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;10m&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    max_ttl<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;1h&#34;</span>
</span></span></code></pre></div><h2 id="creating-a-policy">Creating a Policy</h2>
<p>First, we need to create the policy.  This can be supplied inline on the command line, but reading from a file means it can be source-controlled, and you something readable too!</p>
<p>While the filename doesn&rsquo;t need to match the policy name, it helps make it a bit clearer if it does match, so we&rsquo;ll call this file <code>postgres-connector.hcl</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># vault read database/creds/reader</span>
</span></span><span style="display:flex;"><span>path <span style="color:#e6db74">&#34;database/creds/reader&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    capabilities <span style="color:#f92672">=</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;read&#34;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>We can then register this policy into Vault.  The <code>write</code> documentation indicates that you need to prefix the file path with <code>@</code>, but that doesn&rsquo;t work for me:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault policy write postgres-connector postgres-connector.hcl
</span></span></code></pre></div><h2 id="setup-approles">Setup AppRoles</h2>
<p>As before, we&rsquo;ll create a <code>demo_app</code> role for our application to use to get a token.  However this time, we&rsquo;ll specify the <code>policies</code> field, and pass it in both <code>default</code> and our custom <code>postgres-connector</code> role.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault write auth/approle/role/demo_app <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    policies<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;postgres-connector,default&#34;</span>
</span></span></code></pre></div><p>When we generate our client token using the <code>secret_id</code> and <code>role_id</code>, we&rsquo;ll get a token which can create database credentials, as well as access the cubbyhole.</p>
<p>The final part of being an <strong>admin</strong> user for this is to generate and save the <code>secret_id</code> and <code>role_id</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault write -f -field<span style="color:#f92672">=</span>secret_id auth/approle/role/demo_app/secret-id
</span></span><span style="display:flex;"><span>vault read -field<span style="color:#f92672">=</span>role_id auth/approle/role/demo_app/role-id
</span></span></code></pre></div><h2 id="creating-a-token-and-accessing-the-database">Creating a Token and Accessing the Database</h2>
<p>Opening a new command line window, we need to generate our client token.  Take the two id&rsquo;s output from the admin window, and use them in the following code block:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export VAULT_ADDR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://localhost:8200&#34;</span>
</span></span><span style="display:flex;"><span>SECRET_ID<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span> <span style="color:#75715e"># from the &#39;admin&#39; window!</span>
</span></span><span style="display:flex;"><span>ROLE_ID<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span> <span style="color:#75715e"># from the &#39;admin&#39; window!</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>export VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>curl -X POST --data <span style="color:#e6db74">&#34;{ \&#34;role_id\&#34;:\&#34;</span>$ROLE_ID<span style="color:#e6db74">\&#34;, \&#34;secret_id\&#34;:\&#34;</span>$SECRET_ID<span style="color:#e6db74">\&#34; }&#34;</span> $VAULT_ADDR/v1/auth/approle/login | jq  -r .auth.client_token<span style="color:#66d9ef">)</span>
</span></span></code></pre></div><p>Now we have a client token, we can generate a database connection:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault read database/creds/reader
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Key                Value</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ---                -----</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># lease_id           database/creds/reader/dc2ae2b6-c709-0e2f-49a6-36b45aa84490</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># lease_duration     10m</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># lease_renewable    true</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># password           A1a-1kAiN0gqU07BE39N</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># username           v-approle-reader-incldNFPhixc1Kj25Rar-1529764057</span>
</span></span></code></pre></div><p>Which can also be renewed:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault lease renew database/creds/reader/dc2ae2b6-c709-0e2f-49a6-36b45aa84490
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Key                Value</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ---                -----</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># lease_id           database/creds/reader/dc2ae2b6-c709-0e2f-49a6-36b45aa84490</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># lease_duration     10m</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># lease_renewable    true</span>
</span></span></code></pre></div><p>However, if we try to write to the database roles, we get an error:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault write database/roles/what dbname<span style="color:#f92672">=</span>postgres_demo
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Error writing data to database/roles/what: Error making API request.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># URL: PUT http://localhost:8200/v1/database/roles/what</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Code: 403. Errors:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># * permission denied</span>
</span></span></code></pre></div><h2 id="summary">Summary</h2>
<p>It is also a good idea to have separate fine-grained policies, which can then be grouped up against separate AppRoles, allowing each AppRole to have just the permissions it needs.  For example, you could have the following Policies:</p>
<ul>
<li>postgres-connection</li>
<li>postgres-admin</li>
<li>rabbitmq-connection</li>
<li>kafka-consumer</li>
</ul>
<p>You would then have several AppRoles defined which could use different Policies:</p>
<ul>
<li>App1: rabbitmq-connection, postgres-connection</li>
<li>App2: kafka-consumer, rabbitmq-connection</li>
<li>App3: postgres-admin</li>
</ul>
<p>Which helps encourage you to have separate AppRoles for each of your applications!</p>
<p>Finally, the Vault website has a <a href="https://www.vaultproject.io/guides/secret-mgmt/dynamic-secrets.html">guide</a> on how to do this too&hellip;which I only found after writing this!  At least what I wrote seems to match up with their guide pretty well, other than I also use <code>AppRole</code> authentication (and so should you!)</p>
]]></content:encoded></item><item><title>Secure Communication with Vault</title><link>https://andydote.co.uk/2018/06/22/vault-secure-communication/</link><pubDate>Fri, 22 Jun 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/06/22/vault-secure-communication/</guid><description>I think Vault by Hashicorp is a great product - I particularly love how you can do dynamic secret generation (e.g for database connections). But how do you validate that the application requesting the secret is allowed to perform that action? How do you know it&amp;rsquo;s not someone or something impersonating your application?
While musing this at an airport the other day, my colleague Patrik sent me a link to a StackOverflow post about this very question</description><content:encoded><![CDATA[<p>I think <a href="https://vaultproject.io">Vault by Hashicorp</a> is a great product - I particularly love how you can do dynamic secret generation (e.g <a href="/2018/06/17/secret-management-vault-postgres-connection">for database connections</a>).  But how do you validate that the application requesting the secret is allowed to perform that action?  How do you know it&rsquo;s not someone or something impersonating your application?</p>
<p>While musing this at an airport the other day, my colleague <a href="https://twitter.com/PatrikHerrgard">Patrik</a> sent me a link to a StackOverflow post <a href="https://stackoverflow.com/questions/46583873/hashicorp-vault-client-best-practise">about this very question</a></p>
<p>The summary is this:</p>
<ol>
<li>Use an AppRole rather than a plain token</li>
<li>Bake the RoleID into your application</li>
<li>Provide a SecretID from the environment</li>
<li>Combine both to get a token from Vault on startup</li>
<li>Periodically renew said token.</li>
</ol>
<p>Or, in picture form:</p>
<p><img loading="lazy" src="vault-flow.png" alt="vault token flow"  />
</p>
<p>So let&rsquo;s see how we can go about doing this.</p>
<h2 id="0-setup-vault">0. Setup Vault</h2>
<p>This time we will use Vault in dev mode, which means that it starts unsealed, and we can specify the root token as something simple. On the downside, there is no persistence; restarting the container gives you a blank slate.  If you would prefer to use Vault with persistent storage, see <a href="/2018/06/17/secret-management-vault-postgres-connection">Section 2 of the previous post</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker run <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -d --rm <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --name vault_demo <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --cap-add<span style="color:#f92672">=</span>IPC_LOCK <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -e VAULT_DEV_ROOT_TOKEN_ID<span style="color:#f92672">=</span>vault <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -p 8200:8200 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    vault
</span></span></code></pre></div><p>As in the previous article, we&rsquo;ll export the <code>VAULT_TOKEN</code> and <code>VAULT_ADDR</code> variables so we can use the Vault CLI:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export VAULT_ADDR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://localhost:8200&#34;</span>
</span></span><span style="display:flex;"><span>export VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;vault&#34;</span>
</span></span></code></pre></div><p>For our last setup step, we need to enable the <code>AppRole</code> auth method:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault auth enable approle
</span></span></code></pre></div><h2 id="1-create-a-role">1. Create A Role</h2>
<p>Creating a role has <a href="https://www.vaultproject.io/api/auth/approle/index.html#create-new-approle">many parameters</a> you can specify, but for our <code>demo_app</code> role, we are going to skip most of them, just providing <code>token_ttl</code> and <code>token_max_ttl</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault write auth/approle/role/demo_app <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    token_ttl<span style="color:#f92672">=</span>20m <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    token_max_ttl<span style="color:#f92672">=</span>1h
</span></span></code></pre></div><h2 id="2-request-a-secret-id">2. Request A Secret ID</h2>
<p>Vault has two modes of working, called Push and Pull.  Push mode is when you generate the <code>secret_id</code> yourself and store it against the role.  Pull mode is when you request Vault to generate the <code>secret_id</code> against the role and return it to you.  I favour the Pull model, as it is one less thing to worry about (how to generate a secure <code>secret_id</code>.)</p>
<p>We have to specify the <code>-force</code> (shorthand <code>-f</code>) as we are writing a secret which has no key-value pairs, and as we are using the CLI, I have specified <code>-field=secret_id</code> which changes the command to only output the <code>secret_id</code>&rsquo;s value, rather than the whole object.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export SECRET_ID<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>vault write -f -field<span style="color:#f92672">=</span>secret_id auth/approle/role/demo_app/secret-id<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo $SECRET_ID
</span></span><span style="display:flex;"><span><span style="color:#75715e">#&gt; 119439b3-4eec-5e5b-ce85-c1d00f046234</span>
</span></span></code></pre></div><h2 id="3-write-secret-id-to-environment">3. Write Secret ID to Environment</h2>
<p>This step would be done by another process, such as <a href="https://www.terraform.io/">Terraform</a> when provisioning your environment, or <a href="https://www.spinnaker.io/">Spinnaker</a> when deploying your containers.</p>
<p>As we are just using the CLI, we can pretend that <code>$SECRET_ID</code> represents the value stored in the environment.</p>
<h2 id="4-fetch-role-id">4. Fetch Role ID</h2>
<p>Next, assuming the role of the developer writing an app, we need fetch the <code>role_id</code>, for our <code>demo_app</code> role.  As with fetching the <code>secret_id</code>, we specify the <code>-field=role_id</code> so we only get that part of the response printed:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault read -field<span style="color:#f92672">=</span>role_id auth/approle/role/demo_app/role-id
</span></span><span style="display:flex;"><span><span style="color:#75715e">#&gt; 723d66af-3ddd-91c0-7b35-1ee51a30c5b8</span>
</span></span></code></pre></div><h2 id="5-embed-role-id-in-code">5. Embed Role ID in Code</h2>
<p>We&rsquo;re on the CLI, and have saved the <code>role_id</code> into the <code>$ROLE_ID</code> variable, so nothing more to do here!</p>
<p>Let&rsquo;s create a simple C# Console app to demo this with:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>dotnet new console --name VaultDemo
</span></span><span style="display:flex;"><span>dotnet new sln --name VaultDemo
</span></span><span style="display:flex;"><span>dotnet sln add VaultDemo/VaultDemo.csproj
</span></span><span style="display:flex;"><span>dotnet add VaultDemo/VaultDemo.csproj package VaultSharp
</span></span></code></pre></div><p>We also installed the <code>VaultSharp</code> NuGet package, which takes care of doing the client token fetching for you - but we will go through what this is doing internally later!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Program</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">string</span> RoleID = <span style="color:#e6db74">&#34;723d66af-3ddd-91c0-7b35-1ee51a30c5b8&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">async</span> Task Main(<span style="color:#66d9ef">string</span>[] args)
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> auth = <span style="color:#66d9ef">new</span> AppRoleAuthenticationInfo(
</span></span><span style="display:flex;"><span>      RoleID,
</span></span><span style="display:flex;"><span>      Environment.GetEnvironmentVariable(<span style="color:#e6db74">&#34;SECRET_ID&#34;</span>)
</span></span><span style="display:flex;"><span>    );
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> client = VaultClientFactory.CreateVaultClient(
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">new</span> Uri(<span style="color:#e6db74">&#34;http://localhost:8200&#34;</span>),
</span></span><span style="display:flex;"><span>      auth
</span></span><span style="display:flex;"><span>    );
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> client.CubbyholeWriteSecretAsync(<span style="color:#e6db74">&#34;test/path&#34;</span>, <span style="color:#66d9ef">new</span> Dictionary&lt;<span style="color:#66d9ef">string</span>, <span style="color:#66d9ef">object</span>&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      { <span style="color:#e6db74">&#34;Name&#34;</span>, <span style="color:#e6db74">&#34;I&#39;m a secret Name!&#34;</span> }
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> secrets = <span style="color:#66d9ef">await</span> client.CubbyholeReadSecretAsync(<span style="color:#e6db74">&#34;test/path&#34;</span>);
</span></span><span style="display:flex;"><span>    Console.WriteLine(secrets.Data[<span style="color:#e6db74">&#34;Name&#34;</span>]);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="6-deploy">6. Deploy!</h2>
<p>As we&rsquo;re running locally, nothing to do here, but if you want, imagine that you created a docker container or baked an AMI and deployed it to the cloud or something!</p>
<h2 id="7-run--on-start">7. Run / On Start</h2>
<p>As we&rsquo;ve already saved the <code>SECRET_ID</code> into an environment variable, we can just run the application:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>dotnet run --project VaultDemo/VaultDemo.csproj
</span></span><span style="display:flex;"><span><span style="color:#75715e">#&gt; I&#39;m a secret Name!</span>
</span></span></code></pre></div><h2 id="so-what-did-the-application-do">So what did the application do?</h2>
<p>When run, the application used both the <code>role_id</code> from the constant and the <code>secret_id</code> environment variable to call Vault&rsquo;s <a href="https://www.vaultproject.io/api/auth/approle/index.html#login-with-approle">Login</a> method.  An equivalent <code>curl</code> command would be this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -X POST <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --data <span style="color:#e6db74">&#39;{ &#34;role_id&#34;:&#34;723d66af-3ddd-91c0-7b35-1ee51a30c5b8&#34;, &#34;secret_id&#34;:&#34;119439b3-4eec-5e5b-ce85-c1d00f046234&#34; }&#39;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    http://localhost:8200/v1/auth/approle/login
</span></span></code></pre></div><p>This will spit out a single line of json, but if you have <a href="https://stedolan.github.io/jq/">jq</a> in your path, you can prettify the output by appending <code>| jq .</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;request_id&#34;</span>: <span style="color:#e6db74">&#34;37c0e057-6fab-1873-3ec0-affaace26e76&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;lease_id&#34;</span>: <span style="color:#e6db74">&#34;&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;renewable&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;lease_duration&#34;</span>: <span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;data&#34;</span>: <span style="color:#66d9ef">null</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;wrap_info&#34;</span>: <span style="color:#66d9ef">null</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;warnings&#34;</span>: <span style="color:#66d9ef">null</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;auth&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;client_token&#34;</span>: <span style="color:#e6db74">&#34;c14f5806-aff2-61b6-42c2-8920c8049b6c&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;accessor&#34;</span>: <span style="color:#e6db74">&#34;aef3d4f4-d279-bcda-8d9c-2a3de6344975&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;policies&#34;</span>: [
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">&#34;default&#34;</span>
</span></span><span style="display:flex;"><span>    ],
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;metadata&#34;</span>: {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;role_name&#34;</span>: <span style="color:#e6db74">&#34;demo_app&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;lease_duration&#34;</span>: <span style="color:#ae81ff">1200</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;renewable&#34;</span>: <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;entity_id&#34;</span>: <span style="color:#e6db74">&#34;34b1094b-28d4-1fb0-b8f6-73ad28d80332&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The line we care about is <code>client_token</code> in the <code>auth</code> section.  The value is used to authenticate subsequent requests to Vault.</p>
<p>For instance, in the C# app we used the <a href="https://www.vaultproject.io/api/secret/cubbyhole/index.html">CubbyHole</a> backend to store a <code>Name</code>.  The equivalent curl commands would be:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;c14f5806-aff2-61b6-42c2-8920c8049b6c&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># vault write cubbyhole/test/path name=&#34;Another manual secret&#34;</span>
</span></span><span style="display:flex;"><span>curl -X POST <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --header <span style="color:#e6db74">&#34;X-Vault-Token: </span>$VAULT_TOKEN<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --data <span style="color:#e6db74">&#39;{ &#34;Name&#34;: &#34;Another manual secret&#34; }&#39;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    http://localhost:8200/v1/cubbyhole/test/path
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># vault list cubbyhole/test/path</span>
</span></span><span style="display:flex;"><span>curl -X GET <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --header <span style="color:#e6db74">&#34;X-Vault-Token: </span>$VAULT_TOKEN<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    http://localhost:8200/v1/cubbyhole/test/path
</span></span></code></pre></div><p>So why use the client library if it&rsquo;s just HTTP calls?  Simple - by using <code>VaultSharp</code> (or equivalent) we get token auto renewal handled for us, along with working APIs; no more guessing and head-scratching while trying to work out the proper HTTP call to make!</p>
<h2 id="what-next">What Next?</h2>
<p>Read up on what you can do with Roles - such as limiting token and secret lifetimes, usage counts, etc.</p>
<p>Next article will probably cover Vault&rsquo;s <a href="https://www.vaultproject.io/docs/concepts/policies.html">Policies</a>.</p>
]]></content:encoded></item><item><title>Fixing Docker volume paths on Git Bash on Windows</title><link>https://andydote.co.uk/2018/06/18/git-bash-docker-volume-paths/</link><pubDate>Mon, 18 Jun 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/06/18/git-bash-docker-volume-paths/</guid><description>My normal development laptop runs Windows, but like a lot of developers, I make huge use of Docker, which I run under Hyper-V. I also heavily use the git bash terminal on windows to work.
Usually, everything works as expected, but I was recently trying to run an ELK (Elasticsearch, Logstash, Kibana) container, and needed to pass in an extra configuration file for Logstash. This caused me a lot of trouble, as nothing was working as expected.</description><content:encoded><![CDATA[<p>My normal development laptop runs Windows, but like a lot of developers, I make huge use of Docker, which I run under Hyper-V.  I also heavily use the git bash terminal on windows to work.</p>
<p>Usually, everything works as expected, but I was recently trying to run an ELK (Elasticsearch, Logstash, Kibana) container, and needed to pass in an extra configuration file for Logstash.  This caused me a lot of trouble, as nothing was working as expected.</p>
<p>The command I was running is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker run <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -d --rm <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --name elk_temp <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -p 5044:5044 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -p 5601:5601 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -p 9200:9200 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -v logstash/app.conf:/etc/logstash/conf.d/app.conf <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    sebp/elk
</span></span></code></pre></div><p>But this has the interesting effect of mounting the <code>app.conf</code> in the container as a directory (which is empty), rather than doing the useful thing of mounting it as a file. Hmm.  I realised it was git bash doing path transformations to the windows style causing the issue, but all the work arounds I tried failed:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># single quotes</span>
</span></span><span style="display:flex;"><span>docker run ... -v <span style="color:#e6db74">&#39;logstash/app.conf:/etc/logstash/conf.d/app.conf&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># absolute path</span>
</span></span><span style="display:flex;"><span>docker run ... -v /d/dev/temp/logstash/app.conf:/etc/logstash/conf.d/app.conf
</span></span><span style="display:flex;"><span><span style="color:#75715e"># absolute path with // prefix</span>
</span></span><span style="display:flex;"><span>docker run ... -v //d/dev/temp/logstash/app.conf:/etc/logstash/conf.d/app.conf
</span></span></code></pre></div><p>In the end, I found a way to switch off MSYS&rsquo;s (what git bash is based on) path conversion:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>MSYS_NO_PATHCONV<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span> docker run <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -d --rm <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --name elk_temp <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -p 5044:5044 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -p 5601:5601 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -p 9200:9200 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -v logstash/app.conf:/etc/logstash/conf.d/app.conf <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    sebp/elk
</span></span></code></pre></div><p>And Voila, the paths get passed through correctly, and I can go back to hacking away at Logstash!</p>
]]></content:encoded></item><item><title>Managing Postgres Connection Strings with Vault</title><link>https://andydote.co.uk/2018/06/17/secret-management-vault-postgres-connection/</link><pubDate>Sun, 17 Jun 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/06/17/secret-management-vault-postgres-connection/</guid><description>One of the points I made in my recent NDC talk on 12 Factor microservices, was that you shouldn&amp;rsquo;t be storing sensitive data, such as API keys, usernames, passwords etc. in the environment variables.
Don&amp;rsquo;t Store Sensitive Data in the Environment
My reasoning is that when you were accessing Environment Variables in Heroku&amp;rsquo;s platform, you were actually accessing some (probably) secure key-value store, rather than actual environment variables.
While you can use something like Consul&amp;rsquo;s key-value store for this, it&amp;rsquo;s not much better as it still stores all the values in plaintext, and has no auditing or logging.</description><content:encoded><![CDATA[<p>One of the points I made in my recent NDC talk on 12 Factor microservices, was that you shouldn&rsquo;t be storing sensitive data, such as API keys, usernames, passwords etc. in the environment variables.</p>
<blockquote>
<p>Don&rsquo;t Store Sensitive Data in the Environment</p>
</blockquote>
<p>My reasoning is that when you were accessing Environment Variables in Heroku&rsquo;s platform, you were actually accessing some (probably) secure key-value store, rather than actual environment variables.</p>
<p>While you can use something like Consul&rsquo;s key-value store for this, it&rsquo;s not much better as it still stores all the values in plaintext, and has no auditing or logging.</p>
<h2 id="enter-vault">Enter Vault</h2>
<p>Vault is a secure secret management application, which not only can store static values, but also generate credentials on the fly, and automatically expire them after usage or after a time period.  We&rsquo;re going to look at setting up Vault to generate Postgres connection strings.</p>
<h2 id="what-youll-need">What you&rsquo;ll need</h2>
<ol>
<li>Docker, as we&rsquo;ll be running both Vault and Postgres in containers</li>
<li>A SQL client (for a GUI, I recommend <a href="https://dbeaver.io/">DBeaver</a>, for CLI <a href="https://www.postgresql.org/download/">PSQL</a> included in the Postgres download is fine.)</li>
<li>The <a href="https://www.vaultproject.io/downloads.html">Vault executable</a></li>
</ol>
<h2 id="what-well-do">What we&rsquo;ll do</h2>
<ol>
<li>Setup Postgres and create a SQL user for Vault to use</li>
<li>Setup Vault</li>
<li>Setup Vault&rsquo;s database functionality</li>
<li>Fetch and renew credentials from Vault.</li>
</ol>
<h2 id="1-setup-a-postgres-container">1. Setup a Postgres container</h2>
<p>When running on my local machine, I like to use the Alpine variant of the <a href="https://hub.docker.com/_/postgres/">official Postgres</a> container, as it&rsquo;s pretty small, and does everything I&rsquo;ve needed so far.</p>
<p>We&rsquo;ll run a copy of the image, configure it to listen on the default port, and use the super secure password of <code>postgres</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker run <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -d <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --name postgres_demo <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -p 5432:5432 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  -e <span style="color:#e6db74">&#39;POSTGRES_PASSWORD=postgres&#39;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  postgres:alpine
</span></span></code></pre></div><p>Next up, we need to create a user for Vault to use when generating credentials.  You can execute this SQL in any SQL editor which can connect to postgres, or use the PSQL command line interface:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>psql --username postgres --dbname postgres   <span style="color:#75715e"># it will prompt for password</span>
</span></span><span style="display:flex;"><span>psql&gt; create role VaultAdmin with Login password <span style="color:#e6db74">&#39;vault&#39;</span> CreateRole;
</span></span><span style="display:flex;"><span>psql&gt; grant connect on database postgres to vaultadmin;
</span></span></code></pre></div><p>You can verify this has worked by running another instance of psql as the new user:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>psql --username VaultAdmin --dbname postgres   <span style="color:#75715e"># it will prompt for password</span>
</span></span></code></pre></div><h2 id="2-setting-up-the-vault-container">2. Setting up the Vault container</h2>
<p>The official Vault container image will by default run in <code>dev</code> mode, which means it will startup unsealed, and will use whatever token you specify for authentication.  However, it won&rsquo;t persist any information across container restarts, which is a bit irritating, so instead, we will run it in server mode, and configure file storage to give us (semi) persistent storage.</p>
<p>The configuration, when written out and appropriately formatted, looks as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>backend <span style="color:#e6db74">&#34;file&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    path <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/vault/file&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>listener <span style="color:#e6db74">&#34;tcp&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    address <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;0.0.0.0:8200&#34;</span>
</span></span><span style="display:flex;"><span>    tls_disable <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>ui <span style="color:#f92672">=</span> true
</span></span></code></pre></div><p>We are binding the listener to all interfaces on the container, disabling SSL (don&rsquo;t do this in production environments!) and enabling the UI.  To pass this through to the container, we can set the <code>VAULT_LOCAL_CONFIG</code> environment variable:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker run <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -d <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --name vault_demo <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    --cap-add<span style="color:#f92672">=</span>IPC_LOCK <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -p 8200:8200 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    -e <span style="color:#e6db74">&#39;VAULT_LOCAL_CONFIG=backend &#34;file&#34; { path = &#34;/vault/file&#34; } listener &#34;tcp&#34; { address = &#34;0.0.0.0:8200&#34; tls_disable = 1 } ui = true&#39;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    vault server
</span></span></code></pre></div><p>When we use the Vault CLI to interact with a Vault server, it want&rsquo;s to use TLS, but as we are running without TLS, we need to override this default.  Luckily it&rsquo;s just a case of setting the <code>VAULT_ADDR</code> environment variable:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export VAULT_ADDR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://localhost:8200&#34;</span>
</span></span></code></pre></div><p>You can run <code>vault status</code> to check you can communicate with the container successfully.</p>
<p>Before we can start configuring secret engines in Vault, it needs initialising.  By default, the <code>init</code> command will generate five key shares, of which you will need any three to unseal Vault.  The reason for Key Shares is so that you can distribute the keys to different people so that no one person has access to unseal Vault on their own.  While this is great for production, for experimenting locally, one key is enough.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault operator init -key-shares<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span> -key-threshold<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>
</span></span></code></pre></div><p>The output will amongst other things give you two lines, one with the Unseal Key, and one with the Initial Root Token:</p>
<blockquote>
<p>Unseal Key 1: sk+C4xJihsMaa+DCBHHgoGVozz+dMC4Kd/ijX8oMcrQ=
Initial Root Token: addaaeed-d387-5eab-128d-60d6e92b0757</p>
</blockquote>
<p>We&rsquo;ll need the Unseal key to unseal Vault so we can configure it and generate secrets, and the Root Token so we can authenticate with Vault itself.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> vault operator unseal <span style="color:#e6db74">&#34;sk+C4xJihsMaa+DCBHHgoGVozz+dMC4Kd/ijX8oMcrQ=&#34;</span>
</span></span></code></pre></div><p>To make life a bit easier, we can also set an environment variable with our token so that we don&rsquo;t have to specify it on all the subsequent requests:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export VAULT_TOKEN<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;addaaeed-d387-5eab-128d-60d6e92b0757&#34;</span>
</span></span></code></pre></div><h2 id="3-configure-vaults-database-secret-engine">3. Configure Vault&rsquo;s Database Secret Engine</h2>
<p>First off we need to enable the database secret engine.  This engine supports many different databases, such as Postgres, MSSQL, Mysql, MongoDB and Cassandra amongst others.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault secrets enable database
</span></span></code></pre></div><p>Next, we need to configure how vault will connect to the database.  You will need to substitute the IPAddress in the connection string for your docker host IP (in my case, the network is called <code>DockerNAT</code>, and my machine&rsquo;s IP is <code>10.0.75.1</code>, yours will probably be different.)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault write database/config/postgres_demo <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    plugin_name<span style="color:#f92672">=</span>postgresql-database-plugin <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    allowed_roles<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;*&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    connection_url<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;postgresql://{{username}}:{{password}}@10.0.75.1:5432/postgres?sslmode=disable&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    username<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;VaultAdmin&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    password<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;vault&#34;</span>
</span></span></code></pre></div><p>To explain more of the command:  We can limit what roles can be granted by this database backend by specifying a CSV of roles (which we will define next).  In our case, however, we are using the allow anything wildcard (<code>*</code>).</p>
<p>Next, we need to define a role which our applications can request.  In this case, I am creating a role which only allows reading of data, so it&rsquo;s named <code>reader</code>.  We also specify the <code>default_ttl</code> which controls how long the user is valid for, and the <code>max_ttl</code> which specifies for how long we can renew a user&rsquo;s lease.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault write database/roles/reader <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    db_name<span style="color:#f92672">=</span>postgres_demo <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    creation_statements<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;CREATE ROLE \&#34;{{name}}\&#34; WITH LOGIN PASSWORD &#39;{{password}}&#39; VALID UNTIL &#39;{{expiration}}&#39;; \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        GRANT SELECT ON ALL TABLES IN SCHEMA public TO \&#34;{{name}}\&#34;;&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    default_ttl<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;10m&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>    max_ttl<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;1h&#34;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault read database/creds/reader
</span></span><span style="display:flex;"><span>&gt; Key                Value
</span></span><span style="display:flex;"><span>&gt; ---                -----
</span></span><span style="display:flex;"><span>&gt; lease_id           database/creds/reader/15cf95eb-a2eb-c5ba-5111-8c0c48ae30a6
</span></span><span style="display:flex;"><span>&gt; lease_duration     10m
</span></span><span style="display:flex;"><span>&gt; lease_renewable    true
</span></span><span style="display:flex;"><span>&gt; password           A1a-3gkMQpmoh3gbj2aM
</span></span><span style="display:flex;"><span>&gt; username           v-root-reader-tgl6FSXHZaC5LZOK4q0u-1529138525
</span></span></code></pre></div><p>We can now use the username and password to connect to postgres, but only for 10 minutes, after which, the user will be deleted (Note, Vault sets the expiry of the user in Postgres, but will also remove the user when it expires.)</p>
<p>Verify the user can connect using PSQL again:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>psql --username v-root-reader-tgl6FSXHZaC5LZOK4q0u-1529138525 --dbname postgres
</span></span></code></pre></div><p>If we want to keep using our credentials, we can run the renew command passing in the <code>lease_id</code>, which will increase the current lease timeout by the value of <code>default_ttl</code>.  You can provide the <code>-increment</code> value to request a different duration extension in seconds, but you cannot go further than the <code>max_ttl</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vault lease renew database/creds/reader/15cf95eb-a2eb-c5ba-5111-8c0c48ae30a6
</span></span><span style="display:flex;"><span><span style="color:#75715e"># or</span>
</span></span><span style="display:flex;"><span>vault lease renew database/creds/reader/15cf95eb-a2eb-c5ba-5111-8c0c48ae30a6 -increment <span style="color:#ae81ff">360</span>
</span></span></code></pre></div><h2 id="done">Done!</h2>
<p>There are a lot more options and things you can do with Vault, but hopefully, this will give you an idea of how to start out.</p>
]]></content:encoded></item><item><title>Writing Conference Talks</title><link>https://andydote.co.uk/2018/05/15/writing-conference-talks/</link><pubDate>Tue, 15 May 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/05/15/writing-conference-talks/</guid><description>I saw an interesting question on twitter today:
Hey, people who talk at things: How long does it take you to put a new talk together?
I need like 50 hours over at least a couple of months to make something I don&amp;rsquo;t hate. I&amp;rsquo;m trying to get that down (maybe by not doing pictures?) but wondering what&amp;rsquo;s normal for everyone else.
Source
I don&amp;rsquo;t know how long it takes me to write a talk - as it is usually spread over many weeks/months, worked on as and when I have inspiration.</description><content:encoded><![CDATA[<p>I saw an interesting question on twitter today:</p>
<blockquote>
<p>Hey, people who talk at things: How long does it take you to put a new talk together?</p>
<p>I need like 50 hours over at least a couple of months to make something I don&rsquo;t hate. I&rsquo;m trying to get that down (maybe by not doing pictures?) but wondering what&rsquo;s normal for everyone else.</p>
</blockquote>
<p><a href="https://twitter.com/whereistanya/status/995653828933496832">Source</a></p>
<p>I don&rsquo;t know how long it takes me to write a talk - as it is usually spread over many weeks/months, worked on as and when I have inspiration.  The actual processes is something like this:</p>
<ol>
<li>
<p>Think it through</p>
<p>The start of this is usually with an idea for a subject I like a lot, such as Strong Typing, Feature Toggles, or Trunk Based Development.  Where I live I walk everywhere (around 15k to 20k steps per day), which gives me a lot of time to think about things.</p>
</li>
<li>
<p>Giant markdown file of bullet points which I might want to cover</p>
<p>I write down all the points that I want to talk about into one markdown file, which I add to over time.  I use the github checkbox markdown format (<code>* [ ] some point or other</code>) so I can tick thinks off later.</p>
</li>
<li>
<p>Rough order of points at the bottom</p>
<p>At the bottom of this notes file, I start writing an order of things, just to get a sense of flow.  Once this order gets comfortable enough, I stop updating it and start using the real slides file.</p>
</li>
<li>
<p>Start slides writing sections as I feel like it</p>
<p>I start with the title slide, and finding a suitable large image for it.  This takes way longer than you might imagine!  For the rest of the slides, I use a mix of titles, text and hand drawn images.</p>
<p>I use OneNote and Gimp to do the hand drawn parts, and usually the <a href="https://cloud.google.com/icons/">Google Cloud Platform Icons</a>, as they&rsquo;re the best looking (sorry Amazon!)</p>
<p>Attribute all the images as you go.  Much easier than trying to do it later.</p>
</li>
<li>
<p>Re-order it all!</p>
<p>I talk bits of the presentation through in my head, and shuffle bits around as I see fit.  This happens a lot as I write the slides.</p>
</li>
<li>
<p>Talk it through to a wall</p>
<p>My wall gets me talking to it a lot.  I talk it through outloud, and make note of stumbling points, and how long the talk takes, adding speaker notes if needed.</p>
</li>
<li>
<p>Tweaks and re-ordering</p>
<p>I usually end up making last minute tweaks and order switches as I figure out how to make something flow better.  I am still not happy with some transitions in my best talks yet!</p>
</li>
</ol>
<p>I write all my talks using <a href="https://github.com/hakimel/reveal.js">RevealJS</a>, mostly because I can write my slides as a markdown file and have it rendered in the browser, and partly because I&rsquo;ve always used it.</p>
<p>To get things like the Speaker Notes view working, you need to be running from a webserver (rather than just from an html file on your filesystem.)  For this I use <a href="https://www.npmjs.com/package/nws">NWS</a>, which is a static webserver for your current working directory (e.g. <code>cd /d/dev/presentations &amp;&amp; nws</code>).</p>
<p>Currently, I am trying to work out if I can use Jekyll or Hugo to generate the repository for me, as all the presentations have the same content, other than images, slides file, and a customise.css file.  Still not sure on how best to achieve what I am after though.</p>
<p>You can see the source for all my talks in my <a href="https://github.com/pondidum/presentations">Presentations Repository</a> on github.  The actual slides can be seen on my website <a href="https://andydote.co.uk/presentations/">here</a>, and the videos (if available), I link to <a href="https://andydote.co.uk/talks/">here</a>.</p>
]]></content:encoded></item><item><title>Test Expressiveness</title><link>https://andydote.co.uk/2018/02/26/test-expressiveness/</link><pubDate>Mon, 26 Feb 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/02/26/test-expressiveness/</guid><description>We have a test suite at work which tests a retry decorator class works as expected. One of the tests checks that when the inner implementation throws an exception, it will log the number of times it has failed:
[Test] public async Task ShouldLogRetries() { var mockClient = Substitute.For&amp;lt;IContractProvider&amp;gt;(); var logger = Subsitute.For&amp;lt;ILogger&amp;gt;(); var sut = new RetryDecorator(mockClient, logger, maxRetries: 3); mockClient .GetContractPdf(Arg.Any&amp;lt;string&amp;gt;()) .Throws(new ContractDownloadException()); try { await sut.GetContractPdf(&amp;#34;foo&amp;#34;); } catch (Exception e){} logger.</description><content:encoded><![CDATA[<p>We have a test suite at work which tests a retry decorator class works as expected.  One of the tests checks that when the inner implementation throws an exception, it will log the number of times it has failed:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#a6e22e">[Test]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task ShouldLogRetries()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> mockClient = Substitute.For&lt;IContractProvider&gt;();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> logger = Subsitute.For&lt;ILogger&gt;();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> sut = <span style="color:#66d9ef">new</span> RetryDecorator(mockClient, logger, maxRetries: <span style="color:#ae81ff">3</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    mockClient
</span></span><span style="display:flex;"><span>        .GetContractPdf(Arg.Any&lt;<span style="color:#66d9ef">string</span>&gt;())
</span></span><span style="display:flex;"><span>        .Throws(<span style="color:#66d9ef">new</span> ContractDownloadException());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">try</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> sut.GetContractPdf(<span style="color:#e6db74">&#34;foo&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">catch</span> (Exception e){}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    logger.Received(<span style="color:#ae81ff">1</span>).Information(Arg.Any&lt;<span style="color:#66d9ef">string</span>&gt;(), <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>    logger.Received(<span style="color:#ae81ff">1</span>).Information(Arg.Any&lt;<span style="color:#66d9ef">string</span>&gt;(), <span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>    logger.Received(<span style="color:#ae81ff">1</span>).Information(Arg.Any&lt;<span style="color:#66d9ef">string</span>&gt;(), <span style="color:#ae81ff">3</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>But looking at this test, I couldn&rsquo;t easily work out what the behaviour of <code>sut.GetContractPdf(&quot;foo&quot;)</code> was supposed to be; should it throw an exception, or should it not?  That fact that there is a <code>try...catch</code> indicates that it <em>might</em> throw an exception, but doesn&rsquo;t give any indication that it&rsquo;s required or not.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">try</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> sut.GetContractPdf(<span style="color:#e6db74">&#34;foo&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">catch</span> (Exception e)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Since we have the <a href="https://www.nuget.org/packages/Shouldly/"><code>Shouldly</code></a> library in use, I changed the test to be a little more descriptive:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>Should.Throw&lt;ContractDownloadException&gt;(() =&gt;
</span></span><span style="display:flex;"><span>    sut.GetContractPdfForAccount(<span style="color:#e6db74">&#34;foo&#34;</span>)
</span></span><span style="display:flex;"><span>);
</span></span></code></pre></div><p>Now we know that when the decorator exceeds the number of retries, it should throw the inner implementation&rsquo;s exception.</p>
<p>This in itself is better, but it also raises another question:  Is the test name correct? Or should this now be two separate tests? One called <code>ShouldLogRetries</code>, and one called <code>ShouldThrowInnerExceptionOnRetriesExceeded</code>?</p>
<p>Even though I ended up adding the second test, I still left the first test with the <code>Should.Throw(...)</code> block, as it is still more descriptive at a glance than the <code>try...catch</code>.</p>
]]></content:encoded></item><item><title>Task Chaining and the Pipeline Operator</title><link>https://andydote.co.uk/2018/02/20/task-chainging-pipeline-operator/</link><pubDate>Tue, 20 Feb 2018 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2018/02/20/task-chainging-pipeline-operator/</guid><description>Since I have been trying to learn a functional language (Elixir), I have noticed how grating it is when in C# I need to call a few methods in a row, passing the results of one to the next.
The bit that really grates is that it reads backwards, i.e. the rightmost function call is invoked first, and the left hand one last, like so:
await WriteJsonFile(await QueueParts(await ConvertToModel(await ReadBsxFile(record)))); In Elixir (or F# etc.</description><content:encoded><![CDATA[<p>Since I have been trying to learn a functional language (Elixir), I have noticed how grating it is when in C# I need to call a few methods in a row, passing the results of one to the next.</p>
<p>The bit that really grates is that it reads backwards, i.e. the rightmost function call is invoked first, and the left hand one last, like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">await</span> WriteJsonFile(<span style="color:#66d9ef">await</span> QueueParts(<span style="color:#66d9ef">await</span> ConvertToModel(<span style="color:#66d9ef">await</span> ReadBsxFile(record))));
</span></span></code></pre></div><p>In Elixir (or F# etc.) you can write this in the following way:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> task = <span style="color:#66d9ef">record</span>
</span></span><span style="display:flex;"><span>    |&gt; <span style="color:#66d9ef">await</span> ReadBsxFile
</span></span><span style="display:flex;"><span>    |&gt; <span style="color:#66d9ef">await</span> ConvertToModel
</span></span><span style="display:flex;"><span>    |&gt; <span style="color:#66d9ef">await</span> QueueParts
</span></span><span style="display:flex;"><span>    |&gt; <span style="color:#66d9ef">await</span> WriteJsonFile
</span></span></code></pre></div><p>While there are proposals for the <a href="https://github.com/dotnet/csharplang/issues/74">forward pipe operator</a> to be added to C# being discussed, it doesn&rsquo;t look like it will happen in the near future.</p>
<p>Something close to this is Linq, and at first, I tried to work out a way to write the pipeline for a single object using the <code>Select</code> statement, something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">await</span> <span style="color:#66d9ef">record</span>
</span></span><span style="display:flex;"><span>    .Select(ReadBsxFile)
</span></span><span style="display:flex;"><span>    .Select(ConvertToModel)
</span></span><span style="display:flex;"><span>    .Select(QueueParts)
</span></span><span style="display:flex;"><span>    .Select(WriteJsonFile);
</span></span></code></pre></div><p>The problem with this is that Linq doesn&rsquo;t play well with async code - you end up needing to call <code>.Result</code> on each task selected&hellip;which is a <a href="http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html">Bad</a> <a href="https://msdn.microsoft.com/en-us/magazine/jj991977.aspx">Thing</a> to do.</p>
<p>I realised that as it&rsquo;s just <code>Task</code>s I really care about, I might be able to write some extension methods to accomplish something similar.  I ended up with 3 extensions: one to start a chain from a value, and two to allow either <code>Task&lt;T&gt;</code> to be chained, or a <code>Task</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TaskExtensions</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">async</span> Task&lt;TOut&gt; Start&lt;TIn, TOut&gt;(<span style="color:#66d9ef">this</span> TIn <span style="color:#66d9ef">value</span>, Func&lt;TIn, Task&lt;TOut&gt;&gt; next)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">await</span> next(<span style="color:#66d9ef">value</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">async</span> Task&lt;TOut&gt; Then&lt;TIn, TOut&gt;(<span style="color:#66d9ef">this</span> Task&lt;TIn&gt; current, Func&lt;TIn, Task&lt;TOut&gt;&gt; next)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">await</span> next(<span style="color:#66d9ef">await</span> current);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">async</span> Task Then&lt;TIn&gt;(<span style="color:#66d9ef">this</span> Task&lt;TIn&gt; current, Func&lt;TIn, Task&gt; next)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> next(<span style="color:#66d9ef">await</span> current);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This can be used to take a single value, and &ldquo;pipeline&rdquo; it through a bunch of async methods:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> task = <span style="color:#66d9ef">record</span>
</span></span><span style="display:flex;"><span>    .Start(ReadBsxFile)
</span></span><span style="display:flex;"><span>    .Then(ConvertToModel)
</span></span><span style="display:flex;"><span>    .Then(QueueParts)
</span></span><span style="display:flex;"><span>    .Then(WriteJsonFile);
</span></span></code></pre></div><p>One of the nice things about this is that if I want to add another method in the middle of my chain, as long as it&rsquo;s input and output types fit, it can just be inserted or added to the chain:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> task = <span style="color:#66d9ef">record</span>
</span></span><span style="display:flex;"><span>    .Start(ReadBsxFile)
</span></span><span style="display:flex;"><span>    .Then(ConvertToModel)
</span></span><span style="display:flex;"><span>    .Then(InspectModelForRedundancies)
</span></span><span style="display:flex;"><span>    .Then(QueueParts)
</span></span><span style="display:flex;"><span>    .Then(WriteJsonFile)
</span></span><span style="display:flex;"><span>    .Then(DeleteBsxFile);
</span></span></code></pre></div><p>You can see a real use of this in my <a href="https://github.com/Pondidum/BrickRecon/blob/master/projects/BsxProcessor/src/BsxProcessor/RecordHandler.cs#L24">BsxProcessor Lambda</a>.</p>
<p>This is one of the great things about learning other programming languages: even if you don&rsquo;t use them on a daily basis, they can really give you insight into different ways of doing things, doubly so if they are a different style of language.</p>
]]></content:encoded></item><item><title>Tweaking Processes to Remove Errors</title><link>https://andydote.co.uk/2017/12/09/tweaking-process-remove-errors/</link><pubDate>Sat, 09 Dec 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/12/09/tweaking-process-remove-errors/</guid><description>When we are developing (internal) Nuget packages at work, the process used is the following:
Get latest of master New branch feature-SomethingDescriptive Implement feature Push to GitHub TeamCity builds Publish package to the nuget feed Pull request Merge to master Obviously 3 to 6 can repeat many times if something doesn&amp;rsquo;t work out quite right.
There are a number of problems with this process:
Pull-request after publishing Pull requests are a great tool which we use extensively, but in this case, they are being done too late.</description><content:encoded><![CDATA[<p>When we are developing (internal) Nuget packages at work, the process used is the following:</p>
<ol>
<li>Get latest of master</li>
<li>New branch <code>feature-SomethingDescriptive</code></li>
<li>Implement feature</li>
<li>Push to GitHub</li>
<li>TeamCity builds</li>
<li>Publish package to the nuget feed</li>
<li>Pull request</li>
<li>Merge to master</li>
</ol>
<p>Obviously <code>3</code> to <code>6</code> can repeat many times if something doesn&rsquo;t work out quite right.</p>
<p>There are a number of problems with this process:</p>
<h3 id="pull-request-after-publishing">Pull-request after publishing</h3>
<p>Pull requests are a great tool which we use extensively, but in this case, they are being done too late. By the time another developer has reviewed something, possibly requesting changes, the package is published.</p>
<h3 id="potentially-broken-packages-published">Potentially broken packages published</h3>
<p>As packages are test-consumed from the main package feed, there is the chance that someone else is working on another code base, and decides to update the nuget which you have just published. Now they are pulling in a potentially broken, or unreviewed package.</p>
<h3 id="published-package-is-not-nessacarily-what-is-on-master">Published package is not nessacarily what is on master</h3>
<p>Assuming the pull-request is approved with no changes, then the code is going to make it to master. However there is nothing to stop another developer&rsquo;s changes getting to master first, and now you have a merge&hellip;and the published package doesn&rsquo;t match what the source says it contains.</p>
<h3 id="featureversion-conflicts-with-multiple-developers">Feature/version conflicts with multiple developers</h3>
<p>A few of our packages get updated fairly frequently, and there is a strong likelyhood that two developers are adding things to the same package. Both publish their package off their feature branch, and now someone&rsquo;s changes have been &ldquo;lost&rdquo; as the latest package doesn&rsquo;t have bother developer&rsquo;s changes.</p>
<h2 id="soltuon-continuous-delivery--master-based-development">Soltuon: Continuous Delivery / Master Based Development</h2>
<p>We can solve all of these issues by changing the process to be more &ldquo;Trunk Based&rdquo;:</p>
<ol>
<li>Get latest of master</li>
<li>New branch <code>feature-SomethingDescriptive</code></li>
<li>Implement feature</li>
<li>Push to GitHub</li>
<li>Pull request</li>
<li>TeamCity builds branch</li>
<li>Merge to master</li>
<li>TeamCity builds &amp; publishes the package</li>
</ol>
<p>All we have really changed here is to publish from master, rather than your feature branch. Now a pull-request has to happen (master branch is Protected in GitHub) before you can publish a package, meaning we have elimnated all of the issues with our previous process.</p>
<p>Except one, kind of.</p>
<p>How do developers test their new version of the package is correct from a different project? There are two solutions to this (and you could implement both):</p>
<ul>
<li>Publish package to a local nuget feed</li>
<li>Publish packages from feature branches as <code>-pre</code> versions</li>
</ul>
<p>The local nuget feed is super simple to implement: just use a directory e.g. I have <code>/d/dev/local-packages/</code> defined in my machine&rsquo;s nuget.config file. We use Gulp for our builds, so modifying our <code>gulp publish</code> task to publish locally when no arguments are specified would be trivial.</p>
<p>The publishing of Pre-release packages can also be implemented through our gulp scripts: we just need to adjust TeamCity to pass in the branch name to the gulp command (<code>gulp ci --mode=Release --barnch &quot;%vcsroot.branch%&quot;</code>), and we can modify the script to add the <code>-pre</code> flag to the version number if the branch parameter is not <code>master</code>.</p>
<p>Personally, I would use local publishing only, and implement the feature branch publishing if the package in question is consumed by multiple teams, and you would want an external team to be able to verify the changes made before a proper release.</p>
<p>Now our developers can still test their package works from a consuming application, and not clutter the nuget feed with potentially broken packages.</p>
]]></content:encoded></item><item><title>Evolutionary Development</title><link>https://andydote.co.uk/2017/11/17/evolutionary-development/</link><pubDate>Fri, 17 Nov 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/11/17/evolutionary-development/</guid><description>Having recently finished reading the Building Evolutionary Architectures: Support Constant Change book, I got to thinking about a system which was fairly representative of an architecture which was fine for it&amp;rsquo;s initial version, but it&amp;rsquo;s usage had outgrown the architecture.
Example System: Document Storage The system in question was a file store for a multi user, internal, desktop based CRM system. The number of users was very small, and the first implementation was just a network file share.</description><content:encoded><![CDATA[<p>Having recently finished reading the <a href="https://www.goodreads.com/book/show/35755822-building-evolutionary-architectures">Building Evolutionary Architectures: Support Constant Change book</a>, I got to thinking about a system which was fairly representative of an architecture which was fine for it&rsquo;s initial version, but it&rsquo;s usage had outgrown the architecture.</p>
<h2 id="example-system-document-storage">Example System: Document Storage</h2>
<p>The system in question was a file store for a multi user, internal, desktop based CRM system.  The number of users was very small, and the first implementation was just a network file share.  This was a fine solution to start with, but as the number of CRM users grew, cracks started to appear in the system.</p>
<p>A few examples of problems seen were:</p>
<ul>
<li>Concurrent writes to the same files</li>
<li>Finding files for a specific record in the CRM</li>
<li>Response time</li>
<li>Files &ldquo;going missing&rdquo;</li>
<li>Storage size</li>
<li>Data retention rules</li>
</ul>
<p>Most of this was caused by the number of file stored, which was well past the 5 million mark.  For example, queries for &ldquo;all files for x record&rdquo; got slower and slower over time.</p>
<p>Samba shares can&rsquo;t be listed in date-modified order (you actually get all the file names, then sorting is applied), which means you can&rsquo;t auto delete old files, or auto index (e.g. export text to elasticsearch) updated files easily.</p>
<p>The key to dealing with this problem is to take small steps - if you have a large throughput to support, the last thing you want to do is break it for everyone at once, by doing a &ldquo;big bang&rdquo; release.</p>
<p>Not only can we take small steps in deploying our software, but we can also utilise Feature Toggles to make things safer.  We can switch on a small part of the new system for a small percentage of users, and slowly ramp up usage while monitoring for errors.</p>
<h2 id="incremental-replacement">Incremental Replacement</h2>
<p>To replace this in an incremental manner, we are going to do the following 4 actions for every feature, until all features are done:</p>
<ol>
<li>Implement new feature in API and client</li>
<li>Deploy client (toggle: off)</li>
<li>Deploy API</li>
<li>Start toggle roll out</li>
</ol>
<p>Now that we know how each feature is going to be delivered, we can write out our list of features, in a rough implementation order:</p>
<ul>
<li>Create API, build scripts, CI and deployment pipeline</li>
<li>Implement authentication on the API</li>
<li>Implement fetching a list of files for a record</li>
<li>Implement fetching a single file&rsquo;s content for a record</li>
<li>Implement storing a single file for a record</li>
<li>Implement deletion of a single file for a record</li>
</ul>
<p>The development and deployment of our features can be overlapped too: we can be deploying the next version of the client with the next feature off while we are still rolling out the previous feature(s).  This all assumes that your features are nice and isolated however!</p>
<p>Once this list of features is done, and all the toggles are on, from the client perspective we are feature complete.</p>
<p>We are free to change how the backend of the API works.  As long as we don&rsquo;t change the API&rsquo;s contract, the client doesn&rsquo;t need any more changes.</p>
<p>Our next set of features could be:</p>
<ul>
<li>Implement audit log of API actions</li>
<li>Publish store and delete events to a queue</li>
<li>Change our indexing process to consume the store and delete events</li>
<li>Make the samba hidden (except to the API)</li>
<li>Implement background delete of old documents</li>
<li>Move storage backend (to S3, for example)</li>
</ul>
<p>This list of features doesn&rsquo;t impact the front end (client) system, but the backend systems can now have a more efficient usage of the file store.  As with the client and initial API development, we would do this with a quick, iterative process.</p>
<h2 id="but-we-cant-do-iterative-because">But we can&rsquo;t do iterative because&hellip;</h2>
<p>This is a common reaction when an iterative approach is suggested, and thankfully can be countered in a number of ways.</p>
<p>First off, if this is an absolute requirement, we can do our iterations an feature toggling rollouts to another environment, such a Pre-Production, or QA.  While this reduces some of the benefits (we loose out on live data ramp up), it does at least keep small chunks of work.</p>
<p>Another work around is to use feature toggles anyway, but only have a couple of &ldquo;trusted&rdquo; users use the new functionality.  Depending on what you are releasing, this could mean a couple of users you know, or giving a few users a non-visible change (i.e. they&rsquo;re not aware they&rsquo;ve been selected!)  You could also use NDA (Non Disclosure Agreements) if you need to keep them quiet, although this is quite an extreme measure.</p>
<p>A final option is to use experiments, using an experimentation library (such as <a href="https://github.com/github/scientist">Github&rsquo;s Scientist</a>) which continues to use the existing features, but in parallel runs and records the results of the replacement feature.  This obviously has to be done with care, as you don&rsquo;t want to cause side effects.</p>
<p>How do you replace old software? Big bang, iterative, experimentation, or some other process?</p>
]]></content:encoded></item><item><title>Strong Configuration Composition</title><link>https://andydote.co.uk/2017/11/09/configuration-composition/</link><pubDate>Thu, 09 Nov 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/11/09/configuration-composition/</guid><description>It&amp;rsquo;s no secret I am a fan of strong typing - not only do I talk and blog about it a lot, but I also have a library called Stronk which provides strong typed configuration for non dotnet core projects.
The problem I come across often is large configurations. For example, given the following project structure (3 applications, all reference the Domain project):
DemoService `-- src |-- Domain | |-- Domain.</description><content:encoded><![CDATA[<p>It&rsquo;s no secret I am a fan of strong typing - not only do I talk and blog about it a lot, but I also have a library called <a href="https://github.com/pondidum/stronk">Stronk</a> which provides strong typed configuration for non dotnet core projects.</p>
<p>The problem I come across often is large configurations.  For example, given the following project structure (3 applications, all reference the Domain project):</p>
<pre tabindex="0"><code>DemoService
`-- src
    |-- Domain
    |   |-- Domain.csproj
    |   `-- IConfiguration.cs
    |-- QueueConsumer
    |   |-- app.config
    |   |-- QueueConsumerConfiguration.cs
    |   `-- QueueConsumer.csproj
    |-- RestApi
    |   |-- RestConfiguration.cs
    |   |-- RestApi.csproj
    |   `-- web.config
    `-- Worker
        |-- app.config
        |-- WorkerConfiguration.cs
        `-- Worker.csproj
</code></pre><p>The configuration defined in the domain will look something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IConfiguration</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> ApplicationName { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> LogPath { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    Uri MetricsEndpoint { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Uri DocumentsEndpoint { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    Uri ArchivalEndpoint { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> RabbitMqUsername { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> RabbitMqPassword { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> RabbitMqVHost { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> BulkQueue { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> DirectQueue { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> NotificationsQueue { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Uri RabbitMqConnection { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> DatabaseConnection { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> CacheConnection { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>There are a number of problems with this configuration:</p>
<p>First off, it lives in the <code>Domain</code> project, which kinda makes sense, as things in there need access to some of the properties - but none of them need to know the name of the Queue being listened to, or where the metrics are being written to.</p>
<p>Next, and also somewhat related to the first point, is that all the entry projects (<code>RestApi</code>, <code>QueueConsumer</code> and <code>Worker</code>) need to supply all the configuration values, and you can&rsquo;t tell at a glance which projects actually need which values.</p>
<p>Finally, classes which use this configuration are less externally discoverable.  For example, which properties does this need: <code>new DocumentDeduplicator(new Configuration())</code>? Probably the cache? Maybe the database? or possibly the DocumentsEndpoint?  Who knows without opening the class.</p>
<h2 id="the-solution">The Solution</h2>
<p>The key to solving this is the Interface Segregation Principal - the I in SOLID.  First we need to split the interface into logical parts, which will allow our consuming classes to only take in the configuration they require, rather than the whole thing:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IRabbitConfiguration</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    Uri RabbitMqConnection { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> RabbitMqUsername { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> RabbitMqPassword { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> RabbitMqVHost { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> BulkQueue { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> DirectQueue { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> NotificationsQueue { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IDeduplicationConfiguration</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    Uri DocumentsEndpoint { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> CacheConnection { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IStorageConfiguration</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    Uri ArchivalEndpoint { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> DatabaseConnection { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We can also move the <code>IRabbitConfiguration</code> and <code>IDeduplicationConfiguration</code> out of the domain project, and into the <code>QueueConsumer</code> and <code>Worker</code> projects respectively, as they are only used by types in these projects:</p>
<pre tabindex="0"><code>DemoService
`-- src
    |-- Domain
    |   |-- Domain.csproj
    |   `-- IStorageConfiguration.cs
    |-- QueueConsumer
    |   |-- app.config
    |   |-- IRabbitConfiguration.cs
    |   |-- QueueConsumerConfiguration.cs
    |   `-- QueueConsumer.csproj
    |-- RestApi
    |   |-- RestConfiguration.cs
    |   |-- RestApi.csproj
    |   `-- web.config
    `-- Worker
        |-- app.config
        |-- IDeduplicationConfiguration.cs
        |-- WorkerConfiguration.cs
        `-- Worker.csproj
</code></pre><p>Next we can create some top-level configuration interfaces, which compose the relevant configuration interfaces for a project (e.g. the <code>RestApi</code> doesn&rsquo;t need <code>IDeduplicationConfiguration</code> or <code>IRabbitConfiguration</code>):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IWorkerConfiguration</span> : IStorageConfiguration, IDeduplicationConfiguration
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> ApplicationName { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> LogPath { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    Uri MetricsEndpoint { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IRestConfiguration</span> : IStorageConfiguration
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> ApplicationName { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> LogPath { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    Uri MetricsEndpoint { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IQueueConsumerConfiguration</span> : IStorageConfiguration, IRabbitConfiguration
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> ApplicationName { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> LogPath { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    Uri MetricsEndpoint { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note how we have also not created a central interface for the application configuration - this is because the application configuration is specific to each entry project, and has no need to be passed on to the domain.</p>
<p>Finally, an actual configuration class can be implemented (in this case using <a href="https://github.com/pondidum/stronk">Stronk</a>, but if you are on dotnet core, the inbuilt configuration builder is fine):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">QueueConsumerConfiguration</span> : IQueueConsumerConfiguration
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> ApplicationName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> LogPath { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>    Uri MetricsEndpoint { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Uri ArchivalEndpoint { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> DatabaseConnection { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>    Uri RabbitMqConnection { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> RabbitMqUsername { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> RabbitMqPassword { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> RabbitMqVHost { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> BulkQueue { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> DirectQueue { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> NotificationsQueue { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> QueueConsumerConfiguration()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span>.FromAppConfig();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And our startup class might look something like this (using <a href="http://structuremap.github.io/">StructureMap</a>):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Startup</span> : IDisposable
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Container _container;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IConsumer _consumer;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Startup(IQueueConsumerConfiguration config)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        ConfigureLogging(config);
</span></span><span style="display:flex;"><span>        ConfigureMetrics(config);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        _container = <span style="color:#66d9ef">new</span> Container(_ =&gt;
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            _.Scan(a =&gt; {
</span></span><span style="display:flex;"><span>                a.TheCallingAssembly();
</span></span><span style="display:flex;"><span>                a.LookForRegistries();
</span></span><span style="display:flex;"><span>            })
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            _.For&lt;IQueueConsumerConfiguration&gt;().Use(config);
</span></span><span style="display:flex;"><span>            _.For&lt;IStorageConfiguration&gt;().Use(config);
</span></span><span style="display:flex;"><span>            _.For&lt;IRabbitConfiguration&gt;().Use(config);
</span></span><span style="display:flex;"><span>        });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        _consumer = _container.GetInstance&lt;IConsumer&gt;();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task Start() =&gt; <span style="color:#66d9ef">await</span> _consumer.Start();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task Stop() =&gt; <span style="color:#66d9ef">await</span> _consumer.Stop();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> ConfigureLogging(IQueueConsumerConfiguration config) { <span style="color:#75715e">/* ... */</span> }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> ConfigureMetrics(IQueueConsumerConfiguration config) { <span style="color:#75715e">/* ... */</span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Dispose() =&gt; _container.Dispose();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As our <code>Startup</code> takes in the top-level configuration interface, if we want to write a test which tests our entire system, it can be done with a single mocked configuration object:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#a6e22e">[Fact]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task When_the_entire_system_is_run()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> config = Substitute.For&lt;IQueueConsumerConfiguration&gt;();
</span></span><span style="display:flex;"><span>    config.RabbitMqConnection.Returns(<span style="color:#66d9ef">new</span> Uri(<span style="color:#e6db74">&#34;localhost:5672&#34;</span>));
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// etc.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> startup = <span style="color:#66d9ef">new</span> Startup(config);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> startup.Start();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> startup.Stop();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="one-final-thing">One Final Thing</h2>
<p>Even if you have a microservice type project with only the one csproj, I would still recommend splitting your configuration into small interfaces, just due to the discoverability it provides.</p>
<p>How do you do configuration?</p>
]]></content:encoded></item><item><title>Alarm Fatigue</title><link>https://andydote.co.uk/2017/10/30/alarm-fatigue/</link><pubDate>Mon, 30 Oct 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/10/30/alarm-fatigue/</guid><description>I&amp;rsquo;ve been on-call for work over the last week for the first time, and while it wasn&amp;rsquo;t as alarming (heh) as I thought it might be, I have had a few thoughts on it.
Non-action Alarms We have an alarm periodically about an MVC View not getting passed the right kind of model. The resolution is to mark the bug as completed/ignored in YouTrack. Reading the stack trace, I can see that the page is expecting a particular model, but is being given a HandleErrorInfo model, which is an in built type.</description><content:encoded><![CDATA[<p>I&rsquo;ve been on-call for work over the last week for the first time, and while it wasn&rsquo;t as alarming (heh) as I thought it might be, I have had a few thoughts on it.</p>
<h2 id="non-action-alarms">Non-action Alarms</h2>
<p>We have an alarm periodically about an MVC View not getting passed the right kind of model.  The resolution is to mark the bug as completed/ignored in YouTrack.  Reading the stack trace, I can see that the page is expecting a particular model, but is being given a <code>HandleErrorInfo</code> model, which is an in built type.  After some investigation and a quick pull-request, we no longer get that error message.  Turns out the controller was missing an attribute which would allow custom error handling.</p>
<h2 id="un-aggregated-alarms">Un-aggregated Alarms</h2>
<p>If there is one time out in a system&hellip;I don&rsquo;t care that much. If there are multiple in a short space of time then I want an alarm. Otherwise, it should be logged and reviewed when I am next at the office, so I can look  for a pattern, such as it happening hourly on the hour, or every 28 hours.</p>
<h2 id="bad-error-messages">Bad Error Messages</h2>
<p><code>No or more than one usable entry found</code> - this exception makes sense, if you have the context it is thrown from.  However, when reading the stacktrace in YouTrack, it&rsquo;s not idea.  Some investigation shows that all of the data required to write some good exception messages is available.</p>
<p>This gets harder when the exception is thrown from a library, especially when most of the code required to generate the exception is marked as internal, and that the library only throws one kind of error, differing only by message.  They way I will solve this one is to catch the error, and if the message is the one I care about, throw a new version with a better message.  Unfortunately to build that message, I will have to regex the first exception&rsquo;s message.  Sad times.</p>
<h2 id="run-books">Run Books</h2>
<p>We have some! Not as many as I would like, but hopefully I can expand on them as I learn things.  One thing I noticed about them is they are named after the business purpose, which is great from a business perspective&hellip;but is not so great when I am looking to see if there is a run book for an exception in YouTrack.  A few things can be done to fix this.</p>
<p>First off, we can rename the run books to resemble the exception messages to make them easier to find.  The business description can be included as a sub-title, or in the body of the run book.</p>
<p>Next is to update the exceptions thrown to have a link to the relevant run book in them, so that when someone opens a ticket in YouTrack, they can see the link to the how to solve it.</p>
<p>Third, and my favourite, is to get rid of the run book entirely, by automating it.  If the run book contains a fix like &ldquo;run x query, and if it has rows, change this column to mark the job as processed&rdquo;, then we can just make the code itself handle this case, or modify the code to prevent this case from happening at all.</p>
<h2 id="overall">Overall</h2>
<p>Overall, I enjoyed being on call this week.  Nothing caught fire too much, and I have learnt quite a bit about various parts of our system which I don&rsquo;t often interact with.  But on-call (and thus on-boarding) can be improved - so that&rsquo;s what I am going to do.  Hopefully when a new person enters the on-call schedule, they will have an even easier time getting up to speed.</p>
]]></content:encoded></item><item><title>Vagrant in the world of Docker</title><link>https://andydote.co.uk/2017/10/22/vagrant-in-a-world-of-docker/</link><pubDate>Sun, 22 Oct 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/10/22/vagrant-in-a-world-of-docker/</guid><description>I gave a little talk at work recently on my use of Vagrant, what it is, and why it is still useful in a world full of Docker containers.
So, What is Vagrant? Vagrant is a product by Hashicorp, and is for scripting the creation of (temporary) virtual machines. It&amp;rsquo;s pretty fast to create a virtual machine with too, as it creates them from a base image (known as a &amp;ldquo;box&amp;rdquo;.</description><content:encoded><![CDATA[<p>I gave a little talk at work recently on my use of Vagrant, what it is, and why it is still useful in a world full of Docker containers.</p>
<h2 id="so-what-is-vagrant">So, What is Vagrant?</h2>
<p><a href="">Vagrant</a> is a product by Hashicorp, and is for scripting the creation of (temporary) virtual machines.  It&rsquo;s pretty fast to create a virtual machine with too, as it creates them from a base image (known as a &ldquo;box&rdquo;.)</p>
<p>It also supports multiple virtualisation tools, such as VirtualBox and HyperV.  If you are already using <a href="https://www.packer.io">Packer</a> to create AMIs for your Amazon infrastructure, you can modify your packerfile to also output a Vagrant box.</p>
<p>As an example, this is a really basic VagrantFile for creating a basic Ubuntu box:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">Vagrant</span><span style="color:#f92672">.</span>configure(<span style="color:#e6db74">&#34;2&#34;</span>) <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>config<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>box <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hashicorp/precise64&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provider <span style="color:#e6db74">&#34;hyperv&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>h<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>    h<span style="color:#f92672">.</span>vmname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;UbuntuPrecise&#34;</span>
</span></span><span style="display:flex;"><span>    h<span style="color:#f92672">.</span>cpus <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>    h<span style="color:#f92672">.</span>memory <span style="color:#f92672">=</span> <span style="color:#ae81ff">2048</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>To create the vm, on your command line just run</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vagrant up <span style="color:#75715e"># creates the virtual machine</span>
</span></span><span style="display:flex;"><span>vagrant ssh <span style="color:#75715e"># ssh into the virtual machine</span>
</span></span><span style="display:flex;"><span>vagrant destroy -f <span style="color:#75715e"># destroy the virtual machine</span>
</span></span></code></pre></div><h2 id="what-can-i-use-it-for">What can I use it for?</h2>
<p>Personally I have three main uses for a Vagrant boxes; Performance/Environment Testing, Cluster Testing, and Complete Environment Setup.</p>
<h3 id="performance-and-environment-testing">Performance and Environment Testing</h3>
<p>When I am developing a service which will be deployed to AWS, we tend to know rougly what kind of instance it will be deployed to, for example <code>T2.Small</code>.  The code we develop local performs well&hellip;but that is on a development machine with anywhere from 4 to 16 CPU cores, and 8 to 32 GB of memory, and SSD storage.  How do you know what performance will be like when running on a 2 core, 2048 MB machine in AWS?</p>
<p>While you can&rsquo;t emulate AWS exactly, it has certainly helped us tune applications - for example modifying how many parallel messages to handle when receiving from RabbitMQ (you can see about how to configure this in my previous post <a href="2017/10/11/masstransit-rabbitmq-concurrency-testing/">Concurrency in RabbitMQ</a>.)</p>
<h3 id="cluster-testing">Cluster Testing</h3>
<p>When you want to test a service which will operate in a cluster, Vagrant comes to the rescue again - you can use the <code>define</code> block to setup multiple copies of the machine, and provide common provisioning:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">Vagrant</span><span style="color:#f92672">.</span>configure(<span style="color:#e6db74">&#34;2&#34;</span>) <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>config<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>box <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hashicorp/precise64&#34;</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provision <span style="color:#e6db74">&#34;shell&#34;</span>, <span style="color:#e6db74">inline</span>: <span style="color:#e6db74">&lt;&lt;SCRIPT
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"></span>  <span style="color:#75715e"># a bash script to setup your service might go here</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">SCRIPT</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provider <span style="color:#e6db74">&#34;hyperv&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>h<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>    h<span style="color:#f92672">.</span>vmname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;UbuntuPrecise&#34;</span>
</span></span><span style="display:flex;"><span>    h<span style="color:#f92672">.</span>cpus <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>    h<span style="color:#f92672">.</span>memory <span style="color:#f92672">=</span> <span style="color:#ae81ff">1024</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;first&#34;</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;second&#34;</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;third&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>If you want to do more configuration of your separate instances, you can provider a block to do so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>define <span style="color:#e6db74">&#34;third&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>third<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>    third<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provision <span style="color:#e6db74">&#34;shell&#34;</span>, <span style="color:#e6db74">inline</span>: <span style="color:#e6db74">&#34;./vagrant/boot-cluster.sh&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span></code></pre></div><h3 id="complete-environment">Complete Environment</h3>
<p>If you&rsquo;re developing a microservice in an environment with many other microservies which it needs to interact with, it can be a pain to setup all the hosts and supporting infrastructure.</p>
<p>Instead, we can create a single base box which contains all of the setup and services, then each microservice can have a VagrantFile which is based off the base box, but also: stops the service you are developing, and starts the version which is located in the <code>/vagrant</code> share instead:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">Vagrant</span><span style="color:#f92672">.</span>configure(<span style="color:#e6db74">&#34;2&#34;</span>) <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>config<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>box <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;mycorp/complete-environment&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provider <span style="color:#e6db74">&#34;hyperv&#34;</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>h<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>    h<span style="color:#f92672">.</span>vmname <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;WhateverServiceEnvironment&#34;</span>
</span></span><span style="display:flex;"><span>    h<span style="color:#f92672">.</span>cpus <span style="color:#f92672">=</span> <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>    h<span style="color:#f92672">.</span>memory <span style="color:#f92672">=</span> <span style="color:#ae81ff">4096</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># replace-service is a script which stops/removes an existing service,</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># and installs/starts a replacement. it uses a convention which expects</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># a service to have a script at `/vagrant/&lt;name&gt;/bin/&lt;name&gt;.sh`</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>provision <span style="color:#e6db74">&#34;shell&#34;</span>, <span style="color:#e6db74">inline</span>: <span style="color:#e6db74">&#34;./replace-service.sh WhateverService&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>In this case, the <code>mycorp/complete-environment</code> box would have all the services installed and started, and also a script in the machine root which does all the work to replace a service with the one under development.</p>
<p>This base box could also be used to provide a complete testing environment too - just create a Vagrant file with no additional provisioning, and call <code>vagrant up</code>.</p>
<h2 id="couldnt-you-use-docker-for-this-instead">Couldn&rsquo;t you use Docker for this instead?</h2>
<p>Well yes, you can user Docker&hellip;but for some tasks, this is just easier.  We can also utilise Docker as both input and output for this; the base image could run docker internally to run all the services, or we could use a Packer script which would generate a Docker container of this setup <strong>and</strong> a vagrant box.</p>
<p>Just because Docker is the cool thing to be using these days, doesn&rsquo;t mean Vagrant doesn&rsquo;t have any uses any more.  Far from it!</p>
]]></content:encoded></item><item><title>Testing RabbitMQ Concurrency in MassTransit</title><link>https://andydote.co.uk/2017/10/11/masstransit-rabbitmq-concurrency-testing/</link><pubDate>Wed, 11 Oct 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/10/11/masstransit-rabbitmq-concurrency-testing/</guid><description>We have a service which consumes messages from a RabbitMQ queue - for each message, it makes a few http calls, collates the results, does a little processing, and then pushes the results to a 3rd party api. One of the main benefits to having this behind a queue is our usage pattern - the queue usually only has a few messages in it per second, but periodically it will get a million or so messages within 30 minutes (so from ~5 messages/second to ~560 messages/second.</description><content:encoded><![CDATA[<p>We have a service which consumes messages from a <a href="http://www.rabbitmq.com/">RabbitMQ</a> queue - for each message, it makes a few http calls, collates the results, does a little processing, and then pushes the results to a 3rd party api.  One of the main benefits to having this behind a queue is our usage pattern - the queue usually only has a few messages in it per second, but periodically it will get a million or so messages within 30 minutes (so from ~5 messages/second to ~560 messages/second.)</p>
<p>Processing this spike of messages takes ages, and while this service is only on a <code>T2.Medium</code> machine (2 CPUs, 4GB Memory), it only uses 5-10% CPU while processing the messages, which is clearly pretty inefficient.</p>
<p>We use <a href="http://masstransit-project.com/">MassTransit</a> when interacting with RabbitMQ as it provides us with a lot of useful features, but by default sets the amount of messages to be processed in parallel to <code>Environment.ProcessorCount * 2</code>.  For this project that means 4 messages, and as the process is IO bound, it stands to reason that we could increase that concurrency a bit. Or a lot.</p>
<p>The existing MassTransit setup looks pretty similar to this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>_bus = Bus.Factory.CreateUsingRabbitMq(rabbit =&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> host = rabbit.Host(<span style="color:#66d9ef">new</span> Uri(<span style="color:#e6db74">&#34;rabbitmq://localhost&#34;</span>), h =&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        h.Username(<span style="color:#e6db74">&#34;guest&#34;</span>);
</span></span><span style="display:flex;"><span>        h.Password(<span style="color:#e6db74">&#34;guest&#34;</span>);
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    rabbit.ReceiveEndpoint(host, <span style="color:#e6db74">&#34;SpikyQueue&#34;</span>, endpoint =&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        endpoint.Consumer(() =&gt; <span style="color:#66d9ef">new</span> TestConsumer());
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><h2 id="the-test-driven-development">The Test (Driven Development)</h2>
<p>As we like testing things, I wrote a test to validate the degree of concurrency we have.  We use a real instance of RabbitMQ (<a href="/2017/10/02/dotnet-core-docker-integration-tests/">Started with Docker, as part of the build</a>), and have a test message and consumer.  Due to the speed of RabbitMQ delivery, we make the consumer just take a little bit of time before returning:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TestMessage</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> Value { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TestConsumer</span> : IConsumer&lt;TestMessage&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task Consume(ConsumeContext&lt;TestMessage&gt; context)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> Task.Delay(<span style="color:#ae81ff">600</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The final piece of our puzzle is an <code>IConsumeObserver</code>, which will count the number of messages processed in parallel, as well as the total number of messages processed.  We will use the total number of messages to know when our test can stop running, and the parallel number to prove if our concurrency changes worked.</p>
<p>What this observer is doing is the following, but as we are in a multithreaded environment, we need to use the <code>Interlocked</code> class, and do a bit more work to make sure we don&rsquo;t lose values:</p>
<pre tabindex="0"><code>PreConsume:
    currentPendingDeliveryCount++
    maxPendingDeliveryCount = Math.Max(maxPendingDeliveryCount, currentPendingDeliveryCount)
PostConsume:
    currentPendingDeliveryCount--
</code></pre><p>The actual <code>ConsumeCountObserver</code> code is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ConsumeCountObserver</span> : IConsumeObserver
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> _deliveryCount;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> _currentPendingDeliveryCount;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> _maxPendingDeliveryCount;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">readonly</span> <span style="color:#66d9ef">int</span> _messageCount;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">readonly</span> TaskCompletionSource&lt;<span style="color:#66d9ef">bool</span>&gt; _complete;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> ConsumeCountObserver(<span style="color:#66d9ef">int</span> messageCount)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        _messageCount = messageCount;
</span></span><span style="display:flex;"><span>        _complete = <span style="color:#66d9ef">new</span> TaskCompletionSource&lt;<span style="color:#66d9ef">bool</span>&gt;();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> MaxDeliveryCount =&gt; _maxPendingDeliveryCount;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task Wait() =&gt; <span style="color:#66d9ef">await</span> _complete.Task;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Task IConsumeObserver.ConsumeFault&lt;T&gt;(ConsumeContext&lt;T&gt; context, Exception exception) =&gt; Task.CompletedTask;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Task IConsumeObserver.PreConsume&lt;T&gt;(ConsumeContext&lt;T&gt; context)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        Interlocked.Increment(<span style="color:#66d9ef">ref</span> _deliveryCount);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> current = Interlocked.Increment(<span style="color:#66d9ef">ref</span> _currentPendingDeliveryCount);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">while</span> (current &gt; _maxPendingDeliveryCount)
</span></span><span style="display:flex;"><span>            Interlocked.CompareExchange(<span style="color:#66d9ef">ref</span> _maxPendingDeliveryCount, current, _maxPendingDeliveryCount);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> Task.CompletedTask;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Task IConsumeObserver.PostConsume&lt;T&gt;(ConsumeContext&lt;T&gt; context)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        Interlocked.Decrement(<span style="color:#66d9ef">ref</span> _currentPendingDeliveryCount);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (_deliveryCount == _messageCount)
</span></span><span style="display:flex;"><span>            _complete.TrySetResult(<span style="color:#66d9ef">true</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> Task.CompletedTask;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Finally, we can put the actual test together:  We publish some messages, connect the observer, and start processing.  Finally, when the observer indicates we have finished, we assert that the <code>MaxDeliveryCount</code> was the same as the <code>ConcurrencyLimit</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#a6e22e">[Test]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task WhenTestingSomething()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">var</span> i = <span style="color:#ae81ff">0</span>; i &lt; MessageCount; i++)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> _bus.Publish(<span style="color:#66d9ef">new</span> TestMessage { Value = i });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> observer = <span style="color:#66d9ef">new</span> ConsumeCountObserver(MessageCount);
</span></span><span style="display:flex;"><span>    _bus.ConnectConsumeObserver(observer);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> _bus.StartAsync();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> observer.Wait();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> _bus.StopAsync();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    observer.MaxDeliveryCount.ShouldBe(ConcurrencyLimit);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="the-problem">The Problem</h2>
<p>The problem we had was actually increasing the concurrency:  There are two things you can change, <code>.UseConcurrencyLimit(32)</code> and <code>.PrefetchCount = 32</code>, but doing this doesn&rsquo;t work:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>_bus = Bus.Factory.CreateUsingRabbitMq(rabbit =&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> host = rabbit.Host(<span style="color:#66d9ef">new</span> Uri(<span style="color:#e6db74">&#34;rabbitmq://localhost&#34;</span>), h =&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        h.Username(<span style="color:#e6db74">&#34;guest&#34;</span>);
</span></span><span style="display:flex;"><span>        h.Password(<span style="color:#e6db74">&#34;guest&#34;</span>);
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    rabbit.ReceiveEndpoint(host, <span style="color:#e6db74">&#34;SpikeyQueue&#34;</span>, endpoint =&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        endpoint.UseConcurrencyLimit(ConcurrencyLimit);
</span></span><span style="display:flex;"><span>        endpoint.PrefetchCount = (<span style="color:#66d9ef">ushort</span>) ConcurrencyLimit;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        endpoint.Consumer(() =&gt; <span style="color:#66d9ef">new</span> TestConsumer());
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>Or well&hellip;it does work, if the <code>ConcurrencyLimit</code> is <strong>less</strong> than the default.  After a lot of trial and error, it turns out there are not two things you can change, but four:</p>
<ul>
<li><code>rabbit.UseConcurrencyLimit(val)</code></li>
<li><code>rabbit.PrefetchCount = val</code></li>
<li><code>endpoint.UseConcurrencyLimit(val)</code></li>
<li><code>endpoint.PrefetchCount = val</code></li>
</ul>
<p>This makes sense (kind of): You can set limits on the factory, and then the endpoints can be any value less than or equal to the factory limits.  My process of trial and error to work out which needed to be set:</p>
<ol>
<li>Set them all to 32</li>
<li>Run test
<ul>
<li>if it passes, remove one setting, go to 2.</li>
<li>if it fails, add last setting back, remove a different setting, go to 2.</li>
</ul>
</li>
</ol>
<p>After iterating this set of steps for a while, it turns out for my use case that I need to set <code>rabbit.UseConcurrencyLimit(val)</code> and <code>endpoint.PrefetchCount = val</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>_bus = Bus.Factory.CreateUsingRabbitMq(rabbit =&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> host = rabbit.Host(<span style="color:#66d9ef">new</span> Uri(<span style="color:#e6db74">&#34;rabbitmq://localhost&#34;</span>), h =&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        h.Username(<span style="color:#e6db74">&#34;guest&#34;</span>);
</span></span><span style="display:flex;"><span>        h.Password(<span style="color:#e6db74">&#34;guest&#34;</span>);
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    rabbit.UseConcurrencyLimit(ConcurrencyLimit);
</span></span><span style="display:flex;"><span>    rabbit.ReceiveEndpoint(host, <span style="color:#e6db74">&#34;SpikeyQueue&#34;</span>, endpoint =&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        endpoint.PrefetchCount = (<span style="color:#66d9ef">ushort</span>) ConcurrencyLimit;
</span></span><span style="display:flex;"><span>        endpoint.Consumer(() =&gt; <span style="color:#66d9ef">new</span> TestConsumer());
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>Interestingly, no matter which place you set the <code>PrefetchCount</code> value, it doesn&rsquo;t show up in the RabbitMQ web dashboard.</p>
<p>Hope this might help someone else struggling with getting higher concurrency with MassTransit.</p>
]]></content:encoded></item><item><title>Composite Decorators with StructureMap</title><link>https://andydote.co.uk/2017/10/04/structuremap-composite-decorator/</link><pubDate>Wed, 04 Oct 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/10/04/structuremap-composite-decorator/</guid><description>While I was developing my Crispin project, I ended up needing to create a bunch of implementations of a single interface, and then use all those implementations at once (for metrics logging).
The interface looks like so:
public interface IStatisticsWriter { Task WriteCount(string format, params object[] parameters); } And we have a few implementations already:
LoggingStatisticsWriter - writes to an ILogger instance StatsdStatisticsWriter - pushes metrics to StatsD InternalStatisticsWriter - aggregates metrics for exposing via Crispin&amp;rsquo;s api To make all of these be used together, I created a fourth implementation, called CompositeStatisticsWriter (a name I made up, but apparently matches the Gang of Four definition of a composite!</description><content:encoded><![CDATA[<p>While I was developing my <a href="https://github.com/pondidum/crispin">Crispin</a> project, I ended up needing to create a bunch of implementations of a single interface, and then use all those implementations at once (for metrics logging).</p>
<p>The interface looks like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IStatisticsWriter</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    Task WriteCount(<span style="color:#66d9ef">string</span> format, <span style="color:#66d9ef">params</span> <span style="color:#66d9ef">object</span>[] parameters);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And we have a few implementations already:</p>
<ul>
<li>LoggingStatisticsWriter - writes to an <code>ILogger</code> instance</li>
<li>StatsdStatisticsWriter - pushes metrics to <a href="https://github.com/etsy/statsd">StatsD</a></li>
<li>InternalStatisticsWriter - aggregates metrics for exposing via Crispin&rsquo;s api</li>
</ul>
<p>To make all of these be used together, I created a fourth implementation, called <code>CompositeStatisticsWriter</code> (a name I made up, but apparently matches the <a href="https://en.wikipedia.org/wiki/Composite_pattern">Gang of Four definition</a> of a composite!)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">CompositeStatisticsWriter</span> : IStatisticsWriter
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IStatisticsWriter[] _writers;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> CompositeStatisticsWriter(IEnumerable&lt;IStatisticsWriter&gt; writers)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        _writers = writers.ToArray();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task WriteCount(<span style="color:#66d9ef">string</span> format, <span style="color:#66d9ef">params</span> <span style="color:#66d9ef">object</span>[] parameters)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> Task.WhenAll(_writers
</span></span><span style="display:flex;"><span>            .Select(writer =&gt; writer.WriteCount(format, parameters))
</span></span><span style="display:flex;"><span>            .ToArray());
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The problem with doing this is that StructureMap throws an error about a bi-directional dependency:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>StructureMap.Building.StructureMapBuildException : Bi-directional dependency relationship detected!
</span></span><span style="display:flex;"><span>Check the StructureMap stacktrace below:
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1.</span>) Instance of Crispin.Infrastructure.Statistics.IStatisticsWriter (Crispin.Infrastructure.Statistics.CompositeStatisticsWriter)
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2.</span>) All registered children <span style="color:#66d9ef">for</span> IEnumerable&lt;IStatisticsWriter&gt;
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3.</span>) Instance of IEnumerable&lt;IStatisticsWriter&gt;
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4.</span>) <span style="color:#66d9ef">new</span> CompositeStatisticsWriter(*Default of IEnumerable&lt;IStatisticsWriter&gt;*)
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5.</span>) Crispin.Infrastructure.Statistics.CompositeStatisticsWriter
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">6.</span>) Instance of Crispin.Infrastructure.Statistics.IStatisticsWriter (Crispin.Infrastructure.Statistics.CompositeStatisticsWriter)
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">7.</span>) Container.GetInstance&lt;Crispin.Infrastructure.Statistics.IStatisticsWriter&gt;()
</span></span></code></pre></div><p>After attempting to solve this myself in a few different ways (you can even <a href="https://www.youtube.com/watch?v=2N6cgMBN7ZA">watch the stream</a> of my attempts), I asked in the StructreMap gitter chat room, and received this answer:</p>
<blockquote>
<p>This has come up a couple times, and yeah, you’ll either need a custom convention or a policy that adds the other <code>ITest</code>’s to the instance for <code>CompositeTest</code> as inline dependencies so it doesn’t try to make Composite a dependency of itself
&ndash; <cite>Jeremy D. Miller</cite></p>
</blockquote>
<p>Finally, Babu Annamalai provided a simple implementation when I got stuck (again).</p>
<p>The result is the creation of a custom convention for registering the composite, which provides all the implementations I want it to wrap:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">CompositeDecorator</span>&lt;TComposite, TDependents&gt; : IRegistrationConvention
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">where</span> TComposite : TDependents
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> ScanTypes(TypeSet types, Registry registry)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> dependents = types
</span></span><span style="display:flex;"><span>            .FindTypes(TypeClassification.Concretes)
</span></span><span style="display:flex;"><span>            .Where(t =&gt; t.CanBeCastTo&lt;TDependents&gt;() &amp;&amp; t.HasConstructors())
</span></span><span style="display:flex;"><span>            .Where(t =&gt; t != <span style="color:#66d9ef">typeof</span>(TComposite))
</span></span><span style="display:flex;"><span>            .ToList();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        registry
</span></span><span style="display:flex;"><span>            .For&lt;TDependents&gt;()
</span></span><span style="display:flex;"><span>            .Use&lt;TComposite&gt;()
</span></span><span style="display:flex;"><span>            .EnumerableOf&lt;TDependents&gt;()
</span></span><span style="display:flex;"><span>            .Contains(x =&gt; dependents.ForEach(t =&gt; x.Type(t)));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>To use this the StructureMap configuration changes from this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> CrispinRestRegistry()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    Scan(a =&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        a.AssemblyContainingType&lt;Toggle&gt;();
</span></span><span style="display:flex;"><span>        a.WithDefaultConventions();
</span></span><span style="display:flex;"><span>        a.AddAllTypesOf&lt;IStatisticsWriter&gt;();
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> store = BuildStorage();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    For&lt;IStorage&gt;().Use(store);
</span></span><span style="display:flex;"><span>    For&lt;IStatisticsWriter&gt;().Use&lt;CompositeStatisticsWriter&gt;();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>To this version:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> CrispinRestRegistry()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    Scan(a =&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        a.AssemblyContainingType&lt;Toggle&gt;();
</span></span><span style="display:flex;"><span>        a.WithDefaultConventions();
</span></span><span style="display:flex;"><span>        a.Convention&lt;CompositeDecorator&lt;CompositeStatisticsWriter, IStatisticsWriter&gt;&gt;();
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> store = BuildStorage();
</span></span><span style="display:flex;"><span>    For&lt;IStorage&gt;().Use(store);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And now everything works successfully, and I have Pull Request open on StructureMap&rsquo;s repo with an update to the documentation about this.</p>
<p>Hopefully this helps someone else too!</p>
]]></content:encoded></item><item><title>Integration Testing with Dotnet Core, Docker and RabbitMQ</title><link>https://andydote.co.uk/2017/10/02/dotnet-core-docker-integration-tests/</link><pubDate>Mon, 02 Oct 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/10/02/dotnet-core-docker-integration-tests/</guid><description>When building libraries, not only is it a good idea to have a large suite of Unit Tests, but also a suite of Integration Tests.
For one of my libraries (RabbitHarness) I have a set of tests which check it behaves as expected against a real instance of RabbitMQ. Ideally these tests will always be run, but sometimes RabbitMQ just isn&amp;rsquo;t available such as when running on AppVeyor builds, or if I haven&amp;rsquo;t started my local RabbitMQ Docker container.</description><content:encoded><![CDATA[<p>When building libraries, not only is it a good idea to have a large suite of Unit Tests, but also a suite of Integration Tests.</p>
<p>For one of my libraries (<a href="https://github.com/pondidum/rabbitharness">RabbitHarness</a>) I have a set of tests which check it behaves as expected against a real instance of <a href="http://www.rabbitmq.com/">RabbitMQ</a>.  Ideally these tests will always be run, but sometimes RabbitMQ just isn&rsquo;t available such as when running on <a href="https://ci.appveyor.com/project/Pondidum/rabbitharness">AppVeyor</a> builds, or if I haven&rsquo;t started my local RabbitMQ Docker container.</p>
<h2 id="skipping-tests-if-rabbitmq-is-not-available">Skipping tests if RabbitMQ is not available</h2>
<p>First off, I prevent the tests from running if RabbitMQ is not available by using a custom <a href="https://xunit.github.io/">XUnit</a> <code>FactAttribute</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">RequiresRabbitFactAttribute</span> : FactAttribute
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">readonly</span> Lazy&lt;<span style="color:#66d9ef">bool</span>&gt; IsAvailable = <span style="color:#66d9ef">new</span> Lazy&lt;<span style="color:#66d9ef">bool</span>&gt;(() =&gt;
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> factory = <span style="color:#66d9ef">new</span> ConnectionFactory { HostName = <span style="color:#e6db74">&#34;localhost&#34;</span>, RequestedConnectionTimeout = <span style="color:#ae81ff">1000</span> };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">try</span>
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> connection = factory.CreateConnection())
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">return</span> connection.IsOpen;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">catch</span> (Exception)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">false</span>;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">string</span> Skip
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> IsAvailable.Value ? <span style="color:#e6db74">&#34;&#34;</span> : <span style="color:#e6db74">&#34;RabbitMQ is not available&#34;</span>;  }
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">set</span> { <span style="color:#75715e">/* nothing */</span> }
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This attribute will try connecting to a RabbitMQ instance on <code>localhost</code> once for all tests per run, and cause any test with this attribute to be skipped if RabbitMQ is not available.</p>
<h2 id="build-script--docker">Build Script &amp; Docker</h2>
<p>I decided the build script should start a RabbitMQ container, and use that for the tests, but I didn&rsquo;t want to re-use my standard RabbitMQ instance which I use for all kinds of things, and may well be broken at any given time.</p>
<p>As my build script is just a <code>bash</code> script, I can check if the <code>docker</code> command is available, and then start a container if it is (relying on the assumption that if <code>docker</code> is available, I can start a container).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -x <span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">$(</span>command -v docker<span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  CONTAINER<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>docker run -d --rm -p 5672:5672 rabbitmq:3.6.11-alpine<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Started RabbitMQ container: </span>$CONTAINER<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span></code></pre></div><p>If <code>docker</code> is available, we start a new container.  I use <code>rabbitmq:3.6.11-alpine</code> as it is a tiny image, with no frills, and also start it with the <code>-d</code> and <code>--rm</code> flags, which starts the container in a disconnected mode (e.g. the <code>docker run</code> command returns instantly), and will delete the container when it is stopped, taking care of clean up for us! I only bother binding the main data connection port (<code>5672</code>), as that is all we are going to be using. Finally, the container&rsquo;s ID, which is returned by the <code>docker run</code> command, is stored in the <code>CONTAINER</code> variable.</p>
<p>I recommend putting this step as the very first part of your build script, as it gives the container time to start up RabbitMQ and be ready for connections while your build is running.  Otherwise I found I was needing to put a <code>sleep 5</code> command in afterwards to pause the script for a short time.</p>
<p>The script then continues on with the normal build process:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>dotnet restore <span style="color:#e6db74">&#34;</span>$NAME<span style="color:#e6db74">.sln&#34;</span>
</span></span><span style="display:flex;"><span>dotnet build <span style="color:#e6db74">&#34;</span>$NAME<span style="color:#e6db74">.sln&#34;</span> --configuration $MODE
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>find . -iname <span style="color:#e6db74">&#34;*.Tests.csproj&#34;</span> -type f -exec dotnet test <span style="color:#e6db74">&#34;{}&#34;</span> --configuration $MODE <span style="color:#ae81ff">\;</span>
</span></span><span style="display:flex;"><span>dotnet pack ./src/$NAME --configuration $MODE --output ../../.build
</span></span></code></pre></div><p>Once this is all done, I have another check that <code>docker</code> exists, and stop the container we started earlier, by using the container ID in <code>CONTAINER</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -x <span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">$(</span>command -v docker<span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  docker stop $CONTAINER
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span></code></pre></div><p>And that&rsquo;s it!  You can see the full <a href="https://github.com/Pondidum/RabbitHarness/blob/master/build.sh">build script for RabbitHarness here</a>.</p>
<p>The only problem with this script is if you try and start a RabbitMQ container while you already have one running, the command will fail, but the build should succeed anyway as the running instance of RabbitMQ will work for the tests, and the <code>docker stop</code> command will just output that it can&rsquo;t find a container with a blank ID.</p>
<p>I think I will be using this technique more to help provide isolation for builds - I think that the <a href="https://hub.docker.com/r/microsoft/mssql-server-linux/">Microsoft/mssql-server-linux</a> containers might be very useful for some of our work codebases (which do work against the Linux instances of MSSQL, even if they weren&rsquo;t designed to!)</p>
]]></content:encoded></item><item><title>Implementing Custom Aspnet Core ModelBinders</title><link>https://andydote.co.uk/2017/09/22/implemeting-custom-aspnetcore-modelbinders/</link><pubDate>Fri, 22 Sep 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/09/22/implemeting-custom-aspnetcore-modelbinders/</guid><description>This post is a summary of a stream I did last night where I implemented all of this. If you want to watch me grumble my way through it, it&amp;rsquo;s available on YouTube here.
In my Crispin project, I wanted the ability to support loading Toggles by both name and ID, for all operations. As I use mediator to send messages from my controllers to the handlers in the domain, this means that I had to either:</description><content:encoded><![CDATA[<p>This post is a summary of a <a href="https://twitch.tv/pondidum">stream</a> I did last night where I implemented all of this.  If you want to watch me grumble my way through it, it&rsquo;s <a href="https://www.youtube.com/watch?v=hR213Oxj_xI">available on YouTube here</a>.</p>
<p>In my <a href="https://github.com/pondidum/crispin">Crispin</a> project, I wanted the ability to support loading Toggles by both name and ID, for all operations.  As I use mediator to send messages from my controllers to the handlers in the domain, this means that I had to either:</p>
<ul>
<li>create separate request types for loading by name and loading by id</li>
<li>have both an <code>ID</code> and <code>Name</code> property on each method</li>
</ul>
<p>I didn&rsquo;t like the sound of either of these as both involve more typing than I want to do, and the second variant has the added downside of causing a lot of <code>if</code> statements in the handlers, as you have to work out which is set before loading.  Not to mention the duplication of the load toggle logic in every handler.</p>
<p>The solution I came up with was to use some inheritance, a static factory, some method hiding, and a custom <code>IModelBinder</code>.</p>
<h2 id="togglelocator">ToggleLocator</h2>
<p>I started off by having an <code>abstract</code> base class called <code>ToggleLocator</code>.  To start with, it just has two static methods for creating an instance of <code>ToggleLocator</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ToggleLocator</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> ToggleLocator Create(Guid toggleID) =&gt; <span style="color:#66d9ef">new</span> ToggleLocatorByID(toggleID);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> ToggleLocator Create(<span style="color:#66d9ef">string</span> toggleName) =&gt; <span style="color:#66d9ef">new</span> ToggleLocatorByName(toggleName);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As this is going to be used in both Query handlers and Command handlers, I need to be able to load the Toggle (the EventSourced AggregateRoot), and the ToggleView (the projected current state of the AggregateRoot).  So we add two <code>abstract</code> methods to the <code>ToggleLocator</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">internal</span> <span style="color:#66d9ef">abstract</span> ToggleView LocateView(IStorageSession session);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">internal</span> <span style="color:#66d9ef">abstract</span> Toggle LocateAggregate(IStorageSession session);
</span></span></code></pre></div><p>Note that not only are these two methods <code>abstract</code>, they are also <code>internal</code> - we don&rsquo;t want anything outside the domain to know about how a toggle is loaded.  I was considering using an privately implemented interface to do this method hiding, but didn&rsquo;t see the point as I can acomplish the same using the internal methods.</p>
<p>We can now write two implementations of the <code>ToggleLocator</code>.  First up is the <code>ToggleLocatorByID</code>, which is very straight forward to implement; we use the ID to load the AggregateRoot directly, and the <code>AllToggles</code> view can be queried by ID to fetch the view version also.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ToggleLocatorByID</span> : ToggleLocator
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> ToggleID _toggleID;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> ToggleLocatorByID(ToggleID toggleID)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_toggleID = toggleID;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">internal</span> <span style="color:#66d9ef">override</span> ToggleView LocateView(IStorageSession session) =&gt; session
</span></span><span style="display:flex;"><span>		.LoadProjection&lt;AllToggles&gt;()
</span></span><span style="display:flex;"><span>		.Toggles
</span></span><span style="display:flex;"><span>		.SingleOrDefault(view =&gt; view.ID == _toggleID);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">internal</span> <span style="color:#66d9ef">override</span> Toggle LocateAggregate(IStorageSession session) =&gt; session
</span></span><span style="display:flex;"><span>		.LoadAggregate&lt;Toggle&gt;(_toggleID);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The more interesting class to implement is <code>ToggleLocatorByName</code>, as this needs to be able to load an AggregateRoot by name; something which is not directly supported.  So to do this we fetch the <code>ToggleView</code> first, and then use the <code>ID</code> property so we can load the <code>Toggle</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ToggleLocatorByName</span> : ToggleLocator
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> <span style="color:#66d9ef">string</span> _toggleName;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> ToggleLocatorByName(<span style="color:#66d9ef">string</span> toggleName)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_toggleName = toggleName;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">internal</span> <span style="color:#66d9ef">override</span> ToggleView LocateView(IStorageSession session) =&gt; session
</span></span><span style="display:flex;"><span>		.LoadProjection&lt;AllToggles&gt;()
</span></span><span style="display:flex;"><span>		.Toggles
</span></span><span style="display:flex;"><span>		.SingleOrDefault(t =&gt; t.Name.Equals(_toggleName, StringComparison.OrdinalIgnoreCase));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">internal</span> <span style="color:#66d9ef">override</span> Toggle LocateAggregate(IStorageSession session)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> view = LocateView(session);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> view != <span style="color:#66d9ef">null</span>
</span></span><span style="display:flex;"><span>			? session.LoadAggregate&lt;Toggle&gt;(view.ID)
</span></span><span style="display:flex;"><span>			: <span style="color:#66d9ef">null</span>;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>All this means that the handlers have no conditionals for loading, they just call the relevant <code>.Locate</code> method:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> Task&lt;UpdateToggleTagsResponse&gt; ModifyTags(ToggleLocator locator, Action&lt;Toggle&gt; modify)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> session = _storage.BeginSession())
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> toggle = locator.LocateAggregate(session);
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//or</span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> view  = locator.LocateView(session);
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//...</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And in the controllers, we have separate action methods for each route:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#a6e22e">[Route(&#34;name/{toggleName}/tags/{tagName}&#34;)]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">[HttpPut]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task&lt;IActionResult&gt; PutTag(<span style="color:#66d9ef">string</span> toggleName, <span style="color:#66d9ef">string</span> tagName)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> request = <span style="color:#66d9ef">new</span> AddToggleTagRequest(ToggleLocator.Create(toggleName), tagName);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> response = <span style="color:#66d9ef">await</span> _mediator.Send(request);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> JsonResult(response.Tags);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">[Route(&#34;id/{toggleID}/tags/{tagName}&#34;)]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">[HttpPut]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task&lt;IActionResult&gt; PutTag(Guid toggleID, <span style="color:#66d9ef">string</span> tagName)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> request = <span style="color:#66d9ef">new</span> AddToggleTagRequest(ToggleLocator.Create(ToggleID.Parse(toggleID)), tagName);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> response = <span style="color:#66d9ef">await</span> _mediator.Send(request);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> JsonResult(response.Tags);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>But that is still more duplication than I would like, so lets see if we can resolve this with a custom <code>IModelBinder</code>.</p>
<h2 id="custom-imodelbinder-for-togglelocator">Custom IModelBinder for ToggleLocator</h2>
<p>To make a custom model binder, we need to implement two interfaces: <code>IModelBinderProvider</code> and <code>IModelBinder</code>.  I am not sure why <code>IModelBinderProvider</code> exists to be perfectly honest, but you need it, and as it is doing nothing particularly interesting, I decided to implement both interfaces in the one class, and just return <code>this</code> from <code>IModelBinderProvider.GetBinder</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ToggleLocatorBinder</span> : IModelBinderProvider
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> IModelBinder GetBinder(ModelBinderProviderContext context)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (context.Metadata.ModelType == <span style="color:#66d9ef">typeof</span>(ToggleLocator))
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">this</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">null</span>;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We can then implement the second interface, <code>IModelBinder</code>.  Here we check (again) that the parameter is a <code>ToggleLocator</code>, fetch the value which came from the route (or querystring, thanks to the <code>.ValueProvider</code> property).</p>
<p>All I need to do here is try and parse the value as a <code>Guid</code>.  If it parses successfully, we create a <code>ToggleLocatorByID</code> instance, otherwise create a <code>ToggleLocatorByName</code> instance.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ToggleLocatorBinder</span> : IModelBinderProvider, IModelBinder
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Task BindModelAsync(ModelBindingContext bindingContext)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (bindingContext.ModelType != <span style="color:#66d9ef">typeof</span>(ToggleLocator))
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span> Task.CompletedTask;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> <span style="color:#66d9ef">value</span> = bindingContext.ValueProvider.GetValue(bindingContext.FieldName);
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> guid = Guid.Empty;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> locator = Guid.TryParse(<span style="color:#66d9ef">value</span>.FirstValue, <span style="color:#66d9ef">out</span> guid)
</span></span><span style="display:flex;"><span>			? ToggleLocator.Create(ToggleID.Parse(guid))
</span></span><span style="display:flex;"><span>			: ToggleLocator.Create(<span style="color:#66d9ef">value</span>.FirstValue);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		bindingContext.Result = ModelBindingResult.Success(locator);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> Task.CompletedTask;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We add this into our MVC registration code at the beginning of the <code>ModelBinderProviders</code> collection, as MVC will use the first binder which can support the target type, and there is a binder in the collection somewhere which will handle anything which inherits object&hellip;</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>services.AddMvc(options =&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	options.ModelBinderProviders.Insert(<span style="color:#ae81ff">0</span>, <span style="color:#66d9ef">new</span> ToggleLocatorBinder());
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>Now we can reduce our action methods down to one which handles both routes:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#a6e22e">[Route(&#34;id/{id}/tags/{tagName}&#34;)]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">[Route(&#34;name/{id}/tags/{tagName}&#34;)]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">[HttpPut]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task&lt;IActionResult&gt; PutTag(ToggleLocator id, <span style="color:#66d9ef">string</span> tagName)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> request = <span style="color:#66d9ef">new</span> AddToggleTagRequest(id, tagName);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> response = <span style="color:#66d9ef">await</span> _mediator.Send(request);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> JsonResult(response.Tags);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Much better, no duplication, and no (obvious) if statements!</p>
]]></content:encoded></item><item><title>Testing Containers or Test Behaviour, Not Implementation</title><link>https://andydote.co.uk/2017/09/17/testing-containers/</link><pubDate>Sun, 17 Sep 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/09/17/testing-containers/</guid><description>The trouble with testing containers is that usually the test ends up very tightly coupled to the implementation.
Let&amp;rsquo;s see an example. If we start off with an interface and implementation of a &amp;ldquo;cache&amp;rdquo;, which in this case is just going to store a single string value.
public interface ICache { string Value { get; set; } } public class Cache { public string Value { get; set; } } We then setup our container (StructureMap in this case) to return the same instance of the cache whenever an ICache is requested:</description><content:encoded><![CDATA[<p>The trouble with testing containers is that usually the test ends up very tightly coupled to the implementation.</p>
<p>Let&rsquo;s see an example.  If we start off with an interface and implementation of a &ldquo;cache&rdquo;, which in this case is just going to store a single string value.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">ICache</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> Value { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Cache</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> Value { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We then setup our container (<a href="http://structuremap.github.io">StructureMap</a> in this case) to return the same instance of the cache whenever an <code>ICache</code> is requested:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> container = <span style="color:#66d9ef">new</span> Container(_ =&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    _.For&lt;ICache&gt;().Use&lt;Cache&gt;().Singleton();
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>The following test is fairly typical of how this behaviour gets verified - it just compares that the same instance was returned by the container:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> first = container.GetInstance&lt;ICache&gt;();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> second = container.GetInstance&lt;ICache&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>first.ShouldBe(second);
</span></span></code></pre></div><p>But this is a very brittle test, as it is assuming that <code>ICache</code> will actually be the singleton.  However in the future, we might add in a decorator, or make the cache a totally different style of implementation which isn&rsquo;t singleton based.</p>
<p>For example, if we were to include a decorator class, which just logs reads and writes to the console:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">LoggingCache</span> : ICache
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Cache _backingCache;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> LoggingCache(Cache backingCache)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        _backingCache = backingCache;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> Value
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">get</span>
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            Console.WriteLine(<span style="color:#e6db74">&#34;Value fetched&#34;</span>);
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> _backingCache.Value;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">set</span>
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            Console.Write(<span style="color:#e6db74">$&#34;Value changed from {_backingCache.Value} to {value}&#34;</span>);
</span></span><span style="display:flex;"><span>            _backingCache.Value = <span style="color:#66d9ef">value</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Which will change our container registration:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> container = <span style="color:#66d9ef">new</span> Container(_ =&gt; {
</span></span><span style="display:flex;"><span>    _.ForSingletonOf&lt;Cache&gt;();
</span></span><span style="display:flex;"><span>    _.For&lt;ICache&gt;().Use&lt;LoggingCache&gt;();
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>The test will now fail, or need changing to match the new implementation.  This shows two things:</p>
<ul>
<li>Tests are tightly coupled to the implementation</li>
<li>Tests are testing the implementation, not the intent.</li>
</ul>
<h2 id="testing-intent-not-implementation">Testing intent, not implementation</h2>
<p>Instead of checking if we get the same class instances back from the container, it would make for more sense to check the classes <em>behave</em> as expected.  For my &ldquo;super stupid cache&rdquo; example this could take the following form:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> first = container.GetInstance&lt;ICache&gt;();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> second = container.GetInstance&lt;ICache&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>first.Value = <span style="color:#e6db74">&#34;testing&#34;</span>;
</span></span><span style="display:flex;"><span>second.Value.ShouldBe(<span style="color:#e6db74">&#34;testing&#34;</span>);
</span></span></code></pre></div><p>Not only does this test validate the behaviour of the classes, but it is far less brittle - we can change what the container returns entirely for <code>ICache</code>, as long as it behaves the same.</p>
<p>But what do you think? How do you go about testing behaviour?</p>
]]></content:encoded></item><item><title>Repositories Revisited (and why CQRS is better)</title><link>https://andydote.co.uk/2017/09/09/repositories-revisited/</link><pubDate>Sat, 09 Sep 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/09/09/repositories-revisited/</guid><description>TLDR: I still don&amp;rsquo;t like Repositories!
Recently I had a discussion with a commenter on my The problems with, and solutions to Repositories post, and felt it was worth expanding on how I don&amp;rsquo;t use repositories.
My applications tend to use the mediator pattern to keep things decoupled (using the Mediatr library), and this means that I end up with &amp;ldquo;handler&amp;rdquo; classes which process messages; they load something from storage, call domain methods, and then write it back to storage, possibly returning some or all the data.</description><content:encoded><![CDATA[<p><strong>TLDR:</strong> I still don&rsquo;t like Repositories!</p>
<p>Recently I had a discussion with a commenter on my <a href="2015/03/28/problems-with-and-solutions-to-repositories/">The problems with, and solutions to Repositories</a> post, and felt it was worth expanding on how I don&rsquo;t use repositories.</p>
<p>My applications tend to use the mediator pattern to keep things decoupled (using the <a href="https://github.com/jbogard/MediatR">Mediatr</a> library), and this means that I end up with &ldquo;handler&rdquo; classes which process messages; they load something from storage, call domain methods, and then write it back to storage, possibly returning some or all the data.</p>
<p>For example you could implement a handler to update the tags on a toggle class like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UpdateToggleTagsHandler</span> : IAsyncRequestHandler&lt;UpdateToggleTagsRequest, UpdateToggleTagsResponse&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> GetToggleQuery _getToggle;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> SaveToggleCommand _saveToggle;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> UpdateToggleTagsHandler(GetToggleQuery getToggle, SaveToggleCommand saveToggle)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        _getToggle = getToggle;
</span></span><span style="display:flex;"><span>        _saveToggle = saveToggle;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task&lt;UpdateToggleTagsResponse&gt; Handle(UpdateToggleTagsRequest message)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> toggle = <span style="color:#66d9ef">await</span> _getToggle.Execute(message.ToggleID);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        toggle.AddTag(message.Tag);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> _saveToggle(toggle);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> UpdateToggleTagsResponse
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            Tags = toggle.Tags.ToArray()
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note how we use constructor injection to get a single command and a single query, and that  the business logic is contained within the <code>Toggle</code> class itself, not the <code>Handler</code>.</p>
<p>By depending on commands and queries rather than using a repository, we can see at a glance what the <code>UpdateToggleTagsHandler</code> requires in the way of data, rather than having to pick through the code and figure out which of 20 methods on a repository is actually being called.</p>
<p>The actual domain classes (in this case, the <code>Toggle</code> class) know nothing of storage concerns.  As I use EventSourcing a lot, the domain classes just need a few methods to facilitate storage: applying events, fetching pending events, and clearing pending events.  For non EventSourced classes, I tend to use the Memento pattern: each class implements two methods, one to load from a plain object, one to write to the same plain object.</p>
<p>If your handler starts needing many commands or many queries passed in, it&rsquo;s a pretty good indication that your design has a weakness which will probably need refactoring.  This is harder to notice when using repositories as you might still only have a single constructor parameter, but be calling tens of methods on it.</p>
<p>Hopefully this provides a bit more reasoning behind my dislike of repositories, and how I try to implement alternatives.</p>
]]></content:encoded></item><item><title>Serilog LogContext with StructureMap and SimpleInjector</title><link>https://andydote.co.uk/2017/07/28/serilog-context-with-structuremap-and-simpleinjector/</link><pubDate>Fri, 28 Jul 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/07/28/serilog-context-with-structuremap-and-simpleinjector/</guid><description>This article has been updated after feedback from .Net Junkie (Godfather of SimpleInjector). I now have a working SimpleInjector implementation of this, and am very appreciative of him for taking the time to help me :)
Serilog is one of the main set of libraries I use on a regular basis, and while it is great at logging, it does cause something in our codebase that I am less happy about.</description><content:encoded><![CDATA[<p><em>This article has been updated after feedback from <a href="https://twitter.com/dot_NET_Junkie">.Net Junkie</a> (Godfather of SimpleInjector).  I now have a working SimpleInjector implementation of this, and am very appreciative of him for taking the time to help me :)</em></p>
<p>Serilog is one of the main set of libraries I use on a regular basis, and while it is great at logging, it does cause something in our codebase that I am less happy about.  Take the following snippet for example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Something</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">readonly</span> ILogger Log = Log.ForContext(<span style="color:#66d9ef">typeof</span>(Something));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>There are two things I don&rsquo;t like about this.  The first is the static field access:  We have tests which assert on log content for disallowed information, or to include a correlationid etc.  Having a static field means that if tests run in parallel, we end up with flaky tests due to multiple log messages being written.  The second thing I don&rsquo;t like is less about the line itself, but the repetition of this line throughout the codebase.  Nearly every class which does logging has the same line, but with the type parameter changed.</p>
<p>I set out to see if I could remedy both problems at once.</p>
<h2 id="fixing-the-static-field">Fixing the Static Field</h2>
<p>The first fix is to inject the logger in via a constructor argument, which will allow tests to use their own version of the logger:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Something</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> ILogger _log;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Something(ILogger logger)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        _log = logger.ForContext(<span style="color:#66d9ef">typeof</span>(Something));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>That was easy! Now on to the hard part; removing the repeated <code>.ForContext</code> call.</p>
<h2 id="fixing-the-forcontext-repetition">Fixing the ForContext Repetition</h2>
<p>Most (if not all) the applications I build use a dependency injection container to build objects.  In my opinion there are only two containers which are worth considering in the .net space:  <a href="http://structuremap.github.io/">StructureMap</a>, and <a href="https://simpleinjector.org">SimpleInjector</a>.  If you like convention based registration, use StructureMap.  If you like to get a safety net that prevents and detects common misconfigurations, use SimpleInjector.</p>
<h3 id="tests">Tests</h3>
<p>We can use the same tests to verify the behaviour both when using StructureMap and SimpleInjector&rsquo;s.  We have a couple of test classes, and an interface to allow for more generic testing:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">ILogOwner</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    ILogger Logger { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Something</span> : ILogOwner
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> ILogger Logger { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Something(ILogger logger)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        Logger = logger;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Everything</span> : ILogOwner
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> ILogger Logger { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Everything(ILogger logger)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        Logger = logger;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And then a single parameterised test method for verification:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Tests</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Container _container;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Tests()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        Log.Logger = <span style="color:#66d9ef">new</span> LoggerConfiguration()
</span></span><span style="display:flex;"><span>            .MinimumLevel.Debug()
</span></span><span style="display:flex;"><span>            .WriteTo.Console()
</span></span><span style="display:flex;"><span>            .CreateLogger();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// _container = new ...</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">    [Theory]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">    [InlineData(typeof(Something))]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">    [InlineData(typeof(Everything))]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Types_get_their_own_context(Type type)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> instance = (ILogOwner)_container.GetInstance(type);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> context = GetContextFromLogger(instance);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        context.ShouldBe(type.FullName);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">string</span> GetContextFromLogger(ILogOwner owner)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> logEvent = CreateLogEvent();
</span></span><span style="display:flex;"><span>        owner.Logger.Write(logEvent);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> logEvent.Properties[<span style="color:#e6db74">&#34;SourceContext&#34;</span>].ToString().Trim(<span style="color:#e6db74">&#39;&#34;&#39;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> LogEvent CreateLogEvent() =&gt; <span style="color:#66d9ef">new</span> LogEvent(
</span></span><span style="display:flex;"><span>        DateTimeOffset.Now,
</span></span><span style="display:flex;"><span>        LogEventLevel.Debug,
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">null</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">new</span> MessageTemplate(<span style="color:#e6db74">&#34;&#34;</span>, Enumerable.Empty&lt;MessageTemplateToken&gt;()),
</span></span><span style="display:flex;"><span>        Enumerable.Empty&lt;LogEventProperty&gt;());
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="structuremap">StructureMap</h3>
<p>The StructureMap initialisation just requires a single line change to use the construction context when creating a logger:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>_container = <span style="color:#66d9ef">new</span> Container(_ =&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    _.Scan(a =&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        a.TheCallingAssembly();
</span></span><span style="display:flex;"><span>        a.WithDefaultConventions();
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// original:</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// _.For&lt;ILogger&gt;().Use(context =&gt; Log.Logger);</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// contextual</span>
</span></span><span style="display:flex;"><span>    _.For&lt;ILogger&gt;().Use(context =&gt; Log.ForContext(context.ParentType));
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><h3 id="simpleinjector">SimpleInjector</h3>
<p>SimpleInjector does a lot of verification of your container configuration, and as such deals mostly with Types, rather than instances, or types which have multiple mappings as we are doing.  This makes it slightly harder to support the behaviour we had with StructureMap, but not impossible.  A huge thanks to .Net Junkie for assisting with this!</p>
<p>First we need to create an implementation of  <code>IDependencyInjectionBehavior</code>, which will handle our <code>ILogger</code> type requests, and pass all other types requests to the standard implementation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">SerilogContextualLoggerInjectionBehavior</span> : IDependencyInjectionBehavior
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IDependencyInjectionBehavior _original;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Container _container;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> SerilogContextualLoggerInjectionBehavior(ContainerOptions options)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        _original = options.DependencyInjectionBehavior;
</span></span><span style="display:flex;"><span>        _container = options.Container;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Verify(InjectionConsumerInfo consumer) =&gt; _original.Verify(consumer);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> InstanceProducer GetInstanceProducer(InjectionConsumerInfo i, <span style="color:#66d9ef">bool</span> t) =&gt;
</span></span><span style="display:flex;"><span>        i.Target.TargetType == <span style="color:#66d9ef">typeof</span>(ILogger)
</span></span><span style="display:flex;"><span>            ? GetLoggerInstanceProducer(i.ImplementationType)
</span></span><span style="display:flex;"><span>            : _original.GetInstanceProducer(i, t);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> InstanceProducer&lt;ILogger&gt; GetLoggerInstanceProducer(Type type) =&gt;
</span></span><span style="display:flex;"><span>        Lifestyle.Transient.CreateProducer(() =&gt; Log.ForContext(type), _container);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This can then be set in our container setup:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>_ontainer = <span style="color:#66d9ef">new</span> Container();
</span></span><span style="display:flex;"><span>_container.Options.DependencyInjectionBehavior = <span style="color:#66d9ef">new</span> SerilogContextualLoggerInjectionBehavior(_container.Options);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>_container.Register&lt;Something&gt;();
</span></span><span style="display:flex;"><span>_container.Register&lt;Everything&gt;();
</span></span></code></pre></div><p>And now our tests pass!</p>
<h2 id="outcomes">Outcomes</h2>
<p>Thanks to this container usage, I no longer have to have the <code>.ForContext(typeof(Something))</code> scattered throughout my codebases.</p>
<p>Hopefully this shows how taking away just some of the little tasks makes life easier - I now no longer have to remember to do the <code>.ForContext</code> on each class, and don&rsquo;t need to have tests to validate it is done on each class (I have one test in my container configuration tests which validates this behaviour instead).</p>
]]></content:encoded></item><item><title>Getting Things Done</title><link>https://andydote.co.uk/2017/07/15/getting-things-done/</link><pubDate>Sat, 15 Jul 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/07/15/getting-things-done/</guid><description>I have been trying to actually be productive in my evenings and weekends, but I find I often end up not getting as much done as I feel I could have. I end up browsing imgur, reading slashdot, reddit, twitter, etc. rather than reading books, writing or anything else.
The first point doesn&amp;rsquo;t fit in anywhere else, but somewhere I saw a tip about keeping a house clean (I think):</description><content:encoded><![CDATA[<p>I have been trying to actually be productive in my evenings and weekends, but I find I often end up not getting as much done as I feel I could have.  I end up browsing imgur, reading slashdot, reddit, twitter, etc. rather than reading books, writing or anything else.</p>
<p>The first point doesn&rsquo;t fit in anywhere else, but somewhere I saw a tip about keeping a house clean (I think):</p>
<blockquote>
<p>If it takes less than 2 minutes to do, do it immediately</p>
</blockquote>
<p>This has helped me a lot in keeping my work areas tidier (e.g. take empty tea cups back to the sink&hellip;), but I also find I am applying this to things while working too.  Notice a spelling mistake in a <code>readme.md</code>? Fix and pull request. Notice packages are out of date on a project? update them and pull request.  Notice a method could be refactored to be clearer? Refactor and&hellip;you get the picture.  Lots of little improvements add up.  Katrina Owen does a great talk about <a href="https://www.youtube.com/watch?v=J4dlF0kcThQ">Therapeutic Refactoring</a>, and a lot of what she says applies to the fixing of small issues.</p>
<p>So here are some of the things which I have found help me to get things done.</p>
<h2 id="a-good-environment">A Good Environment</h2>
<p>Being comfortable is super important.  A slightly uncomfortable chair will niggle away at the back of your mind, and cause you to fidget.  Try a standing desk if you find yourself getting restless sitting down all day.</p>
<p>If you can control the temperature of the room you are in (without causing office drama/war over it), do so!  Nothing like the constant discomfort of being too hot to distract you.  Oh, and if you want the room hotter, but someone else want&rsquo;s it colder, let them have the coolness.  You can put on more layers to stay warm, but they&rsquo;re probably not allowed to take any more off by this point!</p>
<p>Lighting is another important part, and not just in making sure you are not straining your eyes, or coping with screen glare.  One of my previous work locations had inset lights in the ceiling, but no diffusers underneath them, so in the corner of my eye all day was a bright halogen-type light.  It was amazing how some days the light drove me crazy, and other days I barely noticed it.</p>
<h2 id="a-good-virtual-environment">A Good Virtual Environment</h2>
<p>How often are you part way through a task, and you switch to reddit/twitter/slashdot/whatever to have a quick look?  I never want to shut all my standard browsing tabs, but when I am working, I don&rsquo;t want to be distracted by them either.</p>
<p>Luckily, Windows 10 finally added Virtual Desktop support in, which I use to create separate areas for different tasks.  For example, the laptop I am typing on at the moment has 3 Virtual Desktops:</p>
<ol>
<li>General/day to day: chrome, spotify, etc</li>
<li>Blog writing: atom, git bash, chrome (with only a tab of my local blog instance open)</li>
<li>Current development project, so a couple of git bash windows, atom, rider, chrome with AWS tabs open</li>
</ol>
<p>By doing this, when I get briefly distracted and tab to chrome&hellip;there is only task related tabs open, and I just keep on at the current task.</p>
<h2 id="music">Music</h2>
<p>Something to listen to, which wont distract.  Game and film sound tracks are amazing for this, as they are designed to be immersive, but also not to distract you from what is going on.  Generally there are no words to them, so you don&rsquo;t end up singing along either.  Personally, I like using:</p>
<ul>
<li>Mirror&rsquo;s Edge (game) <a href="https://www.youtube.com/watch?v=Y05wiQQbFLU">YouTube</a>, <a href="https://open.spotify.com/album/3x8kUWCtDfOEnOtyaRdkdp">Spotify</a></li>
<li>Inception (film) <a href="https://www.youtube.com/watch?v=zp6pwnfmO48">YouTube</a>, <a href="https://open.spotify.com/album/2qvA7HmSg1iM6XMiFF76dp">Spotify</a></li>
<li>Oblivion (film) -<a href="https://www.youtube.com/watch?v=sYD_U1CChew">YouTube</a>, <a href="https://open.spotify.com/album/6V8ConRfFeocQqrgmGd2MY">Spotify</a> - I actually listened to this a lot before seeing the film&hellip;</li>
</ul>
<h2 id="focus">Focus</h2>
<p>I find timeboxing tasks helps me a great deal.  The method I like is called <a href="https://en.wikipedia.org/wiki/Pomodoro_Technique">Pomodoro</a>, and just involves doing 3x 25min tasks with 5min breaks after, and the 4th task gets a longer break after.  I tend to use 20 minute timers for this, and allow myself to keep working a little if I wish to finish a paragraph or similar.</p>
<p>Setting tasks up for success helps a great deal too.  For example, I find getting started on writing something very difficult.  For example, this blog post has been rattling around in my head for at least a week.  To help write it, I start off by writing a list of bullet point ideas, which goes into my drafts folder.  When I sit down to write a blog post, I can hopefully start off by expanding a bullet point or two, and by the time that is done, I am in the writing zone.</p>
<h2 id="and-on">And on</h2>
<p>Hopefully all these little techniques will become habit soon, and I will find more along the way I am sure.</p>
]]></content:encoded></item><item><title>Terraform, Kinesis Streams, Lambda and IAM problems</title><link>https://andydote.co.uk/2017/07/12/terraform-kinesis-lambda-iam/</link><pubDate>Wed, 12 Jul 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/07/12/terraform-kinesis-lambda-iam/</guid><description>I hit an problem the recently with Terraform, when I was trying to hook up a Lambda Trigger to a Kinesis stream. Both the lambda itself, and the stream creation succeeded within Terraform, but the trigger would just stay stuck on &amp;ldquo;creating&amp;hellip;&amp;rdquo; for at least 5 minutes, before I got bored of waiting and killed the process. Several attempts at doing this had the same issue.
The code looked something along the lines of this:</description><content:encoded><![CDATA[<p>I hit an problem the recently with Terraform, when I was trying to hook up a Lambda Trigger to a Kinesis stream.  Both the lambda itself, and the stream creation succeeded within Terraform, but the trigger would just stay stuck on &ldquo;creating&hellip;&rdquo; for at least 5 minutes, before I got bored of waiting and killed the process.  Several attempts at doing this had the same issue.</p>
<p>The code looked something along the lines of this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>data <span style="color:#e6db74">&#34;archive_file&#34;</span> <span style="color:#e6db74">&#34;consumer_lambda&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;zip&#34;</span>
</span></span><span style="display:flex;"><span>  source_dir <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;./js/consumer&#34;</span>
</span></span><span style="display:flex;"><span>  output_path <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;./build/consumer.zip&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>resource <span style="color:#e6db74">&#34;aws_lambda_function&#34;</span> <span style="color:#e6db74">&#34;kinesis_consumer&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  filename <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>data.archive_file.consumer_lambda.output_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  function_name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;kinesis_consumer&#34;</span>
</span></span><span style="display:flex;"><span>  role <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>aws_iam_role.consumer_role.arn<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  handler <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;index.handler&#34;</span>
</span></span><span style="display:flex;"><span>  runtime <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;nodejs6.10&#34;</span>
</span></span><span style="display:flex;"><span>  source_code_hash <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>base64sha256(file(<span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>data.archive_file.consumer_lambda.output_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>))<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  timeout <span style="color:#f92672">=</span> <span style="color:#ae81ff">300</span> <span style="color:#75715e"># 5 mins</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>resource <span style="color:#e6db74">&#34;aws_kinesis_stream&#34;</span> <span style="color:#e6db74">&#34;replay_stream&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;replay_stream&#34;</span>
</span></span><span style="display:flex;"><span>  shard_count <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>resource <span style="color:#e6db74">&#34;aws_lambda_event_source_mapping&#34;</span> <span style="color:#e6db74">&#34;kinesis_replay_lambda&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  event_source_arn <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>aws_kinesis_stream.replay_stream.arn<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  function_name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>aws_lambda_function.kinesis_consumer.arn<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  starting_position <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;TRIM_HORIZON&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>resource <span style="color:#e6db74">&#34;aws_iam_role&#34;</span> <span style="color:#e6db74">&#34;consumer_role&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;consumer_role&#34;</span>
</span></span><span style="display:flex;"><span>  assume_role_policy <span style="color:#f92672">=</span> <span style="color:#e6db74">&lt;&lt;EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">{
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  &#34;Version&#34;: &#34;2012-10-17&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  &#34;Statement&#34;: [
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#34;Action&#34;: &#34;sts:AssumeRole&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#34;Principal&#34;: {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;Service&#34;: [&#34;lambda.amazonaws.com&#34;]
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      },
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#34;Effect&#34;: &#34;Allow&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    }
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  ]
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>resource <span style="color:#e6db74">&#34;aws_iam_role_policy&#34;</span> <span style="color:#e6db74">&#34;consumer_role_policy&#34;</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;consumer_role_policy&#34;</span>
</span></span><span style="display:flex;"><span>  role <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>aws_iam_role.consumer_role.id<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  policy <span style="color:#f92672">=</span> <span style="color:#e6db74">&lt;&lt;EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">{
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  &#34;Version&#34;: &#34;2012-10-17&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  &#34;Statement&#34;: [
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#34;Sid&#34;: &#34;Stmt1493060054000&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#34;Effect&#34;: &#34;Allow&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#34;Action&#34;: [&#34;lambda:InvokeAsync&#34;, &#34;lambda:InvokeFunction&#34;],
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#34;Resource&#34;: [&#34;arn:aws:lambda:*:*:*&#34;]
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    },
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#34;Effect&#34;: &#34;Allow&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#34;Action&#34;: [&#34;s3:GetObject*&#34;, &#34;s3:PutObject*&#34;],
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#34;Resource&#34;: [&#34;arn:aws:s3:::*&#34;]
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    }
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>I decided to try creating the trigger manually in AWS, which gave me the following error:</p>
<blockquote>
<p>There was an error creating the trigger: Cannot access stream arn:aws:kinesis:eu-west-1:586732038447:stream/test. Please ensure the role can perform the <strong>GetRecords</strong>, <strong>GetShardIterator</strong>, <strong>DescribeStream</strong>, and <strong>ListStreams</strong> Actions on your stream in IAM.</p>
</blockquote>
<p>All I had to do to fix this was to change my <code>consumer_role_policy</code> to include the relevant permissions:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;Effect&#34;</span>: <span style="color:#e6db74">&#34;Allow&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;Action&#34;</span>: [
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;kinesis:DescribeStream&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;kinesis:GetShardIterator&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;kinesis:GetRecords&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;kinesis:ListStreams&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;kinesis:PutRecords&#34;</span>
</span></span><span style="display:flex;"><span>    ],
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;Resource&#34;</span>: <span style="color:#e6db74">&#34;arn:aws:kinesis:*:*:*&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="takeaways">Takeaways</h2>
<ul>
<li><strong>Terraform could do with better errors</strong> - preferably in nice red text telling me I am doing things wrong!</li>
<li><strong>AWS told me exactly what was needed</strong> - Good error messages in AWS, so no need to spend hours googling which permissions would be needed.</li>
</ul>
]]></content:encoded></item><item><title>S3 Multi-File upload with Terraform</title><link>https://andydote.co.uk/2017/04/23/s3-multi-file-upload-terraform/</link><pubDate>Sun, 23 Apr 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/04/23/s3-multi-file-upload-terraform/</guid><description>Hosting a static website with S3 is really easy, especially from terraform:
First off, we want a public readable S3 bucket policy, but we want to apply this only to one specific bucket. To achive that we can use Terraform&amp;rsquo;s template_file data block to merge in a value:
{ &amp;#34;Version&amp;#34;: &amp;#34;2012-10-17&amp;#34;, &amp;#34;Statement&amp;#34;: [ { &amp;#34;Sid&amp;#34;: &amp;#34;PublicReadGetObject&amp;#34;, &amp;#34;Effect&amp;#34;: &amp;#34;Allow&amp;#34;, &amp;#34;Principal&amp;#34;: &amp;#34;*&amp;#34;, &amp;#34;Action&amp;#34;: [ &amp;#34;s3:GetObject&amp;#34; ], &amp;#34;Resource&amp;#34;: [ &amp;#34;arn:aws:s3:::${bucket_name}/*&amp;#34; ] } ] } As you can see the interpolation syntax is pretty much the same as how you use variables in terraform itself.</description><content:encoded><![CDATA[<p>Hosting a static website with S3 is really easy, especially from terraform:</p>
<p>First off, we want a public readable S3 bucket policy, but we want to apply this only to one specific bucket.  To achive that we can use Terraform&rsquo;s <code>template_file</code> data block to merge in a value:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Version&#34;</span>: <span style="color:#e6db74">&#34;2012-10-17&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Statement&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Sid&#34;</span>: <span style="color:#e6db74">&#34;PublicReadGetObject&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Effect&#34;</span>: <span style="color:#e6db74">&#34;Allow&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Principal&#34;</span>: <span style="color:#e6db74">&#34;*&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Action&#34;</span>: [
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;s3:GetObject&#34;</span>
</span></span><span style="display:flex;"><span>      ],
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Resource&#34;</span>: [
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;arn:aws:s3:::${bucket_name}/*&#34;</span>
</span></span><span style="display:flex;"><span>      ]
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As you can see the interpolation syntax is pretty much the same as how you use variables in terraform itself.  Next we define a <code>template_file</code> to do the transformation.  As the bucket name is going to be used many times, we extract that into a <code>variable</code> block also:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cmake" data-lang="cmake"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">variable</span> <span style="color:#960050;background-color:#1e0010">&#34;bucket&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">default</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;examplebucket&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">data</span> <span style="color:#960050;background-color:#1e0010">&#34;template_file&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;s3_public_policy&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">template</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${</span>file(<span style="color:#e6db74">&#34;policies/s3-public.json&#34;</span>)<span style="color:#960050;background-color:#1e0010">}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">vars</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>    <span style="color:#960050;background-color:#1e0010">bucket_name</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${var.bucket}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">}
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span></code></pre></div><p>Next we want to create the S3 bucket and set it to be a static website, which we can do using the <code>website</code> sub block.  For added usefulness, we will also define an <code>output</code> to show the website url on the command line:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cmake" data-lang="cmake"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">resource</span> <span style="color:#960050;background-color:#1e0010">&#34;aws_s3_bucket&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;static_site&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">bucket</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${var.bucket}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">acl</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;public-read&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">policy</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${data.template_file.s3_public_policy.rendered}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">website</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>    <span style="color:#960050;background-color:#1e0010">index_document</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;index.html&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">}
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">output</span> <span style="color:#960050;background-color:#1e0010">&#34;url&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">value</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${aws_s3_bucket.static_site.bucket}.s3-website-${var.region}.amazonaws.com&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span></code></pre></div><h2 id="single-file-upload">Single File Upload</h2>
<p>If you just want one file in the website (say the <code>index.html</code> file), then you can add the following block.  Just make sure the <code>key</code> property matches the <code>index_document</code> name in the <code>aws_s3_bucket</code> block.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cmake" data-lang="cmake"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">resource</span> <span style="color:#960050;background-color:#1e0010">&#34;aws_s3_bucket_object&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;index&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">bucket</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${aws_s3_bucket.static_site.bucket}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">key</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;index.html&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">source</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;src/index.html&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">content_type</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;text/html&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">etag</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${</span>md5(<span style="color:#e6db74">file(</span><span style="color:#e6db74">&#34;src/index.html&#34;</span>)<span style="color:#960050;background-color:#1e0010">)}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span></code></pre></div><h2 id="multi-file-upload">Multi File Upload</h2>
<p>Most websites need more than one file to be useful, and while we could write out an <code>aws_s3_bucket_object</code> block for every file, that seems like a lot of effort.  Other options include manually uploading the files to S3, or using the aws cli to do it.  While both methods work, they&rsquo;re error prone - you need to specify the <code>content_type</code> for each file for them to load properly, and you can&rsquo;t change this property once a file is uploaded.</p>
<p>To get around this, I add one more variable to my main terraform file, and generate a second file with all the <code>aws_s3_bucket_object</code> blocks in I need.</p>
<p>The added <code>variable</code> is a lookup for mime types:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cmake" data-lang="cmake"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">variable</span> <span style="color:#960050;background-color:#1e0010">&#34;mime_types&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">default</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>    <span style="color:#960050;background-color:#1e0010">htm</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;text/html&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>    <span style="color:#960050;background-color:#1e0010">html</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;text/html&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>    <span style="color:#960050;background-color:#1e0010">css</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;text/css&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>    <span style="color:#960050;background-color:#1e0010">js</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;application/javascript&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>    <span style="color:#960050;background-color:#1e0010">map</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;application/javascript&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>    <span style="color:#960050;background-color:#1e0010">json</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;application/json&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">}
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span></code></pre></div><p>I then create a shell script which will write a new file containing a <code>aws_s3_bucket_object</code> block for each file in the <code>src</code> directory:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#! /bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>SRC<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;src/&#34;</span>
</span></span><span style="display:flex;"><span>TF_FILE<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;files.tf&#34;</span>
</span></span><span style="display:flex;"><span>COUNT<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>cat &gt; $TF_FILE <span style="color:#e6db74">&#39;&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>find $SRC -iname <span style="color:#e6db74">&#39;*.*&#39;</span> | <span style="color:#66d9ef">while</span> read path; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    cat &gt;&gt; $TF_FILE <span style="color:#e6db74">&lt;&lt; EOM
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">resource &#34;aws_s3_bucket_object&#34; &#34;file_$COUNT&#34; {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  bucket = &#34;\${aws_s3_bucket.static_site.bucket}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  key = &#34;${path#$SRC}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  source = &#34;$path&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  content_type = &#34;\${lookup(var.mime_types, &#34;${path##*.}&#34;)}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  etag = &#34;\${md5(file(&#34;$path&#34;))}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOM</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    COUNT<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>expr $COUNT + 1<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span></code></pre></div><p>Now when I want to publish a static site, I just have to make sure I run <code>./files.sh</code> once before my <code>terraform plan</code> and <code>terraform apply</code> calls.</p>
<h2 id="caveats">Caveats</h2>
<p>This technique has one major drawback: it doesn&rsquo;t work well with updating an existing S3 bucket.  It won&rsquo;t remove files which are no longer in the terraform files, and can&rsquo;t detect file moves.</p>
<p>However, if you&rsquo;re happy with a call to <code>terraform destroy</code> before applying, this will work fine.  I use it for a number of test sites which I don&rsquo;t tend to leave online very long, and for scripted aws infrastructure that I give out to other people so they can run their own copy.</p>
]]></content:encoded></item><item><title>Don't write Frameworks, write Libraries</title><link>https://andydote.co.uk/2017/04/16/dont-write-frameworks-write-libraries/</link><pubDate>Sun, 16 Apr 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/04/16/dont-write-frameworks-write-libraries/</guid><description>Programmers have a fascination with writing frameworks for some reason. There are many problems with writing frameworks:
Opinions Frameworks are opinionated, and will follow their author&amp;rsquo;s opinions on how things should be done, such as application structure, configuration, and methodology. The problem this gives is that not everyone will agree with the author, or their framework&amp;rsquo;s opinions. Even if they really like part of how the framework works, they might not like another part, or might not be able to rewrite their application to take advantage of the framework.</description><content:encoded><![CDATA[<p>Programmers have a fascination with writing frameworks for some reason.  There are many problems with writing frameworks:</p>
<h3 id="opinions">Opinions</h3>
<p>Frameworks are opinionated, and will follow their author&rsquo;s opinions on how things should be done, such as application structure, configuration, and methodology.  The problem this gives is that not everyone will agree with the author, or their framework&rsquo;s opinions.  Even if they really like part of how the framework works, they might not like another part, or might not be able to rewrite their application to take advantage of the framework.</p>
<h3 id="configurability">Configurability</h3>
<p>The level of configuration available in a framework is almost never correct.  Not only is there either too little or too much configuration options, but how the configuration is done can cause issues.  Some developers love conventions, other prefer explicit configuration.</p>
<h3 id="development">Development</h3>
<p>Frameworks suffer from the danger of not solving the right problem, or missing the problem due to how long it took to implement the framework.  This is compounded by <em>when</em> a framework is decided to be developed, which is often way before the general case is even recognised.  Writing a framework before writing your project is almost certain to end up with a framework which either isn&rsquo;t suitable for the project, or isn&rsquo;t suitable for any other projects.</p>
<h2 id="what-about-a-library-or-two">What about a library or two?</h2>
<p>If you want a higher chance at success, reduce your scope and write a library.</p>
<p>A library is usually a small unit of functionality, and does one thing and does it well (sound like microservices or Bounded Contexts much?).  This gives it a higher chance of success, as the opinions of the library are going to effect smaller portions of peoples applications.  It won&rsquo;t dictate their entire app structure.  They can opt in to using the libraries they like, rather than all the baggage which comes with a framework.</p>
<h2 id="but-i-really-want-to-write-a-framework">But I really want to write a framework</h2>
<p>Resist, if you can!  Perhaps a framework will evolve from your software, perhaps not.  What I have found to be a better path is to create libraries which work on their own, but also work well with each other.  This can make this more difficult, but it also give you the ability to release libraries as they are completed, rather than waiting for an entire framework to be &ldquo;done&rdquo;.</p>
<h2 id="some-examples">Some examples</h2>
<p>These are some libraries I have written which solve small problems in an isolated manner</p>
<ul>
<li><a href="https://github.com/pondidum/stronk">Stronk</a> - A library to populate strong typed configuration objects.</li>
<li><a href="https://github.com/pondidum/FileSystem">FileSystem</a> - Provides a FileSystem abstraction,  with decorators and an InMemory FileSystem implementation.</li>
<li><a href="https://github.com/pondidum/Finite">Finite</a> - a Finite State Machine library.</li>
<li><a href="https://github.com/pondidum/conifer">Conifer</a> - Strong typed, Convention based routing for WebAPI, also with route lookup abilities</li>
</ul>
<p>So why not write some libraries?</p>
]]></content:encoded></item><item><title>Using Terraform to setup AWS API-Gateway and Lambda</title><link>https://andydote.co.uk/2017/03/17/terraform-aws-lambda-api-gateway/</link><pubDate>Fri, 17 Mar 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/03/17/terraform-aws-lambda-api-gateway/</guid><description>I have been writing simple webhook type applications using Claudiajs, which in behind the scenes is using Aws&amp;rsquo;s Lambda and Api Gateway to make things happen, but I really wanted to understand what exactly it was doing for me, and how I could achieve the same results using Terraform.
The Lambda Function I started off with a simple NodeJS function, in a file called index.js
exports.handler = function(event, context, callback) { callback(null, { statusCode: &amp;#39;200&amp;#39;, body: JSON.</description><content:encoded><![CDATA[<p>I have been writing simple webhook type applications using <a href="https://claudiajs.com/">Claudiajs</a>, which in behind the scenes is using Aws&rsquo;s Lambda and Api Gateway to make things happen, but I really wanted to understand what exactly it was doing for me, and how I could achieve the same results using <a href="https://terraform.io">Terraform</a>.</p>
<h3 id="the-lambda-function">The Lambda Function</h3>
<p>I started off with a simple NodeJS function, in a file called <code>index.js</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">exports</span>.<span style="color:#a6e22e">handler</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">event</span>, <span style="color:#a6e22e">context</span>, <span style="color:#a6e22e">callback</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">callback</span>(<span style="color:#66d9ef">null</span>, {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">statusCode</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;200&#39;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">body</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>({ <span style="color:#e6db74">&#39;message&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;hello world&#39;</span> }),
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">&#39;Content-Type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;application/json&#39;</span>,
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>First thing to note about this function is the 2nd argument passed to <code>callback</code>: <strong>this maps to the whole response object not just the body</strong>.  If you try and just run <code>callback(null, { message: 'hello world' })</code>, when called from the API Gateway, you will get the following error in your CloudWatch logs, and not a lot of help on Google:</p>
<blockquote>
<p>Execution failed due to configuration error: &ldquo;Malformed Lambda proxy response&rdquo;</p>
</blockquote>
<h2 id="terraform">Terraform</h2>
<p>We want to upload a zip file containing all our lambda&rsquo;s code, which in this case is just the <code>index.js</code> file.  While this could be done by generating the zip file with a gulp script or manually, we can just get terraform to do this for us, by using the <a href="https://www.terraform.io/docs/providers/archive/d/archive_file.html">archive_file data source</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cmake" data-lang="cmake"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">data</span> <span style="color:#960050;background-color:#1e0010">&#34;archive_file&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;lambda&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">type</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;zip&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">source_file</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;index.js&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">output_path</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;lambda.zip&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">resource</span> <span style="color:#960050;background-color:#1e0010">&#34;aws_lambda_function&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;example_test_function&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">filename</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${data.archive_file.lambda.output_path}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">function_name</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;example_test_function&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">role</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${aws_iam_role.example_api_role.arn}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">handler</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;index.handler&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">runtime</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;nodejs4.3&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">source_code_hash</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${</span>base64sha256(<span style="color:#e6db74">file(</span><span style="color:#e6db74">&#34;${data.archive_file.lambda.output_path}&#34;</span>)<span style="color:#960050;background-color:#1e0010">)}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">publish</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">true
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span></code></pre></div><p>By using the <code>source_code_hash</code> property, Terraform can detect when the zip file has changed, and thus know whether to re-upload the function when you call <code>terraform apply</code>.</p>
<p>We also need an IAM role for the function to run under.  While the policy could be written inline, but I have found it more expressive to have a separate file for the role policy:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cmake" data-lang="cmake"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">resource</span> <span style="color:#960050;background-color:#1e0010">&#34;aws_iam_role&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;example_api_role&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">name</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;example_api_role&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">assume_role_policy</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${</span>file(<span style="color:#e6db74">&#34;policies/lambda-role.json&#34;</span>)<span style="color:#960050;background-color:#1e0010">}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Version&#34;</span>: <span style="color:#e6db74">&#34;2012-10-17&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Statement&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Action&#34;</span>: <span style="color:#e6db74">&#34;sts:AssumeRole&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Principal&#34;</span>: {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;Service&#34;</span>: [
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;lambda.amazonaws.com&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;apigateway.amazonaws.com&#34;</span>
</span></span><span style="display:flex;"><span>        ]
</span></span><span style="display:flex;"><span>      },
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Effect&#34;</span>: <span style="color:#e6db74">&#34;Allow&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Sid&#34;</span>: <span style="color:#e6db74">&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>That&rsquo;s the lambda done - you can login to the AWS Console, setup a test event and execute it if you want :)</p>
<h3 id="creating-the-api-gateway">Creating the Api Gateway</h3>
<p>We are going to create a simple api, with one endpoint (or resource, in AWS terminology).</p>
<p>First we need to define an api root:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cmake" data-lang="cmake"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">resource</span> <span style="color:#960050;background-color:#1e0010">&#34;aws_api_gateway_rest_api&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;example_api&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">name</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;ExampleAPI&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">description</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;Example</span> <span style="color:#960050;background-color:#1e0010">Rest</span> <span style="color:#960050;background-color:#1e0010">Api&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span></code></pre></div><p>And then a resource to represent the <code>/messages</code> endpoint, and a method to handle <code>POST</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cmake" data-lang="cmake"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">resource</span> <span style="color:#960050;background-color:#1e0010">&#34;aws_api_gateway_resource&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;example_api_resource&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">rest_api_id</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${aws_api_gateway_rest_api.example_api.id}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">parent_id</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${aws_api_gateway_rest_api.example_api.root_resource_id}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">path_part</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;messages&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">resource</span> <span style="color:#960050;background-color:#1e0010">&#34;aws_api_gateway_method&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;example_api_method&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">rest_api_id</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${aws_api_gateway_rest_api.example_api.id}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">resource_id</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${aws_api_gateway_resource.example_api_resource.id}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">http_method</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;POST&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">authorization</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;NONE&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span></code></pre></div><p>The <code>aws_api_gateway_resource</code> can be attached to other <code>aws_api_gateway_resource</code>s rather than to the api root too, allowing for multi level routes.  You can do this by changing the <code>parent_id</code> property to point to another <code>aws_api_gateway_resource.id</code>.</p>
<p>Now we need add an integration between the api and lambda:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cmake" data-lang="cmake"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">resource</span> <span style="color:#960050;background-color:#1e0010">&#34;aws_api_gateway_integration&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;example_api_method-integration&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">rest_api_id</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${aws_api_gateway_rest_api.example_api.id}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">resource_id</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${aws_api_gateway_resource.example_api_resource.id}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">http_method</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${aws_api_gateway_method.example_api_method.http_method}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">type</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;AWS_PROXY&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">uri</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;arn:aws:apigateway:${var.region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${var.region}:${var.account_id}:function:${aws_lambda_function.example_test_function.function_name}/invocations&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">integration_http_method</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;POST&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span></code></pre></div><p>Finally a couple of deployment stages, and an output variable for each to let you know the api&rsquo;s urls:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cmake" data-lang="cmake"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">resource</span> <span style="color:#960050;background-color:#1e0010">&#34;aws_api_gateway_deployment&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;example_deployment_dev&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">depends_on</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">[
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>    <span style="color:#960050;background-color:#1e0010">&#34;aws_api_gateway_method.example_api_method&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>    <span style="color:#960050;background-color:#1e0010">&#34;aws_api_gateway_integration.example_api_method-integration&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">]
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">rest_api_id</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${aws_api_gateway_rest_api.example_api.id}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">stage_name</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;dev&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">resource</span> <span style="color:#960050;background-color:#1e0010">&#34;aws_api_gateway_deployment&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;example_deployment_prod&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">depends_on</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">[
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>    <span style="color:#960050;background-color:#1e0010">&#34;aws_api_gateway_method.example_api_method&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>    <span style="color:#960050;background-color:#1e0010">&#34;aws_api_gateway_integration.example_api_method-integration&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">]
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">rest_api_id</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${aws_api_gateway_rest_api.example_api.id}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">stage_name</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;api&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">output</span> <span style="color:#960050;background-color:#1e0010">&#34;dev_url&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">value</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;https://${aws_api_gateway_deployment.example_deployment_dev.rest_api_id}.execute-api.${var.region}.amazonaws.com/${aws_api_gateway_deployment.example_deployment_dev.stage_name}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">output</span> <span style="color:#960050;background-color:#1e0010">&#34;prod_url&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">value</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;https://${aws_api_gateway_deployment.example_deployment_prod.rest_api_id}.execute-api.${var.region}.amazonaws.com/${aws_api_gateway_deployment.example_deployment_prod.stage_name}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span></code></pre></div><p>The two output variables will cause terraform to output the paths when you call <code>terraform apply</code>, or afterwards when you call <code>terraform output dev_url</code>.  Great for scripts which need to know the urls!</p>
<h3 id="run-it">Run it!</h3>
<p>You can now call your url and see a friendly hello world message:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -X POST -H <span style="color:#e6db74">&#34;Content-Type: application/json&#34;</span> <span style="color:#e6db74">&#34;YOUR_DEV_OR_PROD_URL&#34;</span>
</span></span></code></pre></div><h2 id="switching-to-c">Switching to C#</h2>
<p>Switching to a C#/dotnetcore lambda is very straight forward from here.  We just need to change the <code>aws_lambda_function</code>&rsquo;s runtime and handler properties, and change the <code>archive_file</code> to use <code>source_dir</code> rather than <code>source_file</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cmake" data-lang="cmake"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">data</span> <span style="color:#960050;background-color:#1e0010">&#34;archive_file&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;lambda&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">type</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;zip&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">source_dir</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;./src/published&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">output_path</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;lambda.zip&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">resource</span> <span style="color:#960050;background-color:#1e0010">&#34;aws_lambda_function&#34;</span> <span style="color:#960050;background-color:#1e0010">&#34;example_test_function&#34;</span> <span style="color:#960050;background-color:#1e0010">{
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">filename</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${data.archive_file.lambda.output_path}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">function_name</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;example_test_function&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">role</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${aws_iam_role.example_api_role.arn}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">handler</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;ExampleLambdaApi::ExampleLambdaApi.Handler::Handle&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">runtime</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;dotnetcore1.0&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">source_code_hash</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">&#34;${</span>base64sha256(<span style="color:#e6db74">file(</span><span style="color:#e6db74">&#34;${data.archive_file.lambda.output_path}&#34;</span>)<span style="color:#960050;background-color:#1e0010">)}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  <span style="color:#960050;background-color:#1e0010">publish</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">true
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}
</span></span></span></code></pre></div><p>Note the <code>handler</code> property is in the form <code>AssemblyName::FullyQualifiedTypeName::MethodName</code>.</p>
<p>For our C# project, we need the following two nugets:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>Amazon.Lambda.APIGatewayEvents
</span></span><span style="display:flex;"><span>Amazon.Lambda.Serialization.Json
</span></span></code></pre></div><p>And the only file in our project looks like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">namespace</span> ExampleLambdaApi
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Handler</span>
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">    [LambdaSerializer(typeof(JsonSerializer))]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> APIGatewayProxyResponse Handle(APIGatewayProxyRequest apigProxyEvent)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> APIGatewayProxyResponse
</span></span><span style="display:flex;"><span>      {
</span></span><span style="display:flex;"><span>        Body = apigProxyEvent.Body,
</span></span><span style="display:flex;"><span>        StatusCode = <span style="color:#ae81ff">200</span>,
</span></span><span style="display:flex;"><span>      };
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>One thing worth noting is that the first time a C# function is called it takes a long time - in the region of 5-6 seconds.  Subsequent invocations are in the 200ms region.</p>
<p>All the code for this demo can be found on my <a href="https://github.com/pondidum/">GitHub</a>, in the <a href="https://github.com/Pondidum/Terraform-Demos/tree/master/api-lambda">terraform-demos repository</a>.</p>
]]></content:encoded></item><item><title>Unit Tests &amp; Scratchpads</title><link>https://andydote.co.uk/2017/01/21/unit-tests-and-scratchpads/</link><pubDate>Sat, 21 Jan 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/01/21/unit-tests-and-scratchpads/</guid><description>Often when developing something, I have the need to check how a function or library works. For example, I always have to check for this question:
Does Directory.ListFiles(&amp;quot;.\\temp\\&amp;quot;) return a list of filenames, a list of relative filepaths, or a list of rooted filepaths?
It returns relative filepaths by the way:
Directory.ListFiles(&amp;#34;.\\temp\\&amp;#34;); [ &amp;#34;.\temp\NuCrunch.Tests.csproj&amp;#34;, &amp;#34;.\temp\packages.config&amp;#34;, &amp;#34;.\temp\Scratchpad.cs&amp;#34; ] Now that there is a C# Interactive window in Visual Studio, you can use that to test the output.</description><content:encoded><![CDATA[<p>Often when developing something, I have the need to check how a function or library works.  For example, I <em>always</em> have to check for this question:</p>
<blockquote>
<p>Does <code>Directory.ListFiles(&quot;.\\temp\\&quot;)</code> return a list of filenames, a list of relative filepaths, or a list of rooted filepaths?</p>
</blockquote>
<p>It returns relative filepaths by the way:</p>
<pre tabindex="0"><code>Directory.ListFiles(&#34;.\\temp\\&#34;);
[ &#34;.\temp\NuCrunch.Tests.csproj&#34;, &#34;.\temp\packages.config&#34;, &#34;.\temp\Scratchpad.cs&#34; ]
</code></pre><p>Now that there is a C# Interactive window in Visual Studio, you can use that to test the output.  Sometimes however the C# Interactive window is not suitable:</p>
<ul>
<li>You want to test needs a little more setup than a couple of lines</li>
<li>You wish to use the debugger to check on intermediate state</li>
<li>You are not in Visual Studio (I am 99% of the time in <a href="https://www.jetbrains.com/rider/">Rider</a>)</li>
</ul>
<p>When this happens, I turn to the unit test file which I add to all unit test projects:  the <code>Scratchpad.cs</code>.</p>
<p>The complete listing of the file is this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">using</span> Xunit;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">using</span> Xunit.Abstractions;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">namespace</span> NuCrunch.Tests
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Scratchpad</span>
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> ITestOutputHelper _output;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">public</span> Scratchpad(ITestOutputHelper output)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			_output = output;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">		[Fact]</span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> When_testing_something()
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>It gets committed to the git repository with no content in the <code>When_testing_something</code> method, and is never committed again afterwards.  The <code>_output</code> field is added to allow writing to console/test window easily too.</p>
<p>Now whenever I wish to experiment with something, I can pop open the <code>Scratchpad</code> write some test content, then execute and debug it to my hearts content.</p>
<p>After I am done with the test code, one of two things happen:  it gets deleted, or it gets moved into a proper unit test.</p>
]]></content:encoded></item><item><title>Update all Docker images</title><link>https://andydote.co.uk/2017/01/16/update-all-docker-images/</link><pubDate>Mon, 16 Jan 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/01/16/update-all-docker-images/</guid><description>My work&amp;rsquo;s wifi is much faster than my 4G connection, so periodically I want to update all my docker images on my personal laptop while at work.
As I want to just set it going and then forget about it, I use the following one liner to do a docker pull against each image on my local machine:
docker images | grep -v REPOSITORY | awk &amp;#39;{print $1}&amp;#39;| xargs -L1 docker pull If you only want to fetch the versions you have the tags for:</description><content:encoded><![CDATA[<p>My work&rsquo;s wifi is <em>much</em> faster than my 4G connection, so periodically I want to update all my docker images on my personal laptop while at work.</p>
<p>As I want to just set it going and then forget about it, I use the following one liner to do a <code>docker pull</code> against each image on my local machine:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker images | grep -v REPOSITORY | awk <span style="color:#e6db74">&#39;{print $1}&#39;</span>| xargs -L1 docker pull
</span></span></code></pre></div><p>If you only want to fetch the versions you have the tags for:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker images | grep -v REPOSITORY | awk <span style="color:#e6db74">&#39;{ if ($2 != &#34;&lt;none&gt;&#34;) { print $1&#34;:&#34;$2 } else { print $1 } }&#39;</span> | xargs -L1 docker pull
</span></span></code></pre></div><p>Now if only I could get git bash to do TTY properly so I get the pretty download indicators too :(</p>
]]></content:encoded></item><item><title>MediatR and Magic</title><link>https://andydote.co.uk/2017/01/07/mediatr-and-magic/</link><pubDate>Sat, 07 Jan 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/01/07/mediatr-and-magic/</guid><description>Having recently watched Greg Young&amp;rsquo;s excellent talk on 8 Lines of Code I was thinking about how this kind of thinking applies to the mediator pattern, and specifically the MediatR implementation.
I have written about the advantages of CQRS with MediatR before, but having used it for a long time now, there are some parts which cause friction on a regular basis.
The problems Discoverability The biggest issue first. You have a controller with the following constructor:</description><content:encoded><![CDATA[<p>Having recently watched Greg Young&rsquo;s excellent talk on <a href="https://www.infoq.com/presentations/8-lines-code-refactoring">8 Lines of Code</a> I was thinking about how this kind of thinking applies to the mediator pattern, and specifically the <a href="https://github.com/jbogard/MediatR">MediatR</a> implementation.</p>
<p>I have written about the advantages of <a href="/2016/03/19/cqs-with-mediatr/">CQRS with MediatR</a> before, but having used it for a long time now, there are some parts which cause friction on a regular basis.</p>
<h2 id="the-problems">The problems</h2>
<h3 id="discoverability">Discoverability</h3>
<p>The biggest issue first.  You have a controller with the following constructor:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> AddressController(IMediator mediator)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    _mediator = mediator;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>What messages does it emit? What handlers are used by it?  No idea without grepping for <code>_mediator.</code></p>
<h3 id="where-is-the-hander-for-x">Where is the hander for X?</h3>
<p>So you have a controller with a method which sends a <code>GetAllAddressesQuery</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">AddressController</span> : ApiController
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> IEnumerable&lt;Address&gt; Get()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> _mediator.Send(<span style="color:#66d9ef">new</span> GetAllAddressesQuery(User));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The fastest way to get to the handler definition is to hit <code>Ctrl+T</code> and type in <code>GetAllAddressesQueryHandler</code>.  This becomes more problematic on larger codebases when you can end up with many handlers with similar names.</p>
<h3 id="what-calls-commandqueryhandler">What calls {command|query}Handler?</h3>
<p>Given the following handler, what uses it?</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">GetAllAddressesQueryHandler</span> : IRequestHandler&lt;GetAllAddressesQuery, IEnumerable&lt;Address&gt;&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> IEnumerable&lt;Address&gt; Handle(GetAllAddressesQuery message)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//...</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>With this problem you can use <code>Find Usages</code> on the <code>GetAllAddressesQuery</code> type parameter to find what calls it, so this isn&rsquo;t so bad at all.  The main problem is I am often doing <code>Find Usages</code> on the handler itself, not the message.</p>
<h2 id="solutions">Solutions</h2>
<h3 id="discoverability-1">Discoverability</h3>
<p>The team I am on at work felt this problem a lot before I joined, and had decided to role their own mediation pipeline.  It works much the same as MediatR, but rather than injecting an <code>IMediator</code> interface into the constructor, you inject interface(s) representing the handler(s) being used:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> AddressController(IGetAllAddressesQueryHandler getHandler, IAddAddressHandler addHandler)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    _getHandler = getHandler;
</span></span><span style="display:flex;"><span>    _addHandler = addHandler;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The trade-offs made by this method are:</p>
<ul>
<li>The controllers are now more tightly coupled to the handlers (Handlers are mostly used by 1 controller anyway)</li>
<li>We can&rsquo;t easily do multicast messages (We almost never need to do this)</li>
<li>More types are required (the interface) for your handler (so what?)</li>
</ul>
<p>On the whole, I think this is a pretty good trade-off to be made, we get all the discoverability we wanted, and our controllers and handlers are still testable.</p>
<h3 id="what-callswhere-is-commandqueryhandler">What calls/Where is {command|query}Handler?</h3>
<p>This is also solved by the switch to our internal library, but we also augment the change by grouping everything into functionality groups:</p>
<pre tabindex="0"><code>Frontend
  Adddress
    AddressController.cs
    GetAllAddressesQuery.cs
    GetAllAddressesQueryHandler.cs
    IGetAllAddressesQueryHandler.cs
  Contact
    ContactController.cs
    ...
  Startup.cs
  project.json
</code></pre><p>I happen to prefer this structure to a folder for each role (e.g. <code>controllers</code>, <code>messages</code>, <code>handlers</code>), so this is not a hard change to make for me.</p>
<h2 id="magic">Magic</h2>
<p>As Greg noted in his video, the second you take in a 3rd party library, it&rsquo;s code you own (or are responsible for).  The changes we have made have really just traded some 3rd party magic for some internal magic.  How the handler pipeline gets constructed can be a mystery still (unless you go digging through the library), but it&rsquo;s a mystery we control.</p>
<p>The important part of this to note is that we felt a pain/friction with how we are working, and decided to change what trade-offs we were making.</p>
<p>What trade-offs are you making?  Is it worth changing the deal?</p>
]]></content:encoded></item><item><title>Git Aliases</title><link>https://andydote.co.uk/2017/01/06/git-aliases/</link><pubDate>Fri, 06 Jan 2017 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2017/01/06/git-aliases/</guid><description>Git is great, but creating some git aliases is a great way to make your usages even more efficient.
To add any of these you can either copy and paste into the [alias] section of your .gitconfig file or run git config --global alias.NAME 'COMMAND' replacing NAME with the alias to use, and COMMAND with what to run.
So without further ado, here are the ones I have created and use on a very regular basis.</description><content:encoded><![CDATA[<p>Git is great, but creating some git aliases is a great way to make your usages even more efficient.</p>
<p>To add any of these you can either copy and paste into the <code>[alias]</code> section of your <code>.gitconfig</code> file or run <code>git config --global alias.NAME 'COMMAND'</code> replacing <code>NAME</code> with the alias to use, and <code>COMMAND</code> with what to run.</p>
<p>So without further ado, here are the ones I have created and use on a very regular basis.</p>
<h1 id="constant-usage">Constant usage</h1>
<ul>
<li>
<p><code>git s</code> - an alias for <code>git status</code>.  Have to save those 5 keypresses!</p>
<pre tabindex="0"><code>s = status
</code></pre></li>
<li>
<p><code>git cm &quot;some commit message&quot;</code> - shorthand for commit with a message</p>
<pre tabindex="0"><code>cm = commit -m
</code></pre></li>
<li>
<p><code>git dc</code> - diff files staged for commit</p>
<pre tabindex="0"><code>dc = diff --cached
</code></pre></li>
<li>
<p><code>git scrub</code> - deletes everything not tracked by git (<code>git clean -dxf</code>) except the <code>packages</code> and <code>node_modules</code> directories</p>
<pre tabindex="0"><code>scrub = clean -dxf --exclude=packages --exclude=node_modules
</code></pre></li>
</ul>
<h1 id="context-switching-rebasing-on-dirty-head">Context switching, rebasing on dirty HEAD</h1>
<p>I rebase my changes onto the current branches often, but rebasing requires a clean repository to work on.  The following two aliases are used something like this: <code>git save &amp;&amp; git pull --rebase &amp;&amp; git undo</code></p>
<ul>
<li>
<p><code>git save</code> - adds and commits everything in the repository, with the commit message <code>SAVEPOINT</code></p>
<pre tabindex="0"><code>save = !git add -A &amp;&amp; git commit -m &#39;SAVEPOINT&#39;
</code></pre></li>
<li>
<p><code>git undo</code> - undoes the last commit, leaving everything as it was before committing.  Mostly used to undo a <code>git save</code> call</p>
<pre tabindex="0"><code>undo = reset HEAD~1 --mixed
</code></pre></li>
</ul>
<p>I also use these if I need to save my work to work on a bug fix on a different branch.</p>
<h1 id="what-have-i-done">What have I done?</h1>
<p>Often I want commits I have pending, either to the local master, or a remote tracking branch.  These both give an output like this:</p>
<p><img loading="lazy" src="git-pending.png" alt="Git Pending"  />
</p>
<ul>
<li>
<p><code>git pending</code> - shows the commits on the current branch compared to the <code>origin/master</code> branch</p>
<pre tabindex="0"><code>pending = log origin/master..HEAD --pretty=oneline --abbrev-commit --format=&#39;%Cgreen%cr:%Creset %C(auto)%h%Creset %s&#39;
</code></pre></li>
<li>
<p><code>git pendingup</code> - shows the commits on the current branch compared to its tracking branch</p>
<pre tabindex="0"><code>pendingup = &#34;!git log origin/\&#34;$(git rev-parse --abbrev-ref HEAD)\&#34;..HEAD --pretty=oneline --abbrev-commit --format=&#39;%Cgreen%cr:%Creset %C(auto)%h%Creset %s&#39;&#34;
</code></pre></li>
</ul>
<h1 id="more">More?</h1>
<p>I have some others not documented here, but are in my <a href="https://github.com/Pondidum/config/blob/master/configs/.gitconfig">config repo</a> on Github.</p>
]]></content:encoded></item><item><title>Strong Type All The Configurations</title><link>https://andydote.co.uk/2016/12/06/strong-type-all-the-configurations/</link><pubDate>Tue, 06 Dec 2016 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2016/12/06/strong-type-all-the-configurations/</guid><description>As anyone I work with can attest, I a have been prattling on about strong typing everything for quite a while. One of the places I feel people don&amp;rsquo;t utilise strong typing enough is in application configuration. This manifests in a number of problems in a codebase.
The Problems The first problem is when nothing at all is done about it, and you end up with code spattered with this:</description><content:encoded><![CDATA[<p>As anyone I work with can attest, I a have been prattling on about strong typing everything for quite a while.
One of the places I feel people don&rsquo;t utilise strong typing enough is in application configuration.  This manifests in a number of problems in a codebase.</p>
<h2 id="the-problems">The Problems</h2>
<p>The first problem is when nothing at all is done about it, and you end up with code spattered with this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> someUrl = <span style="color:#66d9ef">new</span> Uri(ConfigurationManager.AppSettings[<span style="color:#e6db74">&#34;RemoteService&#34;</span>]);
</span></span></code></pre></div><p>This itself causes a few problems:</p>
<ul>
<li><strong>Repeated:</strong> You have magic strings throughout your codebase</li>
<li><strong>Consistency:</strong> Was it <code>RemoteService</code> or <code>RemoteServiceUri</code>. Or was it in <code>ConnectionStrings</code> or <code>AppSettings</code>?</li>
<li><strong>Visibility:</strong> Can you tell which classes require on which (if any) configuration values?</li>
<li><strong>Typing:</strong> Was it actually a URL? or was it DNS entry?</li>
<li><strong>Late errors:</strong> You will only find out once that particular piece of code runs</li>
<li><strong>Tight Coupling:</strong> Tests won&rsquo;t help either, as they&rsquo;ll be reading your test&rsquo;s <code>app.config</code> instead&hellip;</li>
</ul>
<h2 id="solution-version-1">Solution: Version 1</h2>
<p>The first solution involves abstracting the <code>ConfigurationManager</code> behind a general interface, which can be injected into classes requiring configuration values.  The interface is usually along the following lines:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">ISettings</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> GetString(<span style="color:#66d9ef">string</span> key);
</span></span><span style="display:flex;"><span>    Uri GetUri(<span style="color:#66d9ef">string</span> key);
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// GetInt, GetShort, etc.</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And having an implementation which uses the <code>ConfigurationManager</code> directly:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Settings</span> : ISettings
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> GetString(<span style="color:#66d9ef">string</span> key) =&gt; ConfigurationManager.AppSettings[key];
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Uri GetUri(<span style="color:#66d9ef">string</span> key) =&gt; <span style="color:#66d9ef">new</span> Uri(ConfigurationManager.AppSettings[key]);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This solves one of the problems of direct usage of the <code>ConfigurationManager</code>, namely <strong>Tight Coupling</strong>.  By using an interface we can now use <a href="http://nsubstitute.github.io/">NSubstitute</a> or similar mocking library to disconnect tests from <code>app.config</code> and <code>web.config</code>.</p>
<p>It doesn&rsquo;t really solve the <strong>Typing</strong> issue however, as the casting is only done on fetching the configuration value, and so errors in casting still only happen when the code is executed.  It also doesn&rsquo;t really solve the <strong>Discoverability</strong> issue either - you can now tell if a class requires configuration values, but you cannot tell which values it requires from outside.</p>
<p>The other issues such as <strong>Repeatablility</strong>, <strong>Late Errors</strong> and <strong>Consistency</strong> are not addressed by this method at all.</p>
<h2 id="solution-version-2">Solution: Version 2</h2>
<p>My preferred method of solving all of these problems is to replace direct usage of <code>ConfigurationManager</code> with an interface &amp; class pair, but with the abstraction being application specific, rather than general.  For example, at application might have this as the interface:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IConfiguration</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> ApplicationName { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    Uri RemoteHost { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> TimeoutSeconds { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This would then be implemented by a concrete class:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Configuration</span> : IConfiguration
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> ApplicationName { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Uri RemoteHost { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> TimeoutSeconds { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Configuration()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        ApplicationName = ConfigurationManager.AppSetting[nameof(ApplicationName)];
</span></span><span style="display:flex;"><span>        RemoteHost = <span style="color:#66d9ef">new</span> Uri(ConfigurationManager.AppSetting[nameof(RemoteHost)]);
</span></span><span style="display:flex;"><span>        TimeoutSeconds = (<span style="color:#66d9ef">int</span>)ConfigurationManager.AppSetting[nameof(TimeoutSeconds)];
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This method solves all of the first listed problems:</p>
<p><strong>Repeated</strong> and <strong>Consistency</strong> are solved, as the only repetition is the usage of configuration properties themselves.  <strong>Visibility</strong> is solved as you can now either use &ldquo;Find Usages&rdquo; on a property, or you can split your configuration <code>interface</code> to have a specific set of properties for each class which is going to need configuration.</p>
<p><strong>Typing</strong> and <strong>Late errors</strong> are solved as all properties are populated on the first creation of the class, and exceptions are thrown immediately if there are any type errors.</p>
<p><strong>Tight Coupling</strong> is also solved, as you can fake the entire <code>IConfiguration</code> interface for testing with, or just the properties required for a given test.</p>
<p>The only down side is the amount of writing needed to make the constructor, and having to do the same code in every application you write.</p>
<h2 id="solution-version-3">Solution: Version 3</h2>
<p>The third solution works exactly as the 2nd solution, but uses the <a href="https://www.nuget.org/packages/stronk">Stronk Nuget library</a> to populate the configuration object.  <strong>Stronk</strong> takes all the heavy lifting out of configuration reading, and works for most cases with zero extra configuration required.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IConfiguration</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">string</span> ApplicationName { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    Uri RemoteHost { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> TimeoutSeconds { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Configuration</span> : IConfiguration
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> ApplicationName { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Uri RemoteHost { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> TimeoutSeconds { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> Configuration()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span>.FromAppConfig(); <span style="color:#75715e">//this.FromWebConfig() works too</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Stronk</strong> supports a lot of customisation.  For example, if you wanted to be able to handle populating properties of type <code>MailAddress</code>, you can add it like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> Configuration()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> mailConverter = <span style="color:#66d9ef">new</span> LambdaValueConverter&lt;MailAddress&gt;(val =&gt; <span style="color:#66d9ef">new</span> MailAddress(val));
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> options = <span style="color:#66d9ef">new</span> StronkOptions();
</span></span><span style="display:flex;"><span>    options.Add(mailConverter);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">this</span>.FromAppConfig(options);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>You can also replace (or supplement):</p>
<ul>
<li>How it detects which properties to populate</li>
<li>How to populate a property</li>
<li>How to pick a value from the configuration source for a given property</li>
<li>How to convert a value for a property</li>
<li>Where configuration is read from</li>
</ul>
<p>A few features to come soon:</p>
<ul>
<li>Additional types supported &ldquo;out of the box&rdquo; (such as <code>TimeSpan</code> and <code>DateTime</code>)</li>
<li>Exception policy controlling:
<ul>
<li>What happens on not being able to find a value in the configuration source</li>
<li>What happens on not being able to find a converter</li>
<li>What happens on a converter throwing an exception</li>
</ul>
</li>
</ul>
<p>I hope you find it useful.  <a href="https://github.com/Pondidum/Stronk/">Stronk&rsquo;s Source is available on Github</a>, and contributions are welcome :)</p>
]]></content:encoded></item><item><title>Shouldly: Why would you assert any other way?</title><link>https://andydote.co.uk/2016/10/09/assertion-style/</link><pubDate>Sun, 09 Oct 2016 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2016/10/09/assertion-style/</guid><description>I like to make my development life as easy as possible - and removing small irritations is a great way of doing this. Having used Shouldly in anger for a long time, I have to say I feel a little hamstrung when going back to just using NUnit&amp;rsquo;s assertions.
I have been known on a couple of projects which use only NUnit assertions, when trying to solve a test failure with array differences, to install Shouldly, fix the test, then remove Shouldly again!</description><content:encoded><![CDATA[<p>I like to make my development life as easy as possible - and removing small irritations is a great way of doing this.  Having used <a href="http://docs.shouldly-lib.net/v2.4.0/docs">Shouldly</a> in anger for a long time, I have to say I feel a little hamstrung when going back to just using NUnit&rsquo;s assertions.</p>
<p>I have been known on a couple of projects which use only NUnit assertions, when trying to solve a test failure with array differences, to install Shouldly, fix the test, then remove Shouldly again!</p>
<p>The rest of this post goes through the different assertion models, and how they differ from each other and, eventually, why everyone should be using Shouldly!</p>
<h2 id="the-most-basic">The Most Basic</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> valueOne = <span style="color:#e6db74">&#34;Something&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> valueTwo = <span style="color:#e6db74">&#34;Something else&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Debug.Assert(valueOne == valueTwo);
</span></span><span style="display:flex;"><span>Debug.Assert(valueOne == valueTwo, <span style="color:#e6db74">$&#34;{valueOne} should have been {valueTwo}&#34;</span>);
</span></span></code></pre></div><p>This is an assertion at it&rsquo;s most basic.  It will only assert if the condition is false, and optionally you can specify a 2nd parameter with a message.</p>
<p>This has a couple of good points to it. No external dependencies are required, and it is strong typed (as your condition has to compile.)  The down sides to this are that it is not very descriptive, and can only be used in Debug compiles (or with the DEBUG constant defined), meaning a Release mode build cannot be tested with this.</p>
<p>This also suffers from the descriptiveness problem - an output from this will only have a message saying an assertion failed, rather than anything helpful in figuring out why an assertion failed.</p>
<h2 id="nunits-first-attempt">NUnit&rsquo;s First Attempt</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> valueOne = <span style="color:#e6db74">&#34;Something&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> valueTwo = <span style="color:#e6db74">&#34;Something else&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Assert.AreEqual(valueOne, valueTwo);
</span></span><span style="display:flex;"><span>Assert.AreEqual(valueOne, valueTwo, <span style="color:#e6db74">$&#34;{valueOne} should have been {valueTwo}&#34;</span>);
</span></span></code></pre></div><p>This improves on the Most Basic version by working in Release mode builds, and as it only depends on the test framework, it doesn&rsquo;t add a dependency you didn&rsquo;t already have.</p>
<p>There are two things I dislike about this method: it remains as undescriptive as the first method, and it adds the problem of parameter ambiguity:  Which of the two parameters is the expected value, and which is the value under test? You can&rsquo;t tell without checking the method declaration.  While this is a small issue, it can cause headaches when you are trying to debug a test which has started failing, only to discover the assertion being the wrong way around was leading you astray!</p>
<h2 id="nunits-second-attempt">NUnit&rsquo;s Second Attempt</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> valueOne = <span style="color:#e6db74">&#34;Something&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> valueTwo = <span style="color:#e6db74">&#34;Something else&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Assert.That(valueOne, Is.EqualTo(valueTwo));
</span></span><span style="display:flex;"><span>Assert.That(valueOne, Is.EqualTo(valueTwo), <span style="color:#e6db74">$&#34;{valueOne} should have been {valueTwo}&#34;</span>);
</span></span></code></pre></div><p>This is an interesting attempt at readability.  On the one hand, it&rsquo;s very easy to read as a sentence, but it is very wordy, especially if you are wanting to do a Not equals <code>Is.Not.EqualTo(valueTwo)</code>.</p>
<p>This biggest problem with this however, is the complete loss of strong typing - both arguments are <code>object</code>.  This can trip you up when testing things such as Guids - especially if one of the values gets <code>.ToString()</code> on it at some point:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> id = Guid.NewGuid();
</span></span><span style="display:flex;"><span>Assert.That(id.ToString(), Is.EqualTo(id));
</span></span></code></pre></div><p>Not only will this compile, but when the test fails, unless you are paying close attention to the output, it will look like it should&rsquo;ve passed, as the only difference is the <code>&quot;</code> on either side of one of the values.</p>
<h2 id="shouldlys-version">Shouldly&rsquo;s Version</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> valueOne = <span style="color:#e6db74">&#34;Something&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> valueTwo = <span style="color:#e6db74">&#34;Something else&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>valueOne.ShouldBe(valueTwo);
</span></span><span style="display:flex;"><span>valueOne.ShouldBe(valueTwo, () =&gt; <span style="color:#e6db74">&#34;Custom Message&#34;</span>);
</span></span></code></pre></div><p>Finally we hit upon the <a href="http://docs.shouldly-lib.net/v2.4.0/docs">Shouldly</a> library.  This assertion library not only solves the code-time issues of strong typing, parameter clarity, and wordiness, it really improves the descriptiveness problem.</p>
<p>Shouldly uses the expression being tested against to create meaningful error messages:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#75715e">//nunit</span>
</span></span><span style="display:flex;"><span>Assert.That(map.IndexOfValue(<span style="color:#e6db74">&#34;boo&#34;</span>), Is.EqualTo(<span style="color:#ae81ff">2</span>));    <span style="color:#75715e">// -&gt; Expected 2 but was 1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//shouldly</span>
</span></span><span style="display:flex;"><span>map.IndexOfValue(<span style="color:#e6db74">&#34;boo&#34;</span>).ShouldBe(<span style="color:#ae81ff">2</span>);                    <span style="color:#75715e">// -&gt; map.IndexOfValue(&#34;boo&#34;) should be 2 but was 1</span>
</span></span></code></pre></div><p>This is even more pronounced when you are comparing collections:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">new</span>[] { <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">3</span> }.ShouldBe(<span style="color:#66d9ef">new</span>[] { <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">4</span> });
</span></span></code></pre></div><p>Produces the following output</p>
<pre tabindex="0"><code>should be
    [1, 2, 4]
but was
    [1, 2, 3]
difference
    [1, 2, *3*]
</code></pre><p>And when comparing strings, not only does it tell you they were different, but provides a visualisation of what was different:</p>
<pre tabindex="0"><code>input
    should be
&#34;this is a longer test sentence&#34;
    but was
&#34;this is a long test sentence&#34;
    difference
Difference     |                                |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |
               |                               \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/
Index          | ...  9    10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29
Expected Value | ...  \s   l    o    n    g    e    r    \s   t    e    s    t    \s   s    e    n    t    e    n    c    e
Actual Value   | ...  \s   l    o    n    g    \s   t    e    s    t    \s   s    e    n    t    e    n    c    e
</code></pre><h2 id="finishing">Finishing</h2>
<p>So having seen the design time experience and rich output Shouldly gives you, why would you not use it?</p>
]]></content:encoded></item><item><title>Visualising NuGet Dependencies</title><link>https://andydote.co.uk/2016/09/12/nuget-dependencies/</link><pubDate>Mon, 12 Sep 2016 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2016/09/12/nuget-dependencies/</guid><description>My new place of work has a lot of nuget packages, and I wanted to understand the dependencies between them. To do this I wrote a simple shell script to find all the packages.config files on my machine, and output all the relationships in a way which I could view them.
The format for viewing I use for this is Graphviz&amp;rsquo;s dot language, and the resulting output can be pasted into WebGraphviz to view.</description><content:encoded><![CDATA[<p>My new place of work has a lot of nuget packages, and I wanted to understand the dependencies between them.  To do this I wrote a simple shell script to find all the <code>packages.config</code> files on my machine, and output all the relationships in a way which I could view them.</p>
<p>The format for viewing I use for this is <a href="http://graphviz.org/doc/info/lang.html">Graphviz&rsquo;s dot language</a>, and the resulting output can be pasted into <a href="http://www.webgraphviz.com/">WebGraphviz</a> to view.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>RESULT_FILE<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;graph.dot&#34;</span> <span style="color:#75715e"># the output file</span>
</span></span><span style="display:flex;"><span>NAME_MATCH<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;Microsoft\.&#39;</span> <span style="color:#75715e"># leave this as a blank string if you want no filtering</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;&#39;</span> &gt; $RESULT_FILE  <span style="color:#75715e"># clear out the file</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;digraph Dependencies {&#39;</span> &gt;&gt; $RESULT_FILE
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;  rankdir=LR;&#39;</span> &gt;&gt; $RESULT_FILE <span style="color:#75715e"># we want a left to right graph, as it&#39;s a little easier to read</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># find all packages.config, recursively beaneath the path passed into the script</span>
</span></span><span style="display:flex;"><span>find $1 -iname packages.config | <span style="color:#66d9ef">while</span> read line; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># find any csproj file next to the packages.config</span>
</span></span><span style="display:flex;"><span>  project_path<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">$(</span>dirname $line<span style="color:#66d9ef">)</span><span style="color:#e6db74">/*.csproj&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># check it exists (e.g. to not error on a /.nuget/packages.config path)</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -f $project_path <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># find the name of the assembly</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># (our projects are not named with the company prefix, but the assemblies/packages are)</span>
</span></span><span style="display:flex;"><span>    asm_name<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>grep -oP <span style="color:#e6db74">&#39;&lt;RootNamespace&gt;\K(.*)(?=&lt;)&#39;</span> $project_path<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Ignore any tests projects (optional)</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">[[</span> <span style="color:#e6db74">${</span>line<span style="color:#e6db74">}</span> !<span style="color:#f92672">=</span> *<span style="color:#e6db74">&#34;Tests&#34;</span>* <span style="color:#f92672">]]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e"># find all lines in the packages.config where the package name has a prefix</span>
</span></span><span style="display:flex;"><span>      grep -Po <span style="color:#e6db74">&#34;package id=\&#34;\K(</span>$NAME_MATCH<span style="color:#e6db74">.*?)(?=\&#34;)&#34;</span> $line | <span style="color:#66d9ef">while</span> read package; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># write it to the result</span>
</span></span><span style="display:flex;"><span>        echo <span style="color:#e6db74">&#34;  \&#34;</span>$asm_name<span style="color:#e6db74">\&#34; -&gt; \&#34;</span>$package<span style="color:#e6db74">\&#34;&#34;</span> &gt;&gt; $RESULT_FILE
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;}&#39;</span> &gt;&gt; $RESULT_FILE
</span></span></code></pre></div><p>To use this, you just need to call it with the path you want to visualise:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ ./graph.sh /d/dev/projects/ledger
</span></span></code></pre></div><p>Note on the <code>grep</code> usage I am using a non-capturing look behind (everything before <code>\K</code>) and a non-capturing look ahead (the <code>(?=\&quot;)</code> part), as if you just use a &rsquo;normal&rsquo; expression, the parts which match which I don&rsquo;t care about also get outputed by grep.  In C# I would have written the expression like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> packageName = Regex.Match(line, <span style="color:#e6db74">&#34;package id=\&#34;(.*?)\&#34;&#34;</span>).Groups[<span style="color:#ae81ff">1</span>].Value;
</span></span></code></pre></div><p>As an example, if I run this over my directory with all of the <a href="https://github.com/pondidum/ledger">Ledger</a> code in it, and filter out test dependencies (e.g. remove Shouldy, NSubstitute, Xunit), you get the following dot file:</p>
<pre tabindex="0"><code>
digraph Dependencies {
  rankdir=LR;
  &#34;Ledger.Acceptance&#34; -&gt; &#34;Newtonsoft.Json&#34;
  &#34;Ledger.Tests&#34; -&gt; &#34;Newtonsoft.Json&#34;
  &#34;Ledger.Tests&#34; -&gt; &#34;RabbitMQ.Client&#34;
  &#34;Ledger.Stores.Postgres&#34; -&gt; &#34;Dapper&#34;
  &#34;Ledger.Stores.Postgres&#34; -&gt; &#34;Ledger&#34;
  &#34;Ledger.Stores.Postgres&#34; -&gt; &#34;Newtonsoft.Json&#34;
  &#34;Ledger.Stores.Postgres&#34; -&gt; &#34;Npgsql&#34;
  &#34;Ledger.Stores.Postgres.Tests&#34; -&gt; &#34;Dapper&#34;
  &#34;Ledger.Stores.Postgres.Tests&#34; -&gt; &#34;Ledger&#34;
  &#34;Ledger.Stores.Postgres.Tests&#34; -&gt; &#34;Ledger.Acceptance&#34;
  &#34;Ledger.Stores.Postgres.Tests&#34; -&gt; &#34;Newtonsoft.Json&#34;
  &#34;Ledger.Stores.Postgres.Tests&#34; -&gt; &#34;Npgsql&#34;
  &#34;Ledger.Stores.Fs&#34; -&gt; &#34;Ledger&#34;
  &#34;Ledger.Stores.Fs&#34; -&gt; &#34;Newtonsoft.Json&#34;
  &#34;Ledger.Stores.Fs.Tests&#34; -&gt; &#34;Ledger&#34;
  &#34;Ledger.Stores.Fs.Tests&#34; -&gt; &#34;Ledger.Acceptance&#34;
  &#34;Ledger.Stores.Fs.Tests&#34; -&gt; &#34;Newtonsoft.Json&#34;
  &#34;Ledger.Stores.Fs.Tests&#34; -&gt; &#34;structuremap&#34;
}
</code></pre><p>Which renders into the following graph:</p>
<p><img loading="lazy" src="nuget-graph.png" alt="Nuget Graph"  />
</p>
<p>In the process of writing this though, I did have to go back into the projects and find out why the <code>Ledger.Tests</code> was referencing <code>RabbitMQ.Client</code> (example of appending events to a queue) and why <code>Ledger.Stores.Fs.Tests</code> referened <code>Structuremap</code> (it looks like I forgot to remove the reference after rewriting how Acceptance tests were setup).</p>
<p>The gist with all the code in can be found here: <a href="https://gist.github.com/Pondidum/a79bddeeba612f9eb1074e9f5274b047">graph.sh</a>.</p>
<p>Hope this is useful to others too!</p>
]]></content:encoded></item><item><title>Preventing MicroService Boilerplate</title><link>https://andydote.co.uk/2016/07/17/preventing-microservice-boilerplate/</link><pubDate>Sun, 17 Jul 2016 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2016/07/17/preventing-microservice-boilerplate/</guid><description>One of the downsides to microservices I have found is that I end up repeating the same blocks of code over and over for each service. Not only that, but the project setup is repetitive, as all the services use the Single Project Service and Console method.
What do we do in every service? Initialise Serilog. Add a Serilog sink to ElasticSearch for Kibana (but only in non-local config.) Hook/Unhook the AppDomain.</description><content:encoded><![CDATA[<p>One of the downsides to microservices I have found is that I end up repeating the same blocks of code over and over for each service.  Not only that, but the project setup is repetitive, as all the services use the <a href="/2015/08/30/single-project-service-and-console/">Single Project Service and Console</a> method.</p>
<h1 id="what-do-we-do-in-every-service">What do we do in every service?</h1>
<ul>
<li>Initialise Serilog.</li>
<li>Add a Serilog sink to ElasticSearch for Kibana (but only in non-local config.)</li>
<li>Hook/Unhook the <code>AppDomain.Current.UnhandledException</code> handler.</li>
<li>Register/UnRegister with Consul.</li>
<li>Setup StructureMap, if using an IOC Container.</li>
<li>Run as a Console if the <code>Environment.UserInteractive</code> flag is true.</li>
<li>Run as a Service otherwise</li>
</ul>
<p>The only task with potential to have variance each time is the setting up of StructureMap, the rest are almost identical every time.</p>
<h1 id="how-to-solve-all-this-repetition">How to solve all this repetition?</h1>
<p>To rectify this, I created a nuget project which encapsulates all of this logic, and allows us to create a Console project with the following startup:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c#" data-lang="c#"><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> Main(<span style="color:#66d9ef">string</span>[] args)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	ServiceHost.Run&lt;Startup&gt;(<span style="color:#e6db74">&#34;TestService&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This requires one class implementing the <code>IStartup</code> interface, and there are some optional interfaces which can be implemented too:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c#" data-lang="c#"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Startup</span> : IStartup, IDisposable
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Startup()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		Console.WriteLine(<span style="color:#e6db74">&#34;starting up&#34;</span>);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Execute(ServiceArgs service)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		File.AppendAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, <span style="color:#e6db74">&#34;log.txt&#34;</span>), <span style="color:#66d9ef">new</span>[] { <span style="color:#e6db74">&#34;boot!&#34;</span> });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">while</span> (service.CancelRequested == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>			Thread.Sleep(<span style="color:#ae81ff">500</span>);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Dispose()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		Console.WriteLine(<span style="color:#e6db74">&#34;shutting down&#34;</span>);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Optionally, the project can implement two interfaces to control Consul and ElasticSearch configuration:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c#" data-lang="c#"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Config</span> : ILogConfig, IConsulRegistration
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">bool</span> EnableKibana { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Uri LoggingEndpoint { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> CatalogRegistration CreateRegistration()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> CatalogRegistration() { Service = <span style="color:#66d9ef">new</span> AgentService
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			Address = <span style="color:#e6db74">&#34;http://localhost&#34;</span>,
</span></span><span style="display:flex;"><span>			Port = <span style="color:#ae81ff">8005</span>,
</span></span><span style="display:flex;"><span>			Service = <span style="color:#e6db74">&#34;TestService&#34;</span>
</span></span><span style="display:flex;"><span>		}};
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> CatalogDeregistration CreateDeregistration()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> CatalogDeregistration { ServiceID = <span style="color:#e6db74">&#34;TestService&#34;</span> };
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>By implementing these interfaces, the <code>ServiceHost</code> class can use StructureMap to find the implementations (if any) at run time.</p>
<p>Talking of StructureMap, if we wish to configure the container in the host application, all we need to do is create a class which inherits <code>Registry</code>, and the ServiceHost&rsquo;s StructureMap configuration will find it.</p>
<h1 id="how-do-we-support-other-tools">How do we support other tools?</h1>
<p>Well we could implment some kind of stage configuration steps, so your startup might change to look like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c#" data-lang="c#"><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> Main(<span style="color:#66d9ef">string</span>[] args)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	ServiceHost.Stages(<span style="color:#66d9ef">new</span> LoggingStage(), <span style="color:#66d9ef">new</span> ConsulStage(), <span style="color:#66d9ef">new</span> SuperAwesomeThingStage());
</span></span><span style="display:flex;"><span>	ServiceHost.Run&lt;Startup&gt;(<span style="color:#e6db74">&#34;TestService&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The reason I haven&rsquo;t done this is that on the whole, we tend to use the same tools for each job in every service; StructureMap for IOC, Serilog for logging, Consul for discovery.  So rather than having to write some boilerplate for every service (e.g. specifying all the stages), I just bake the options in to <code>ServiceHost</code> directly.</p>
<p>This means that if you want your own version of this library with different tooling support, you need to write it yourself.  As a starting point, I have the code for the <a href="https://github.com/pondidum/ServiceContainer"><code>ServiceContainer</code> project up on Github</a>.</p>
<p>It is not difficult to create new stages for the pipeline - all the different tasks the <code>ServiceHost</code> can perform are implemented in a pseudo Russian-Doll model - they inherit <code>Stage</code>, which looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c#" data-lang="c#"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Stage</span> : IDisposable
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> IContainer Container { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">void</span> Execute();
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">void</span> Dispose();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Anything you want to your stage to do before the <code>IStartup.Execute()</code> call is made is done in <code>Execute()</code>, similarly anything to be done afterwards is in <code>Dispose()</code>.  For example, the <code>ConsulStage</code> is implemented like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c#" data-lang="c#"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ConsulStage</span> : Stage
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Execute()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> registration = Container.TryGetInstance&lt;IConsulRegistration&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (registration != <span style="color:#66d9ef">null</span>)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">var</span> client = <span style="color:#66d9ef">new</span> ConsulClient();
</span></span><span style="display:flex;"><span>			client.Catalog.Register(registration.CreateRegistration());
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Dispose()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> registration = Container.TryGetInstance&lt;IConsulRegistration&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (registration != <span style="color:#66d9ef">null</span>)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">var</span> client = <span style="color:#66d9ef">new</span> ConsulClient();
</span></span><span style="display:flex;"><span>			client.Catalog.Deregister(registration.CreateDeregistration());
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Finally you just need to add the stage to the <code>ServiceWrapper</code> constructor:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c#" data-lang="c#"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> ServiceWrapper(<span style="color:#66d9ef">string</span> name, Type entryPoint)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">// snip...</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	_stages = <span style="color:#66d9ef">new</span> Stage[]
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">new</span> LoggingStage(name),
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">new</span> ConsulStage()
</span></span><span style="display:flex;"><span>	};
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h1 id="get-started">Get started!</h1>
<p>That&rsquo;s all there is to it!  Hopefully this gives you a good starting point for de-boilerplating your microservices :)</p>
]]></content:encoded></item><item><title>Database Integrations for MicroServices</title><link>https://andydote.co.uk/2016/06/09/database-integrations-for-microservices/</link><pubDate>Thu, 09 Jun 2016 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2016/06/09/database-integrations-for-microservices/</guid><description>This is a follow up post after seeing Michal Franc&amp;rsquo;s NDC talk on migrating from Monolithic architectures.
One point raised was that Database Integration points are a terrible idea - and I wholeheartedly agree. However, there can be a number of situations where a Database Integration is the best or only way to achieve the end goal. This can be either technical; say a tool does not support API querying (looking at you SSRS), or cultural; the other team either don&amp;rsquo;t have the willingness, time, or power to learn how to query an API.</description><content:encoded><![CDATA[<p>This is a follow up post after seeing <a href="https://twitter.com/francmichal">Michal Franc</a>&rsquo;s NDC talk on migrating from Monolithic architectures.</p>
<p>One point raised was that Database Integration points are a terrible idea - and I wholeheartedly agree.  However, there can be a number of situations where a Database Integration is the best or only way to achieve the end goal.  This can be either technical; say a tool does not support API querying (looking at you SSRS), or cultural; the other team either don&rsquo;t have the willingness, time, or power to learn how to query an API.</p>
<p>One common situation is a reporting team, who either cannot query an API (e.g. they are stuck using SSRS), or don&rsquo;t want/have time to learn how to query an API.</p>
<p>There are two ways which can make a Database Integration an altogether less painful prospect, both with a common starting point: A separate login to the Database, with only readonly access to a very small set of tables and views.</p>
<p>Views can be used to create a representation of the service&rsquo;s data in a manner which makes sense to external systems, for example de-normalising tables, or converting integer based enumerations into their string counterparts.</p>
<p>Tables can be used to expose a transformed version of the service&rsquo;s data, for example a readmodel from an event stream.</p>
<h2 id="event-sourcing-source-data">Event Sourcing source data</h2>
<p>For example, one of our services uses Event Sourcing.  It uses projections to construct readmodels as events are stored (we use the <a href="https://www.nuget.org/packages/ledger">Ledger</a> library, and a SqlServer backend for this.)  To provide a Database Integeration point, we have a second set of projections which populate a set of tables specifically for external querying.</p>
<p>If the following event was committed to the store:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;eventType&#34;</span>: <span style="color:#e6db74">&#34;phoneNumberAdded&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;aggregateID&#34;</span>: <span style="color:#ae81ff">231231</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;number&#34;</span>: <span style="color:#e6db74">&#34;01230 232323&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;home&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The readmodel table, which is just two columns: <code>id:int</code> and <code>json:varchar(max)</code>, would get updated to look like this:</p>
<pre tabindex="0"><code>id      | json
--------+-------------------------------------------------
231231  | {
            &#34;id&#34;: 231231,
            &#34;name&#34;: &#34;Andy Dote&#34;,
            &#34;phones&#34;: [
              { &#34;type&#34;: &#34;mobile&#34;, &#34;number&#34;: &#34;0712345646&#34; },
              { &#34;type&#34;: &#34;home&#34;, &#34;number&#34;: &#34;01230 232323&#34; }
            ]
          }
</code></pre><p>The external integration table, which is a denormalised view of the data would get updated to look like this:</p>
<pre tabindex="0"><code>id      | name      | home_phone    | mobile_phone
--------+-----------+---------------+----------------------
231231  | Andy Dote | 01230 232 323 | 07123 456 456
</code></pre><h3 id="non-sql-systems">Non-SQL Systems</h3>
<p>While I have not needed to implement this yet, there is a plan for how to do it:  a simple regular job which will pull the data from the service&rsquo;s main store, transform it, and insert it into the SQL store.</p>
<h3 id="relational-systems">Relational Systems</h3>
<p>A relational system can be done in a number of ways:</p>
<ul>
<li>In the same manner as the Non-SQL system: with a periodical job</li>
<li>In a similar manner to the Event Sourced system: Updating a second table at the same time as the primary tables</li>
<li>Using SQL triggers: on insert, add a row to the integration table etc.</li>
</ul>
<p>I wouldn&rsquo;t recommend the 3rd option, as you will start ending up with more and more logic living in larger and larger triggers.
The important point on all these methods is that the Integration tables are separate from the main tables: you do not want to expose your internal implementation to external consumers.</p>
]]></content:encoded></item><item><title>CQS with Mediatr</title><link>https://andydote.co.uk/2016/03/19/cqs-with-mediatr/</link><pubDate>Sat, 19 Mar 2016 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2016/03/19/cqs-with-mediatr/</guid><description>This article is some extra thoughts I had on api structure after reading Derek Comartin.
Asides from the benefits that Derek mentions (no fat repositories, thin controllers), there are a number of other advantages that this style of architecture brings.
Ease of Testing By using Command and Queries, you end up with some very useful seams for writing tests.
For controllers With controllers, you typically use Dependency injection to provide an instance of IMediator:</description><content:encoded><![CDATA[<p>This article is some extra thoughts I had on api structure after reading <a href="http://codeopinion.com/thin-controllers-cqrs-mediatr/">Derek Comartin</a>.</p>
<p>Asides from the benefits that Derek mentions (no fat repositories, thin controllers), there are a number of other advantages that this style of architecture brings.</p>
<h2 id="ease-of-testing">Ease of Testing</h2>
<p>By using Command and Queries, you end up with some very useful seams for writing tests.</p>
<h3 id="for-controllers">For controllers</h3>
<p>With controllers, you typically use Dependency injection to provide an instance of <code>IMediator</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">AddressController</span> : ApiController
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IMediator _mediator;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> AddressController(IMediator mediator)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        _mediator = mediator;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> IEnumerable&lt;Address&gt; Get()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> _mediator.Send(<span style="color:#66d9ef">new</span> GetAllAddressesQuery(User));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>You can now test the controller&rsquo;s actions return as you expect:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#a6e22e">[Fact]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> When_requesting_all_addresses()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> mediator = Substitute.For&lt;IMediator&gt;();
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> controller = <span style="color:#66d9ef">new</span> AddressController(mediator);
</span></span><span style="display:flex;"><span>  controller.User = Substitute.For&lt;IPrincipal&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> result = controller.Get();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  mediator
</span></span><span style="display:flex;"><span>      .Received(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>      .Send(Arg.Is&lt;GetAllAddressesQuery&gt;(q =&gt; q.User == controller.User));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This is also useful when doing integration tests, as you can use <code>Microsoft.Owin.Testing.TestApp</code> to test that all the serialization, content negotiation etc works correctly, and still use a substituted mediator so you have known values to test with:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#a6e22e">
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">[Fact]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> <span style="color:#66d9ef">void</span> Addresses_get_should_return_an_empty_json_array()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> mediator = Substitute.For&lt;IMediator&gt;();
</span></span><span style="display:flex;"><span>    mediator.Send(Arg.Any&lt;GetAllAddressesQuery&gt;()).Returns(Enumerable.Empty&lt;Address&gt;());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> server = TestServer.Create(app =&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> api = <span style="color:#66d9ef">new</span> Startup(mediator);
</span></span><span style="display:flex;"><span>        api.Configuration(app);
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> response = <span style="color:#66d9ef">await</span> _server
</span></span><span style="display:flex;"><span>        .CreateRequest(<span style="color:#e6db74">&#34;/api/address&#34;</span>)
</span></span><span style="display:flex;"><span>        .AddHeader(<span style="color:#e6db74">&#34;content-type&#34;</span>, <span style="color:#e6db74">&#34;application/json&#34;</span>)
</span></span><span style="display:flex;"><span>        .GetAsync();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> json = <span style="color:#66d9ef">await</span> response.Content.ReadAsStringAsync();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    json.ShouldBe(<span style="color:#e6db74">&#34;[]&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="for-handlers">For Handlers</h3>
<p>Handler are now isolated from the front end of your application, which means testing is a simple matter of creating an instance, passing in a message, and checking the result.  For example the <code>GetAllAddressesQuery</code> handler could be implemented like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">GetAllAddressesQueryHandler</span> : IRequestHandler&lt;GetAllAddressesQuery, IEnumerable&lt;Address&gt;&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> IEnumerable&lt;Address&gt; Handle(GetAllAddressesQuery message)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (message.User == <span style="color:#66d9ef">null</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> Enumerable.Empty&lt;Address&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> [] {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">new</span> Address { Line1 = <span style="color:#e6db74">&#34;34 Home Road&#34;</span>, PostCode = <span style="color:#e6db74">&#34;BY2 9AX&#34;</span> }
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And a test might look like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#a6e22e">
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">[Fact]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> When_no_user_is_specified()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> handler = <span style="color:#66d9ef">new</span> GetAllAddressesQueryHandler();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> result = handler.Handle(<span style="color:#66d9ef">new</span> GetAllAddressesQuery());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    result.ShouldBeEmpty();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="multiple-front-ends">Multiple Front Ends</h2>
<p>The next advantage of using Commmands and Queries is that you can support multiple frontends without code duplication.  This ties in very nicely with a <a href="http://alistair.cockburn.us/Hexagonal+architecture">Hexagonal architecture</a>. For example, one of my current projects has a set of commands and queries, which are used by a WebApi, and WebSocket connector, and a RabbitMQ adaptor.</p>
<p>This sample also makes use of <a href="https://www.nuget.org/packages/rabbitharness">RabbitHarness</a>, which provides a small interface for easy sending, listening and querying of queues and exchanges.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> RabbitMqConnector(IMediator mediator, IRabbitConnector connector) {
</span></span><span style="display:flex;"><span>    _mediator = mediator;
</span></span><span style="display:flex;"><span>    _connector = connector;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    _connector.ListenTo(<span style="color:#66d9ef">new</span> QueueDefinition { Name = <span style="color:#e6db74">&#34;AddressQueries&#34;</span> }, OnMessage);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">bool</span> OnMessage(IBasicProperties props, GetAllAddressesQuery message)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//in this case, the message sent to RabbitMQ matches the query structure</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> addresses = _mediator.Send(message);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    _connector.SendTo(
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">new</span> QueueDefinition { Name = props.ReplyTo },
</span></span><span style="display:flex;"><span>        replyProps =&gt; replyProps.CorrelationID = props.CorrelationID,
</span></span><span style="display:flex;"><span>        addresses
</span></span><span style="display:flex;"><span>    );
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="vertical-slicing">Vertical Slicing</h2>
<p>This a soft-advantage of Commands and Queries I have found - you can have many more developers working in parallel on a project adding commands and queries etc, before you start treading on each others toes&hellip;and the only painful part is all the <code>*.csproj</code> merges you need to do!  Your mileage may vary on this one!</p>
<h2 id="disadvantages">Disadvantages</h2>
<p>In a large project, you can end up with a lot of extra classes, which can be daunting at first - one of my current projects has around 60 <code>IRequest</code> and <code>IRequestHandler</code> implementations.  As long as you follow a good naming convention, or sort them in to namespaces, it is not that much of a problem.</p>
<h2 id="overall">Overall</h2>
<p>Overall I like this pattern a lot - especially as it makes transitioning towards EventSourcing and/or full CQRS much easier.</p>
<p>How about you? What are your thoughts and experiences on this?</p>
]]></content:encoded></item><item><title>RabbitMQ integration tests in XUnit</title><link>https://andydote.co.uk/2016/03/18/rabbitmq-xunit/</link><pubDate>Fri, 18 Mar 2016 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2016/03/18/rabbitmq-xunit/</guid><description>Quite a number of my projects involve talking to RabbitMQ, and to help check things work as expected, I often have a number of integration tests which talk to a local RabbitMQ instance.
While this is fine for tests being run locally, it does cause problems with the build servers - we don&amp;rsquo;t want to install RabbitMQ on there, and we don&amp;rsquo;t typically want the build to be dependent on RabbitMQ.</description><content:encoded><![CDATA[<p>Quite a number of my projects involve talking to <a href="https://rabbitmq.com">RabbitMQ</a>, and to help check things work as expected, I often have a number of integration tests which talk to a local RabbitMQ instance.</p>
<p>While this is fine for tests being run locally, it does cause problems with the build servers - we don&rsquo;t want to install RabbitMQ on there, and we don&rsquo;t typically want the build to be dependent on RabbitMQ.</p>
<p>To solve this I created a replacement <code>FactAttribute</code> which can check if RabbitMQ is available, and skip tests if it is not.</p>
<p>This attribute works with a single host, and will only check for the host actually being there on its first connection.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">RequiresRabbitFactAttribute</span> : FactAttribute
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">bool?</span> _isAvailable;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> RequiresRabbitFactAttribute(<span style="color:#66d9ef">string</span> host)
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (_isAvailable.HasValue == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>      _isAvailable = CheckHost(host);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (_isAvailable == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>      Skip = <span style="color:#e6db74">$&#34;RabbitMQ is not available on {host}.&#34;</span>;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">bool</span> CheckHost(<span style="color:#66d9ef">string</span> host)
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> factory = <span style="color:#66d9ef">new</span> ConnectionFactory
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      HostName = host,
</span></span><span style="display:flex;"><span>      RequestedConnectionTimeout = <span style="color:#ae81ff">1000</span>;
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">try</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> connection = factory.CreateConnection())
</span></span><span style="display:flex;"><span>      {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> connection.IsOpen;
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">catch</span> (Exception)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">false</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I was planning on using a dictionary, keyed by host to store the availability, but realized that I always use the same host throughout a test suite.</p>
<p>The reason for passing the host name in via the ctor rather than using a constant is that this usually resides within a generic &ldquo;rabbitmq helpers&rdquo; type assembly, and is used in multiple projects.</p>
]]></content:encoded></item><item><title>Generating AssemblyInfo files with Gulp</title><link>https://andydote.co.uk/2015/11/19/generating-assemblyinfo-files-gulpjs/</link><pubDate>Thu, 19 Nov 2015 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2015/11/19/generating-assemblyinfo-files-gulpjs/</guid><description>When changing a project&amp;rsquo;s build script over to Gulpjs, I ran into a problem with one step - creating an AssemblyInfo.cs file.
My projects have their version number in the package.json file, and I read that at compile time, pull in some information from the build server, and write that to an AssemblyVersion.cs file. This file is not tracked by git, and I don&amp;rsquo;t want it showing up as a modification if you run the build script locally.</description><content:encoded><![CDATA[<p>When changing a project&rsquo;s build script over to <a href="http://gulpjs.com/">Gulpjs</a>, I ran into a problem with one step - creating an <code>AssemblyInfo.cs</code> file.</p>
<p>My projects have their version number in the <code>package.json</code> file, and I read that at compile time, pull in some information from the build server, and write that to an <code>AssemblyVersion.cs</code> file.  This file is not tracked by git, and I don&rsquo;t want it showing up as a modification if you run the build script locally.</p>
<p>The problem is that the <a href="https://www.npmjs.com/package/gulp-dotnet-assembly-info">gulp-dotnet-assembly-info</a> package doesn&rsquo;t support generation of files, only updating.  To get around this I used the <a href="https://www.npmjs.com/package/gulp-rename">gulp-rename</a> package to read a template file, and generate the non-tracked <code>AssemblyVersion.cs</code> file.</p>
<h2 id="steps">Steps</h2>
<p>First, create an <code>AssemblyVersion.base</code> file, and save it somewhere in your repository.  I usually put it next to the <code>gulpfile</code>, or in the projects <code>Properties</code> directory, depending on if the project has multiple assemblies or not.  This file can be added and tracked by git - it won&rsquo;t get changed.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">using</span> System.Reflection;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">using</span> System.Runtime.CompilerServices;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">using</span> System.Runtime.InteropServices;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">[assembly: AssemblyVersion(&#34;0.0.0&#34;)]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">[assembly: AssemblyFileVersion(&#34;0.0.0&#34;)]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">[assembly: AssemblyDescription(&#34;Build: 0, Commit Sha: 0&#34;)]</span>
</span></span></code></pre></div><p>Next install the two gulp modules, and import into your <code>gulpfile</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>npm install gulp-rename --save
</span></span><span style="display:flex;"><span>npm install gulp-dotnet-assembly-info --save
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">rename</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">&#39;gulp-rename&#39;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">assemblyInfo</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">&#39;gulp-dotnet-assembly-info&#39;</span>);
</span></span></code></pre></div><p>In the gulp file, read the <code>package.json</code> file and the environment variables.  I do this once at the begining of my <code>gulpfile</code> and use the config all over the place.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">project</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">parse</span>(<span style="color:#a6e22e">fs</span>.<span style="color:#a6e22e">readFileSync</span>(<span style="color:#e6db74">&#34;./package.json&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">config</span> <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">name</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">project</span>.<span style="color:#a6e22e">name</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">version</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">project</span>.<span style="color:#a6e22e">version</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">commit</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">APPVEYOR_REPO_COMMIT</span> <span style="color:#f92672">||</span> <span style="color:#e6db74">&#34;0&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">buildNumber</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">APPVEYOR_BUILD_VERSION</span> <span style="color:#f92672">||</span> <span style="color:#e6db74">&#34;0&#34;</span>,
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Then add a task to create a new <code>AssemblyVersion.cs</code> file.  Change the <code>src</code> parameter to match where you saved the <code>AssemblyVersion.base</code> file.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">gulp</span>.<span style="color:#a6e22e">task</span>(<span style="color:#e6db74">&#39;version&#39;</span>, <span style="color:#66d9ef">function</span>() {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">gulp</span>
</span></span><span style="display:flex;"><span>    .<span style="color:#a6e22e">src</span>(<span style="color:#a6e22e">config</span>.<span style="color:#a6e22e">name</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;/Properties/AssemblyVersion.base&#39;</span>)
</span></span><span style="display:flex;"><span>    .<span style="color:#a6e22e">pipe</span>(<span style="color:#a6e22e">rename</span>(<span style="color:#e6db74">&#34;AssemblyVersion.cs&#34;</span>))
</span></span><span style="display:flex;"><span>    .<span style="color:#a6e22e">pipe</span>(<span style="color:#a6e22e">assemblyInfo</span>({
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">version</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">config</span>.<span style="color:#a6e22e">version</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">fileVersion</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">config</span>.<span style="color:#a6e22e">version</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">description</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;Build: &#34;</span> <span style="color:#f92672">+</span>  <span style="color:#a6e22e">config</span>.<span style="color:#a6e22e">buildNumber</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;, Sha: &#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">config</span>.<span style="color:#a6e22e">commit</span>
</span></span><span style="display:flex;"><span>    }))
</span></span><span style="display:flex;"><span>    .<span style="color:#a6e22e">pipe</span>(<span style="color:#a6e22e">gulp</span>.<span style="color:#a6e22e">dest</span>(<span style="color:#e6db74">&#39;./&#39;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">config</span>.<span style="color:#a6e22e">name</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;/Properties&#39;</span>));
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>Don&rsquo;t forget to reference the <code>AssemblyVersion.cs</code> file in your csproj!</p>
<p>You can see a full <code>gulpfile</code> with this in here: <a href="https://github.com/Pondidum/Magistrate/blob/master/gulpfile.js">Magistrate gulpfile</a>.</p>
]]></content:encoded></item><item><title>Posting PlainText to Asp WebApi</title><link>https://andydote.co.uk/2015/09/21/webapi-post-plaintext/</link><pubDate>Mon, 21 Sep 2015 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2015/09/21/webapi-post-plaintext/</guid><description>Recently I have been writing a WebApi project which needs to accept plaintext via the body of a PUT request, and did the logical thing of using the FromBodyAttribute
public HttpStatusCode PutKv([FromBody]string content, string keyGreedy) { return HttpStatusCode.OK; } Which didn&amp;rsquo;t work, with the useful error message of &amp;ldquo;Unsupported media type.&amp;rdquo;
It turns out that to bind a value type with the FromBody attribute, you have to prefix the body of your request with an =.</description><content:encoded><![CDATA[<p>Recently I have been writing a WebApi project which needs to accept plaintext via the body of a PUT request, and did the logical thing of using the <code>FromBodyAttribute</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> HttpStatusCode PutKv([FromBody]<span style="color:#66d9ef">string</span> content, <span style="color:#66d9ef">string</span> keyGreedy)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> HttpStatusCode.OK;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Which didn&rsquo;t work, with the useful error message of &ldquo;Unsupported media type.&rdquo;</p>
<p>It turns out that to bind a value type with the <code>FromBody</code> attribute, you have to prefix the body of your request with an <code>=</code>.  As I am emulating another Api&rsquo;s interface, this is not an option, so I set about figuring out how to override this requirement.</p>
<p>In the end I discovered that providing a new <code>MediaTypeFormatter</code> which handles plaintext is the answer:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PlainTextMediaTypeFormatter</span> : MediaTypeFormatter
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> PlainTextMediaTypeFormatter()
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    SupportedMediaTypes.Add(<span style="color:#66d9ef">new</span> MediaTypeHeaderValue(<span style="color:#e6db74">&#34;text/plain&#34;</span>));
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> Task&lt;<span style="color:#66d9ef">object</span>&gt; ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> source = <span style="color:#66d9ef">new</span> TaskCompletionSource&lt;<span style="color:#66d9ef">object</span>&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">try</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> memoryStream = <span style="color:#66d9ef">new</span> MemoryStream())
</span></span><span style="display:flex;"><span>      {
</span></span><span style="display:flex;"><span>        readStream.CopyTo(memoryStream);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> text = Encoding.UTF8.GetString(memoryStream.ToArray());
</span></span><span style="display:flex;"><span>        source.SetResult(text);
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">catch</span> (Exception e)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      source.SetException(e);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> source.Task;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> Task WriteToStreamAsync(Type type, <span style="color:#66d9ef">object</span> <span style="color:#66d9ef">value</span>, Stream writeStream, HttpContent content, System.Net.TransportContext transportContext, System.Threading.CancellationToken cancellationToken)
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> bytes = Encoding.UTF8.GetBytes(<span style="color:#66d9ef">value</span>.ToString());
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> writeStream.WriteAsync(bytes, <span style="color:#ae81ff">0</span>, bytes.Length, cancellationToken);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">bool</span> CanReadType(Type type)
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> type == <span style="color:#66d9ef">typeof</span>(<span style="color:#66d9ef">string</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">bool</span> CanWriteType(Type type)
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> type == <span style="color:#66d9ef">typeof</span>(<span style="color:#66d9ef">string</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This can then be added to the <code>config.Formatters</code> collection:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">WebApiConfig</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> Register(HttpConfiguration http)
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    http.Formatters.Add(<span style="color:#66d9ef">new</span> PlainTextMediaTypeFormatter());
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>It really seems like something which should be supplied out of the box with WebApi to me, but at least it wasn&rsquo;t as complicated to implement as I was expecting it to be :)</p>
]]></content:encoded></item><item><title>Running pre-compiled microservices in Docker with Mono</title><link>https://andydote.co.uk/2015/09/15/pre-compiled-microservices/</link><pubDate>Tue, 15 Sep 2015 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2015/09/15/pre-compiled-microservices/</guid><description>Last time we went through creating a Dockerfile for a microservice, with the service being compiled on creation of the container image, using xbuild.
However we might not want to compile the application to create the container image, and use an existing version (e.g. one created by a build server.)
Our original Dockerfile was this:
FROM mono:3.10-onbuild RUN apt-get update &amp;amp;&amp;amp; apt-get install mono-4.0-service -y CMD [ &amp;#34;mono-service&amp;#34;, &amp;#34;./MicroServiceDemo.exe&amp;#34;, &amp;#34;--no-daemon&amp;#34; ] EXPOSE 12345 We only need to make a few modifications to use a pre-compiled application:</description><content:encoded><![CDATA[<p>Last time we went through <a href="/2015/09/05/running-microservices-in-docker-with-mono.html">creating a Dockerfile for a microservice</a>, with the service being compiled on creation of the container image, using xbuild.</p>
<p>However we might not want to compile the application to create the container image, and use an existing version (e.g. one created by a build server.)</p>
<p>Our original Dockerfile was this:</p>
<pre tabindex="0"><code>FROM mono:3.10-onbuild
RUN apt-get update &amp;&amp; apt-get install mono-4.0-service -y

CMD [ &#34;mono-service&#34;,  &#34;./MicroServiceDemo.exe&#34;, &#34;--no-daemon&#34; ]
EXPOSE 12345
</code></pre><p>We only need to make a few modifications to use a pre-compiled application:</p>
<pre tabindex="0"><code>FROM mono:3.10.0
RUN apt-get update &amp;&amp; apt-get install mono-4.0-service -y

RUN mkdir -p /usr/src/app
COPY . /usr/src/app
WORKDIR /usr/src/app

CMD [ &#34;mono-service&#34;,  &#34;./MicroServiceDemo.exe&#34;, &#34;--no-daemon&#34; ]
EXPOSE 12345
</code></pre><p>Asides from changing the base image to <code>mono:3.10.0</code>, the only changes made are to add the following lines:</p>
<pre tabindex="0"><code>RUN mkdir -p /usr/src/app
COPY . /usr/src/app
WORKDIR /usr/src/app
</code></pre><p>These lines create a new directory for our application, copy the contents of the current directory (e.g. the paths specified when you type <code>docker build -t servicedemo .</code>) and make the directory our working directory.</p>
<p>You can now create a container with the same commands as last time:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker build -t servicedemo .
</span></span><span style="display:flex;"><span>docker run -d -p 12345:12345 --name demo servicedemo
</span></span></code></pre></div><p>There is a demo project for all of this on my github: <a href="https://github.com/Pondidum/DockerMonoDemo">DockerMonoDemo</a>.</p>
]]></content:encoded></item><item><title>Running microservices in Docker with Mono</title><link>https://andydote.co.uk/2015/09/05/running-microservices-in-docker-with-mono/</link><pubDate>Sat, 05 Sep 2015 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2015/09/05/running-microservices-in-docker-with-mono/</guid><description>Getting a service running under Docker is fairly straight forward once you have all the working parts together. I have an app written (following my guide on service and console in one), which uses Owin to serve a web page as a demo:
install-package Microsoft.Owin.SelfHost public partial class Service : ServiceBase { //see the service console post for the rest of this protected override void OnStart(string[] args) { _app = WebApp.</description><content:encoded><![CDATA[<p>Getting a service running under <a href="https://www.docker.com">Docker</a> is fairly straight forward once you have all the working parts together.  I have an app written (following <a href="/2015/08/30/single-project-service-and-console.html">my guide</a> on service and console in one), which uses Owin to serve a web page as a demo:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>install-package Microsoft.Owin.SelfHost
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">partial</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Service</span> : ServiceBase
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">//see the service console post for the rest of this</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> OnStart(<span style="color:#66d9ef">string</span>[] args)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_app = WebApp.Start(<span style="color:#e6db74">&#34;http://*:12345&#34;</span>, app =&gt;
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			app.UseWelcomePage(<span style="color:#e6db74">&#34;/&#34;</span>);
</span></span><span style="display:flex;"><span>		});
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> OnStop()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_app.Dispose();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>To run this under docker/mono we just need to add a <code>Dockerfile</code> to the root directory of the solution, which is based off the <a href="https://hub.docker.com/_/mono">documentation here</a>.</p>
<p>Using <code>mono-service</code> instead of <code>mono</code> to run the application caused me a number of headaches to start with, as the container was exiting instantly.  This is because Docker detects the process has exited, and stops the container.  As we will be running the container detached from the console, we just need to supply the <code>--no-daemon</code> argument to <code>mono-service</code>.</p>
<pre tabindex="0"><code>FROM mono:3.10-onbuild
RUN apt-get update &amp;&amp; apt-get install mono-4.0-service -y
CMD [ &#34;mono-service&#34;,  &#34;./MicroServiceDemo.exe&#34;, &#34;--no-daemon&#34; ]
EXPOSE 12345
</code></pre><p>You can then go to your solution directory, and run the following two commands to create your image, and start a container of it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker build -t servicedemo .
</span></span><span style="display:flex;"><span>docker run -d -p 12345:12345 --name demo servicedemo
</span></span></code></pre></div><p>You can now open your browser and go to your Docker host&rsquo;s IP:12345 and see the Owin welcome page.</p>
<h2 id="improvements-speed-and-lack-of-internet">Improvements: Speed and lack of internet</h2>
<p>Quite often I have no internet access, so having to <code>apt-get install mono-4.0-service</code> each time I build the image can be a pain.  This however is also very easily resolved: by making another image with the package already installed.</p>
<p>Create a new directory (outside of your project directory), and create a <code>Dockerfile</code>.  This Dockerfile is identical to the <a href="https://github.com/mono/docker/blob/adc7a3ec47f7d590f75a4dec0203a2103daf8db0/3.10.0/onbuild/Dockerfile">mono:3.10-onbuild</a> image, but with the added apt-get line.</p>
<pre tabindex="0"><code>FROM mono:3.10.0

MAINTAINER Jo Shields &lt;jo.shields@xamarin.com&gt;

RUN apt-get update &amp;&amp; apt-get install mono-4.0-service -y

RUN mkdir -p /usr/src/app/source /usr/src/app/build
WORKDIR /usr/src/app/source

ONBUILD COPY . /usr/src/app/source
ONBUILD RUN nuget restore -NonInteractive
ONBUILD RUN xbuild /property:Configuration=Release /property:OutDir=/usr/src/app/build/
ONBUILD WORKDIR /usr/src/app/build
</code></pre><p>Now run the build command to make your new base image:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker build -t mono-service-onbuild .
</span></span></code></pre></div><p>Now you can go back to your project and update the <code>Dockerfile</code> to use this image base instead:</p>
<pre tabindex="0"><code>FROM mono-service-onbuild
CMD [ &#34;mono-service&#34;,  &#34;./MicroServiceDemo.exe&#34;, &#34;--no-daemon&#34; ]
EXPOSE 12345
</code></pre><p>Now when you run <code>docker build -t &lt;project name&gt; .</code> it will only need to do the compile steps.</p>
<p>Much faster :)</p>
]]></content:encoded></item><item><title>A single project Windows Service and Console</title><link>https://andydote.co.uk/2015/08/30/single-project-service-and-console/</link><pubDate>Sun, 30 Aug 2015 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2015/08/30/single-project-service-and-console/</guid><description>I have found that when developing MicroServices, I often want to run them from within Visual Studio, or just as a console application, and not have to bother with the hassle of installing as windows services.
In the past I have seen this achieved by creating a Class Library project with all the actual implementation inside it, and then both a Console Application and Windows Service project referencing the library and doing nothing other than calling a .</description><content:encoded><![CDATA[<p>I have found that when developing MicroServices, I often want to run them from within Visual Studio, or just as a console application, and not have to bother with the hassle of installing as windows services.</p>
<p>In the past I have seen this achieved by creating a <code>Class Library</code> project with all the actual implementation inside it, and then both a <code>Console Application</code> and <code>Windows Service</code> project referencing the library and doing nothing other than calling a <code>.Start()</code> method or similar.</p>
<p>While this works, it has always bugged me as there should be a straight forward way of achieving a single exe to do both roles.  It turns out there is an easy way to do it too&hellip;</p>
<h2 id="creating-the-project">Creating the Project</h2>
<p>First, create a <code>WindowsService</code> project in VisualStudio:
<img loading="lazy" src="service-new.png" alt="New Windows Service"  />
</p>
<p>Then open the project properties, and change the project type to <code>Console Application</code> and set the startup object:
<img loading="lazy" src="service-project-type.png" alt="Service Type"  />
</p>
<p>Next, open <code>Service1.cs</code> and add a new method (and rename it to <code>Service</code> if you feel the need!):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> StartConsole()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	Console.WriteLine(<span style="color:#e6db74">&#34;Press any key to exit...&#34;</span>);
</span></span><span style="display:flex;"><span>	OnStart(<span style="color:#66d9ef">new</span> <span style="color:#66d9ef">string</span>[] { });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	Console.ReadKey();
</span></span><span style="display:flex;"><span>	OnStop();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Finally  open <code>Program.cs</code> and replace the <code>Main</code> method:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> Main()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> service = <span style="color:#66d9ef">new</span> Service();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> (Environment.UserInteractive)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		service.StartConsole();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		ServiceBase.Run(<span style="color:#66d9ef">new</span> ServiceBase[] { service });
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="displaying-output">Displaying Output</h2>
<p>Calling <code>Console.Write*</code> and <code>Console.Read*</code> methods when running as a windows service will cause exceptions to be thrown, which suggest that you should redirect the console streams to use them under a windows service.</p>
<p>As a MicroService you shouldn&rsquo;t need to be reading keys from the console (other than the one in our <code>StartConsole</code> method), but writing output would be useful&hellip;</p>
<p>To do this I like to use my logging library of choice (<a href="http://serilog.net/">Serilog</a>), which I have setup to write to files and to a console:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> InitializeLogging()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> logs = Path.Combine(baseDirectory, <span style="color:#e6db74">&#34;logs&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	Directory.CreateDirectory(logs);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	Log.Logger = <span style="color:#66d9ef">new</span> LoggerConfiguration()
</span></span><span style="display:flex;"><span>		.MinimumLevel.Debug()
</span></span><span style="display:flex;"><span>		.WriteTo.ColoredConsole()
</span></span><span style="display:flex;"><span>		.WriteTo.RollingFile(Path.Combine(logs, <span style="color:#e6db74">&#34;{Date}.log&#34;</span>))
</span></span><span style="display:flex;"><span>		.CreateLogger();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And call this method inside the <code>Service1</code> constructor:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> Service()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	InitializeComponent();
</span></span><span style="display:flex;"><span>	InitializeLogging();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="the-edge-case">The Edge Case</h2>
<p>There is one slight edge case which I am aware of, which is that the <code>Environment.UserInteractive </code> property can return true even when running as a windows service if when you install the service you tick <code>Allow service to interact with desktop</code> checkbox:</p>
<p><img loading="lazy" src="service-interact.png" alt="Service-Logon"  />
</p>
<p>My only solution to this is: <strong>Don&rsquo;t tick that box</strong>. I don&rsquo;t think I have ever used that option anyway!</p>
<h2 id="wrapping-up">Wrapping Up</h2>
<p>Using this method means less code and projects to maintain, and a very easy path to go from running a service as a desktop application to service.</p>
]]></content:encoded></item><item><title>Don't Let The Database Dictate Your Design</title><link>https://andydote.co.uk/2015/04/01/dont-let-the-database-dictate-your-design/</link><pubDate>Wed, 01 Apr 2015 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2015/04/01/dont-let-the-database-dictate-your-design/</guid><description>I have been thinking recently about how the database can influence our design decisions, and perhaps makes them harder than they need to be in some cases. An example of this is the design of a system which stores data about people, specifically for this, their email addresses. A cut down version of the structure is this:
table people id serial primary key firstname varchar(50) lastname varchar(50) table emails id serial primary key person_id int =&amp;gt; people.</description><content:encoded><![CDATA[<p>I have been thinking recently about how the database can influence our design decisions, and perhaps makes them harder than they need to be in some cases.  An example of this is the design of a system which stores data about people, specifically for this, their email addresses.  A cut down version of the structure is this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">table</span> people
</span></span><span style="display:flex;"><span>id serial <span style="color:#66d9ef">primary</span> <span style="color:#66d9ef">key</span>
</span></span><span style="display:flex;"><span>firstname varchar(<span style="color:#ae81ff">50</span>)
</span></span><span style="display:flex;"><span>lastname varchar(<span style="color:#ae81ff">50</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">table</span> emails
</span></span><span style="display:flex;"><span>id serial <span style="color:#66d9ef">primary</span> <span style="color:#66d9ef">key</span>
</span></span><span style="display:flex;"><span>person_id int <span style="color:#f92672">=&gt;</span> people.id
</span></span><span style="display:flex;"><span>address varchar(<span style="color:#ae81ff">100</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> int
</span></span></code></pre></div><p>Which is represented in code like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Person</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> ID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> FirstName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> LastName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> List&lt;Email&gt; Emails { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Person()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		Emails = <span style="color:#66d9ef">new</span> List&lt;Email&gt;();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Email</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> ID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> PersonID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> Address { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> EmailTypes Type { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>While this works, it is heavily influenced by the storage technology.  Email addresses by definition are unique already, so why do we need a primary key column? They are also associated with exactly one person, so the <code>person_id</code> column is only here to facilitate that.  Why not get rid of the emails table completely, and store the person&rsquo;s email addresses in a single column in the person table?  This could be done with a simple csv, but it would be more fore-thinking to use json, so we can associate a little more data with each email address.</p>
<p>So before we get on to putting data in one column, what reasons we have to keep emails as a separate table?</p>
<ul>
<li>So they can be queried by ID.</li>
<li>So we can put a constraint across <code>[person_id, address]</code> and <code>[person_id, type]</code>.</li>
<li>So all emails of a given type can be found.</li>
<li>So a person can be looked up by email.</li>
<li>So we can attach rules to them.</li>
</ul>
<p>The first three can be answered easily: you never query for an email address by its primary key, only by the address itself.  The constraints are really just a safety net, and a nice to have at best - the collection which manages emails is well tested, implements all business rules properly, and everything which deals with emails uses it.  Getting all emails of a particular type is a legitamate requirement, but can be gotten around in several ways: selecting the entire email column in a sql query, and doing additional filtering client side for the specific email types, or if you are using a database which supports json querying (such as postgres), using that to narrow the results down.</p>
<p>The final point is the most interesting, as it could be resolved with a few different designs.  The current design has one additional table:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">table</span> rules
</span></span><span style="display:flex;"><span>id serial <span style="color:#66d9ef">primary</span> <span style="color:#66d9ef">key</span>
</span></span><span style="display:flex;"><span>person_id int <span style="color:#f92672">=&gt;</span> people.id
</span></span><span style="display:flex;"><span>target_type int <span style="color:#75715e">--e.g 1=email, 2=phone, 3=address etc
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>target_id int
</span></span><span style="display:flex;"><span>active bool
</span></span></code></pre></div><p>And the <code>Person</code> object has a method like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">bool</span> HasRuleInForce(Entity target)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> Rules
</span></span><span style="display:flex;"><span>		.Where(rule =&gt; rule.TargetType == target.Type)
</span></span><span style="display:flex;"><span>		.Where(rule =&gt; rule.TargetID == target.ID)
</span></span><span style="display:flex;"><span>		.Where(rule =&gt; rule.Active)
</span></span><span style="display:flex;"><span>		.Any();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>While this works, the design has a few problems:</p>
<ul>
<li>There is no foreign keying of <code>rules.target_id</code> available</li>
<li>So you have to remember to delete rules when deleting any entity</li>
<li>You have to remember if an entity is valid for rules to be attached to</li>
<li>If normalisation was your argument for an <code>emails</code> table, explain this table relationship&hellip;</li>
</ul>
<p>There are two solutions to this problem:</p>
<p>The first is to change the rules table to just have a <code>target</code> column, and put the unique data in there e.g. a rule for an email would have the email address in the <code>target</code> column, a rule for a phone number would have the actual phone number in the <code>target</code> column.  While this works, it doesn&rsquo;t really improve the design of the system; we still have the existing joins and &ldquo;remember to also&rdquo; problems of before.</p>
<p>The second solution is to remove the <code>rules</code> table entirely and implement rules as small collections on each target entity, and make the <code>person.Rules</code> property a readonly aggregate.  This has a few advantages: each entity explicitly has a rule collection if applicable, and we no longer need to remember to check another collection for updates/deletes.</p>
<p>The implementation of a <code>.Rules</code> property on each entity is trivial - just a standard list property:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Email</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> ID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> PersonID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> Address { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> EmailTypes Type { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> List&lt;Rule&gt; Rules { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As we don&rsquo;t wish to repeat the logic on each collection of rules, we can add an extension method for checking if rules are in force:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">RulesExtensions</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">bool</span> HasRuleInForce(<span style="color:#66d9ef">this</span> IEnumerable&lt;Rule&gt; self)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> self.Any(rule =&gt; rule.Active);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And finally on the <code>Person</code> object itself, we can make a simple aggregate property for all child entity&rsquo;s rules:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> IEnumerable&lt;Rule&gt; Rules
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">get</span>
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> all = <span style="color:#66d9ef">new</span>[]
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			Emails.SelectMany(e =&gt; e.Rules),
</span></span><span style="display:flex;"><span>			Phones.SelectMany(p =&gt; p.Rules),
</span></span><span style="display:flex;"><span>		};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> all.SelectMany(r =&gt; r);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Personally I prefer the 2nd form of this, as it makes domain modelling a lot more straight forward - however like all things, you should consider all your requirements carefully - and don&rsquo;t let the database (sql or nosql variety) dictate your model.</p>
]]></content:encoded></item><item><title>The problems with and solutions to Repositories</title><link>https://andydote.co.uk/2015/03/28/problems-with-and-solutions-to-repositories/</link><pubDate>Sat, 28 Mar 2015 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2015/03/28/problems-with-and-solutions-to-repositories/</guid><description>Repositories are a design pattern which I have never been a huge fan of. I can see the use of them as a good layer boundary, but too often I see them being used all over the place instead of at an infrastructure level in a code base.
A particularly prevalent version of this misuse I see is self populating collections. These generally inherit List&amp;lt;TEntity&amp;gt; or Dictionary&amp;lt;TID, TEntity&amp;gt;, and provide a set of methods such as .</description><content:encoded><![CDATA[<p>Repositories are a design pattern which I have never been a huge fan of.  I can see the use of them as a good layer boundary, but too often I see them being used all over the place instead of at an infrastructure level in a code base.</p>
<p>A particularly prevalent version of this misuse I see is self populating collections.  These generally inherit <code>List&lt;TEntity&gt;</code> or <code>Dictionary&lt;TID, TEntity&gt;</code>, and provide a set of methods such as <code>.LoadByParentID(TID id)</code>.  The problem with this is that the collection still exposes methods such as <code>.Add()</code> and <code>.Remove()</code> - but these operations only run on the in-memory entities, and don&rsquo;t effect the data source itself.</p>
<h2 id="the-alternative">The Alternative</h2>
<p>The technique I prefer for reads are Query objects.  These are simple classes which expose a single public method to return some data.  For example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">GetDocumentsWaitingQuery</span> : IDocumentsQuery
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IDataStore _dataStore;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> GetDocumentsWaitingQuery(IDataStore datastore)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_dataStore = datastore;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> IEnumerable&lt;Document&gt; Execute()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> connection = _dataStore.Open())
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span> connection
</span></span><span style="display:flex;"><span>				.Query&lt;Document&gt;(
</span></span><span style="display:flex;"><span>					<span style="color:#e6db74">&#34;select * from documents where status == @status&#34;</span>,
</span></span><span style="display:flex;"><span>					<span style="color:#66d9ef">new</span> { status = DocumentStatuses.Waiting})
</span></span><span style="display:flex;"><span>				.ToList();
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The code using this class might look something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">DocumentProcessor</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IDocumentsQuery _query;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> DocumentProcessor(IDocumentsQuery waitingDocumentsQuery)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_query = waitingDocumentsQuery;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Run()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">foreach</span> (<span style="color:#66d9ef">var</span> document <span style="color:#66d9ef">in</span> _query.Execute())
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#75715e">//some operation on document...</span>
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This class is almost too simple, but resembles a system&rsquo;s processor which I wrote.  They key here is that the <code>DocumentProcessor</code> only relies on an <code>IDocumentsQuery</code>, not a specific query.</p>
<p>Normal usage of the system looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> ProcessAll()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> query = <span style="color:#66d9ef">new</span> GetDocumentsWaitingQuery(_dataStore);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> saveCommand = <span style="color:#66d9ef">new</span> SaveDocumentCommand(_dataStore);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> processor = <span style="color:#66d9ef">new</span> DocumentProcessor(query, saveCommand);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	processor.Run();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>When the user requests a single document get reprocessed, we just substitute in a different Query:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> query = <span style="color:#66d9ef">new</span> GetDocumentByIDQuery(_dataStore, id: <span style="color:#ae81ff">123123</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> saveCommand = <span style="color:#66d9ef">new</span> SaveDocumentCommand(_dataStore);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> processor = <span style="color:#66d9ef">new</span> DocumentProcessor(query, saveCommand);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>processor.Run();
</span></span></code></pre></div><p>And finally, when the system is under test, we can pass in completely fake commands:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#a6e22e">[Fact]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> When_multiple_documents_for_the_same_user()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> first = <span style="color:#66d9ef">new</span> Document { .UserID = <span style="color:#ae81ff">1234</span>, .Name = <span style="color:#e6db74">&#34;Document One&#34;</span> };
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> second = <span style="color:#66d9ef">new</span> Document { .UserID = <span style="color:#ae81ff">1234</span>, .Name = <span style="color:#e6db74">&#34;Document Two&#34;</span> };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> query = Substitute.For&lt;IDocumentsQuery&gt;();
</span></span><span style="display:flex;"><span>	query.Execute().Returns(<span style="color:#66d9ef">new</span>[] {first, second});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> processor = <span style="color:#66d9ef">new</span> DocumentProcessor(query, Substitute.For&lt;ISaveDocumentCommand&gt;());
</span></span><span style="display:flex;"><span>	processor.Run();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	first.Primary.ShouldBe(<span style="color:#66d9ef">true</span>);
</span></span><span style="display:flex;"><span>	second.Primary.ShouldBe(<span style="color:#66d9ef">false</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This means that in the standard usage, it gets passed an instance of <code>GetDocumentsWaitingQuery</code>, but when under test gets a <code>Substitute.For&lt;IDocumentsQuery&gt;()</code>, and for debugging a problem with a specific document, it gets given <code>new GetSingleDocumentQuery(id: 234234)</code> for example.</p>
<h2 id="commands">Commands</h2>
<p>What about saving?  Well it&rsquo;s pretty much the same story:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">SaveDocumentCommand</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IDataStore datastore;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> SaveDocumentCommand(IDataStore datastore)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_dataStore = datastore
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Execute(Document document)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> connection = _dataStore.Open())
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			connection.Execute(<span style="color:#e6db74">&#34;update documents set status = @status where id = @id&#34;</span>, document);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Obviously the sql in the save command would be a bit more complete&hellip;</p>
<h2 id="but-repositories">But Repositories&hellip;</h2>
<p>Well yes, you can create methods on your repositories to do all of this, like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> IDocumentRepository
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> SaveDocument(Document document) { <span style="color:#75715e">/* ... */</span> }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> IEnumerable&lt;Document&gt; GetDocumentsWaiting() { <span style="color:#75715e">/* ... */</span> }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>But now your classes utilising this repository are tied to the methods it implements - you cannot just swap out the workings of <code>.GetDocumentsWaiting</code> for a single document query any more.</p>
<p>This is why I like to use Command and Query objects - the not only provide good encapsulation (all your sql is contained within), but they also provide a large level of flexibility in your system, and make it very easy to test to boot too!</p>
]]></content:encoded></item><item><title>Communicating Intent in APIs</title><link>https://andydote.co.uk/2015/03/25/communicating-intent-in-apis/</link><pubDate>Wed, 25 Mar 2015 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2015/03/25/communicating-intent-in-apis/</guid><description>Recently was trying to work out how to allow custom resources to be specified in Dashen. I already know what data is needed/defined for a resource: a name, a MIME type, and a Stream. We can make this required data known very easily:
public class Resource { public string Name { get; private set; } public string MimeType { get; private set; } public Stream Content { get; private set; } public Resource(string name, string mimeType, Stream content) { Name = name; MimeType = mimeType; Content = content; } } As all the parameters can only be set through the constructor, you are communicating that they are all required.</description><content:encoded><![CDATA[<p>Recently was trying to work out how to allow custom resources to be specified in <a href="https://github.com/pondidum/Dashen">Dashen</a>.  I already know what data is needed/defined for a resource: a name, a MIME type, and a Stream.  We can make this required data known very easily:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Resource</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> Name { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> MimeType { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Stream Content { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Resource(<span style="color:#66d9ef">string</span> name, <span style="color:#66d9ef">string</span> mimeType, Stream content)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		Name = name;
</span></span><span style="display:flex;"><span>		MimeType = mimeType;
</span></span><span style="display:flex;"><span>		Content = content;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As all the parameters can only be set through the constructor, you are communicating that they are all required.</p>
<p>However when it comes to adding this <code>Resource</code> into our configuration, we are met with 3 possible solutions:</p>
<h2 id="resource-collection-on-the-config">Resource collection on the config</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> dashboard = DashboardBuilder.Create(<span style="color:#66d9ef">new</span> DashboardConfiguration
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	ListenOn = <span style="color:#66d9ef">new</span> Uri(<span style="color:#e6db74">&#34;http://localhost:3030&#34;</span>),
</span></span><span style="display:flex;"><span>	Resources = <span style="color:#66d9ef">new</span>[] { <span style="color:#66d9ef">new</span> Resource(<span style="color:#e6db74">&#34;test.png&#34;</span>, <span style="color:#e6db74">&#34;image/png&#34;</span>, <span style="color:#66d9ef">new</span> FileStrea(...))}
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>As the <code>DashboardConfiguration</code> object is only used in this one call, it implies that the contents of it only get read once.
Nothing to stop you holding on to a reference to the <code>Resources</code> collection though.</p>
<h2 id="addresource-method-on-the-config">AddResource method on the config</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> config = <span style="color:#66d9ef">new</span> DashboardConfiguration
</span></span><span style="display:flex;"><span>config.ListenOn = <span style="color:#66d9ef">new</span> Uri(<span style="color:#e6db74">&#34;http://localhost:3030&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>config.AddResource(<span style="color:#66d9ef">new</span> Resource(<span style="color:#e6db74">&#34;test.png&#34;</span>, <span style="color:#e6db74">&#34;image/png&#34;</span>, <span style="color:#66d9ef">new</span> FileStrea(...)));
</span></span><span style="display:flex;"><span><span style="color:#75715e">//or</span>
</span></span><span style="display:flex;"><span>config.AddResource(<span style="color:#e6db74">&#34;test.png&#34;</span>, <span style="color:#e6db74">&#34;image/png&#34;</span>, <span style="color:#66d9ef">new</span> FileStrea(...));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> dashboard = DashboardBuilder.Create(config);
</span></span></code></pre></div><p><code>Resources</code> are still added to the <code>DashboardConfiguration</code>, but this time via a method.  This hides the internal storage of resources.  Second version also means we can hide the <code>Resource</code> class from the public too if we want.
Also implies a level of uniqueness - could throw an exception on duplicate name being added, or rename the method to <code>AddUniqueResource</code> or similar.</p>
<h2 id="addresource-method-on-the-dashboard">AddResource method on the Dashboard</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> dashboard = DashboardBuilder.Create(<span style="color:#66d9ef">new</span> DashboardConfiguration
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	ListenOn = <span style="color:#66d9ef">new</span> Uri(<span style="color:#e6db74">&#34;http://localhost:3030&#34;</span>),
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>dashboard.AddResource(<span style="color:#66d9ef">new</span> Resource(<span style="color:#e6db74">&#34;test.png&#34;</span>, <span style="color:#e6db74">&#34;image/png&#34;</span>, <span style="color:#66d9ef">new</span> FileStrea(...)));
</span></span><span style="display:flex;"><span><span style="color:#75715e">//or</span>
</span></span><span style="display:flex;"><span>dashboard.AddResource(<span style="color:#e6db74">&#34;test.png&#34;</span>, <span style="color:#e6db74">&#34;image/png&#34;</span>, <span style="color:#66d9ef">new</span> FileStrea(...));
</span></span></code></pre></div><p><code>Resource</code> class is still hideable. Being able to add to the dashboard rather than the config implies that resources could be added at anytime, rather than just startup/config time.</p>
<h1 id="selected-solution">Selected Solution</h1>
<p>In the end I decided to expose the <code>Resources</code> as an <code>IEnumerable&lt;Resource&gt;</code> on the <code>DashboardConfiguration</code> object.  I did this as I don&rsquo;t actually mind if the collection gets modified once the dashboard is started, and I can see some use-cases for dynamic resource resolution.</p>
]]></content:encoded></item><item><title>Encapsulation in Warcraft Addons - Inheritance</title><link>https://andydote.co.uk/2014/12/05/encapsulation-in-warcraft-addons-inheritance/</link><pubDate>Fri, 05 Dec 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/12/05/encapsulation-in-warcraft-addons-inheritance/</guid><description>Using Inheritance (sort of) When we actually need inheritance, things get a little more complicated. We need to use two of lua&amp;rsquo;s slightly harder features to get it to work: metatables and colon notation. A little background on these will help:
MetaTables All &amp;ldquo;objects&amp;rdquo; in lua are tables, and tables can something called a metatable added to them. Metatables can have special methods on them which run under certain circumstances (called metamethods), such as keys being added.</description><content:encoded><![CDATA[<h2 id="using-inheritance-sort-of">Using Inheritance (sort of)</h2>
<p>When we actually need inheritance, things get a little more complicated.  We need to use two of lua&rsquo;s slightly harder features to get it to work: <code>metatables</code> and <code>colon notation</code>.  A little background on these will help:</p>
<h3 id="metatables">MetaTables</h3>
<p>All &ldquo;objects&rdquo; in lua are tables, and tables can something called a metatable added to them.  Metatables can have special methods on them which run under certain circumstances (called metamethods), such as keys being added.  A full list of metamethods is <a href="http://lua-users.org/wiki/MetatableEvents">available here</a>.</p>
<p>The metamethod we are interested in is called called <code>__index</code>, which gets triggered when a key is not found in the table.</p>
<p>There are two ways of using <code>__index</code>.  The first is to assign it a function, which gets passed two arguments: <code>table</code>, and <code>key</code>.  This is useful if you want to provide a default value if a key in a table isn&rsquo;t found, which I use in the <code>spellData</code> example <a href="http://andydote.co.uk/2014/11/28/encapsulation-in-warcraft-addons-closures.html">in the previous post</a>.</p>
<p>The other way of using <code>__index</code> is to pass it another table of methods to call, like in this example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> meta <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>	print <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>()
</span></span><span style="display:flex;"><span>		print(<span style="color:#e6db74">&#34;Hi from the metatable&#34;</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> actual <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>	test <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>()
</span></span><span style="display:flex;"><span>		print(<span style="color:#e6db74">&#34;testing&#34;</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--wont work:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- actual.print()</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>setmetatable(actual, { __index <span style="color:#f92672">=</span> meta })
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- now it will!</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- actual.print()</span>
</span></span></code></pre></div><p>By calling <code>setmetatable</code> on <code>actual</code>, we provide <code>actual</code> with all the methods on <code>meta</code>.  A table can only have one meta table though, and you might break things by overwriting it (example, don&rsquo;t call <code>setmetatable</code> on a Frame or ActionButton&hellip;)</p>
<h3 id="colon-notation">Colon Notation</h3>
<p>All methods on a table can be called in two ways; with a colon, or with a period.  The colon can be thought of as &ldquo;fill in the first parameter with the table this is being called on&rdquo;.  For example, these two statements are equivalent:</p>
<pre tabindex="0"><code class="language-lua%}" data-lang="lua%}">local x = string.gsub(&#34;hello world&#34;, &#34;hello&#34;, &#34;bye&#34;)
local x = &#34;hello world&#34;:gsub(&#34;hello&#34;, &#34;bye&#34;)
</code></pre><p>In the example above, the signature of <code>gsub</code> is something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> string <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>	gsub <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, searchTerm, replacement)
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">--self is the input string</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The convention used is to call the first parameter <code>self</code>.  We can now use this colon notation with metatables to make our version of inheritance.</p>
<h3 id="combining">Combining</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> base <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>	increase <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self)
</span></span><span style="display:flex;"><span>		self.count <span style="color:#f92672">=</span> self.count <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>	print <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self)
</span></span><span style="display:flex;"><span>		print(<span style="color:#e6db74">&#34;The count is &#34;</span> <span style="color:#f92672">..</span> self.count <span style="color:#f92672">..</span> <span style="color:#e6db74">&#34;.&#34;</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> first <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>	count <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>setmetatable(first, { __index <span style="color:#f92672">=</span> base })
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> second <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>	count <span style="color:#f92672">=</span> <span style="color:#ae81ff">100</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>setmetatable(second, { __index <span style="color:#f92672">=</span> base })
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--usage</span>
</span></span><span style="display:flex;"><span>first:increase()
</span></span><span style="display:flex;"><span>second:increase()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>first:print()		<span style="color:#75715e">-- prints 1</span>
</span></span><span style="display:flex;"><span>first:print()		<span style="color:#75715e">-- prints 101</span>
</span></span></code></pre></div><p>Due to the way the colon operator works, the <code>self</code> parameter is filled in with the table calling the method, not the table the method is defined on.  So calling <code>first:increase()</code> is the same as <code>base.increase(first)</code></p>
<h2 id="usage">Usage</h2>
<p>We can now take these elements, and craft a set of classes designed for reuse.  We start off with our root object (think <code>System.Object</code> if you are from a .net world.)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> class <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	extend <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, this)
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> setmetatable(this, { __index <span style="color:#f92672">=</span> self })
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	new <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, ...)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">local</span> this <span style="color:#f92672">=</span> setmetatable({}, { __index <span style="color:#f92672">=</span> self })
</span></span><span style="display:flex;"><span>		this:ctor(...)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> this
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	ctor <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, ...)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We have two methods here, <code>extend</code> and <code>new</code>.  The <code>new</code> method is nice and straight forward - it creates a new table, assigns the meta to be <code>class</code> and calls the <code>ctor</code> method (which is the one you would want to replace in sub classes).</p>
<p>The <code>extend</code> method takes in a new table, and applies and sets the meta to <code>class</code>.  This is what is used to inherit and add new functionality.</p>
<p>For example, in my control library, I have a base class with some common methods:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> control <span style="color:#f92672">=</span> class:extend({
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	size <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, config)
</span></span><span style="display:flex;"><span>		self.frame:SetSize(unpack(config))
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	point <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, config)
</span></span><span style="display:flex;"><span>		self.frame:SetPoint(unpack(config))
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	parent <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, value)
</span></span><span style="display:flex;"><span>		self.frame:SetParent(value)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>})
</span></span></code></pre></div><p>And then many other classes which extend the base, cilling in the <code>ctor</code> method with how to actually create the frame:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> label <span style="color:#f92672">=</span> control:extend({
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	ctor <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, name, parent)
</span></span><span style="display:flex;"><span>		self.frame <span style="color:#f92672">=</span> CreateFrame(<span style="color:#e6db74">&#34;Frame&#34;</span>, name, parent)
</span></span><span style="display:flex;"><span>		self.label <span style="color:#f92672">=</span> self.frame:CreateFontString()
</span></span><span style="display:flex;"><span>		self.label:SetAllPoints(self.frame)
</span></span><span style="display:flex;"><span>		self.label:SetFont(fonts.normal, <span style="color:#ae81ff">12</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>})
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> textbox  <span style="color:#f92672">=</span> control:extend({
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	ctor <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, name, parent)
</span></span><span style="display:flex;"><span>		self.frame <span style="color:#f92672">=</span> CreateFrame(<span style="color:#e6db74">&#34;editbox&#34;</span>, name, parent, <span style="color:#e6db74">&#34;InputBoxTemplate&#34;</span>)
</span></span><span style="display:flex;"><span>		self.frame:SetAutoFocus(<span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>		self.frame:SetFont(fonts.normal, <span style="color:#ae81ff">12</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	text <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, value)
</span></span><span style="display:flex;"><span>		self.frame:SetText(value)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>})
</span></span></code></pre></div><p>Some classes, such as the textbox provide other methods where they make sense.</p>
<h3 id="calling-base-class-methods">Calling Base Class Methods</h3>
<p>If we wish to start overriding a method and then call the original method within, things start to get a lot more complicated.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> class <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>	extend <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, this)
</span></span><span style="display:flex;"><span>		this.base <span style="color:#f92672">=</span> self
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> setmetatable(this, { __index <span style="color:#f92672">=</span> self })
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> child <span style="color:#f92672">=</span> class:extend({
</span></span><span style="display:flex;"><span>	method <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self)
</span></span><span style="display:flex;"><span>		self.name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;child&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>})
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> grandchild <span style="color:#f92672">=</span> child:extend({
</span></span><span style="display:flex;"><span>	method <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self)
</span></span><span style="display:flex;"><span>		self.base:method()
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>})
</span></span></code></pre></div><p>While this looks like it will work, it will cause some strange and hard to debug problems (I know it will, it took me ages to figure out.)</p>
<p>The problem is that when you do <code>self.base:method()</code> you are effectively doing <code>self.base.method(self.base)</code>, which means the base method is referencing the wrong table!</p>
<p>We can solve this, but it requires a certain level of voodoo.  First we need to change our <code>extend</code> method:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span>extend <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, this)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	this.super <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(child)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">local</span> parent <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>			__index <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(_, methodName)
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">function</span>(_, ...)
</span></span><span style="display:flex;"><span>					self[methodName](child, ...)
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> setmetatable({}, parent)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> setmetatable(this, { __index <span style="color:#f92672">=</span> self })
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>This took me far too long to come up with and get working.  Essentially what it does is take all calls, and replace the <code>self</code> parameter with the correct table.</p>
<p>This method has some restrictions, in that you can only go &lsquo;up&rsquo; one level in the class hierarchy, e.g. you cannot do <code>item:super():super():super()</code>.  In practice though, I have never needed to do this.</p>
<p>The entirety of my class file can be found on <a href="https://github.com/Pondidum/Dark/blob/abcaa319ccce1bb448a1e04f1d82b8d24578acbe/class.lua">my github</a>.</p>
<h3 id="problems">Problems</h3>
<p>There are two disadvantages to this method of creating objects.  The first is using a table like this, you can no longer totally hide variables as you could do in the closure version.  The other is the complexity added - especially if you wish to allow base method calling, however in balance, you only need to write the <code>super()</code> functionality once (or use mine!)</p>
<p>When writing addons, I use both methods of encapsulation where they fit best - as like everything else in development the answer to what to use is &ldquo;it depends&rdquo;.</p>
]]></content:encoded></item><item><title>Encapsulation in Warcraft Addons - Closures</title><link>https://andydote.co.uk/2014/11/28/encapsulation-in-warcraft-addons-closures/</link><pubDate>Fri, 28 Nov 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/11/28/encapsulation-in-warcraft-addons-closures/</guid><description>In the last post I alluded to the fact that if you put in a little leg work, you could write well encapsulated objects in lua. There are two main ways to do this; with closures, and with metatables. In this post we will deal with using closures, and in the next post we will cover using metatables.
Using Closures The simplest way to write an object in lua is with a closure to hide all the variables from the outside world.</description><content:encoded><![CDATA[<p>In the <a href="http://andydote.co.uk/2014/11/23/good-design-in-warcraft-addons.html">last post</a> I alluded to the fact that if you put in a little leg work, you could write well encapsulated objects in lua.  There are two main ways to do this; with closures, and with metatables.  In this post we will deal with using closures, and in the next post we will cover using metatables.</p>
<h2 id="using-closures">Using Closures</h2>
<p>The simplest way to write an object in lua is with a <a href="http://en.wikipedia.org/wiki/Closure_(computer_programming)">closure</a>  to hide all the variables from the outside world.  For example, we can write a counter class like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> counter <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	new <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">local</span> count <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">local</span> this <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			increase <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>()
</span></span><span style="display:flex;"><span>				count <span style="color:#f92672">=</span> count <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span> <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			print <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>()
</span></span><span style="display:flex;"><span>				print(<span style="color:#e6db74">&#34;The count is &#34;</span> <span style="color:#f92672">..</span> count <span style="color:#f92672">..</span> <span style="color:#e6db74">&#34;.&#34;</span>)
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> this
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We are using a table to give us a class name, and the closure is the only method on it (called <code>new</code>).  My standard convention is to call the actual object we return <code>this</code>. The <code>this</code> object contains the public surface of our object, in this case two methods called <code>increase()</code> and <code>print()</code>.  You can use the counter like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> first <span style="color:#f92672">=</span> counter.new()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>first.increase()
</span></span><span style="display:flex;"><span>first.print() <span style="color:#75715e">-- prints &#34;The count is 1&#34;</span>
</span></span></code></pre></div><p>By using a closure, we limit the use of the <code>count</code> variable to only methods defined in the body of the function <code>new</code>.  This prevents anyone who uses the class from knowing how it is implemented, which is important as we are now at liberty to change the implementation without affecting our users.</p>
<p>A good example of this technique is in my <a href="https://github.com/Pondidum/Dark.Combat">Dark.Combat</a> addon.  While writing cooldown tracking, I needed to know how many stacks of Maelstrom Weapon was the maximum, so that I could trigger a glow effect on the icon.  The problem is that the Warcraft API doesn&rsquo;t have a way of querying this (you can call <a href="http://wowprogramming.com/docs/api/GetSpellCharges">GetSpellCharges</a> for spells such as Conflagurate, but sadly this doesn&rsquo;t work on an aura.)</p>
<p>To solve this, rather than hard coding values into the view, or forcing the user to specify some kind of &ldquo;glow at xxx stacks&rdquo; parameter in the config, I wrote an object which you can be queried.  This could also be expanded later to hold additional spell data which is not available in the API.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> addon, ns <span style="color:#f92672">=</span> ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> spellData <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	new <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">local</span> charges <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>			[<span style="color:#ae81ff">53817</span>] <span style="color:#f92672">=</span> <span style="color:#ae81ff">5</span>,
</span></span><span style="display:flex;"><span>			[<span style="color:#e6db74">&#34;Maelstrom Weapon&#34;</span>] <span style="color:#f92672">=</span> <span style="color:#ae81ff">5</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			[<span style="color:#ae81ff">91342</span>] <span style="color:#f92672">=</span> <span style="color:#ae81ff">5</span>,
</span></span><span style="display:flex;"><span>			[<span style="color:#e6db74">&#34;Shadow Infusion&#34;</span>] <span style="color:#f92672">=</span> <span style="color:#ae81ff">5</span>,
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		setmetatable(charges, { __index <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(key) <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">1</span> <span style="color:#66d9ef">end</span> })
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> {
</span></span><span style="display:flex;"><span>			getMaxCharges <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(spellID)
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">return</span> charges[spellID]
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>ns.spellData <span style="color:#f92672">=</span> spellData.new()
</span></span></code></pre></div><p>As the implementation of <code>getMaxCharges</code> is hidden, I can change it at will - perhaps splitting my <code>charges</code> table into two separate tables, or if Blizzard kindly implemented a <code>GetMaxStacks(spellName)</code> I could call this instead and remove my <code>charges</code> table altogether.</p>
<h3 id="composition">Composition</h3>
<p>We can utilise composition to create objects based off other objects, by decorating an instance with new functionality.  A slightly cut down version of the grouping code from my <a href="https://github.com/Pondidum/Dark.Bags/tree/master/groups">Dark.Bags addon</a> makes good use of this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> group <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	new <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(name, parent, options)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">local</span> frame <span style="color:#f92672">=</span> CreateFrame(<span style="color:#e6db74">&#34;Frame&#34;</span>, name, parent),
</span></span><span style="display:flex;"><span>		layoutEngine.init(frame, { type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;HORIZONTAL&#34;</span>, wrap <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>, autosize <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span> })
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> {
</span></span><span style="display:flex;"><span>			add <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(child)
</span></span><span style="display:flex;"><span>				frame.add(child)
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> bag <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	new <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(name, parent)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">local</span> this <span style="color:#f92672">=</span> group.new(name, parent)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		this.populate <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(contents)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">for</span> key, details <span style="color:#66d9ef">in</span> pairs(contents) <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>				this.add(itemView.new(details))
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> this
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Here we have two classes <code>group</code> and <code>bag</code>.  The <code>group</code> acts as our base class; it just creates a frame, and initialises a layout engine which does the heavy lifiting of laying out child frames.</p>
<p>In the <code>bag.new()</code> function, we create an instance of a <code>group</code> and add a <code>populate</code> method to it, and return it.  We can continue creating new classes which use <code>bag</code> and <code>group</code> as base types as we need.</p>
<h3 id="problems-with-closures">Problems with Closures</h3>
<p>The down side to using closures is that inheritance is not really possible.  To take the <code>counter</code> example again, if you wanted to create a stepping counter, you couldn&rsquo;t do this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> evenCounter <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>	new <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">local</span> this <span style="color:#f92672">=</span> counter.new()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		this.increase <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>()
</span></span><span style="display:flex;"><span>			<span style="color:#75715e">-- how do we access count?!</span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> this
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Not only can you not access the original <code>count</code> variable, but you would also have to reimplement the <code>print</code> function as it would not have access to your new counting variable.</p>
<p>These problems can be solved using the metatables methods in the next post, however depending on what you are doing, you could just use composition instead as outlined below.</p>
]]></content:encoded></item><item><title>Good Design in Warcraft Addons/Lua</title><link>https://andydote.co.uk/2014/11/23/good-design-in-warcraft-addons/</link><pubDate>Sun, 23 Nov 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/11/23/good-design-in-warcraft-addons/</guid><description>Lack of Encapsulation in Addons I first noticed a lack of good design in addon code when I started trying to tweak existing addons to be slightly different.
One of the stand out examples was a Threat Meter (you know which one I mean). It works well, but I felt like writing my own, to make it really fit into my UI, with as little overhead as possible. Not knowing how to even begin writing a Threat Meter, I downloaded a copy, and opened its source directory&amp;hellip; to discover that the entire addon is one 3500+ line file, and 16 Ace.</description><content:encoded><![CDATA[<h2 id="lack-of-encapsulation-in-addons">Lack of Encapsulation in Addons</h2>
<p>I first noticed a lack of good design in addon code when I started trying to tweak existing addons to be slightly different.</p>
<p>One of the stand out examples was a Threat Meter (you know which one I mean).  It works well, but I felt like writing my own, to make it really fit into my UI, with as little overhead as possible.  Not knowing how to even begin writing a Threat Meter, I downloaded a copy, and opened its source directory&hellip; to discover that the entire addon is one 3500+ line file, and 16 Ace.* dependencies.</p>
<p>When I had finished my Threat Meter, I had two files (170 lines and 130 lines), and one dependency (Dark.Core, which all my addons use).  I learnt a lot while reading the source for the original threat meter - it is very customisable, is externally skinable, and has some very good optimisations in it.  But it also has a lot of unused variables (which are named very similarly to used ones), and so much of it&rsquo;s code <em>could</em> be separated out, making it easier to modify by newer project members.</p>
<p>This set of observations goes on forever when concerning addons.  The three main problems I see are:</p>
<ul>
<li>Pollution of the global namespace</li>
<li>All code in one file</li>
<li>No separation of concerns</li>
</ul>
<p>All of this makes it harder for new developers to pick up and learn how to maintain and write addons.  They are all fairly straight forward to solve problems, so lets address them!</p>
<h2 id="pollution-of-the-global-namespace">Pollution of the Global Namespace</h2>
<p>A lot of addons you find declare many variables as global so they can access them anywhere within their addon.  For example, this is pretty standard:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span>MyAddonEvents <span style="color:#f92672">=</span> CreateFrame(<span style="color:#e6db74">&#34;Frame&#34;</span>, <span style="color:#e6db74">&#34;MyAddonEventFrame&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>MyAddonEvents:RegisterEvent(<span style="color:#e6db74">&#34;PLAYER_ENTERING_WORLD&#34;</span>)
</span></span><span style="display:flex;"><span>MyAddonEvents:SetScript(<span style="color:#e6db74">&#34;OnEvent&#34;</span>, MyAddonEventHandler)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>MyAddonEventHandler <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, event, ...)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> event <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;PLAYER_ENTERING_WORLD&#34;</span> <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">--do something useful</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>This is an example of poluting the global namespace, as now the entire UI has access to: <code>MyAddonEvents</code>, <code>MyAddonEventFrame</code>, <code>MyAddonEventHandler</code>.  This is very trivial to rewrite to not expose anything to the global namespace:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> events <span style="color:#f92672">=</span> CreateFrame(<span style="color:#e6db74">&#34;Frame&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> handler <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, event, ...)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> event <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;PLAYER_ENTERING_WORLD&#34;</span> <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">--do something useful</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>events:RegisterEvent(<span style="color:#e6db74">&#34;PLAYER_ENTERING_WORLD&#34;</span>)
</span></span><span style="display:flex;"><span>events:SetScript(<span style="color:#e6db74">&#34;OnEvent&#34;</span>, handler)
</span></span></code></pre></div><p>This version exposes nothing to the global namespace, and performs exactly the same function (you can even get rid of the <code>handler</code> variable and just pass the function directly into <code>SetScript</code>).</p>
<p>However, by writing your code like this, you can&rsquo;t access any of this from another file (either a lua file, or <em>shudder</em> a frameXml file), but using namespaces we can get around this limitation without polluting the global namespace.</p>
<h2 id="splitting-into-separate-files">Splitting into Separate Files</h2>
<p>So, how to access local variables in other files?  Well Warcraft addons come with a feature where all lua files are provided with two arguments: <code>addon</code> and <code>ns</code>.  The first of these is a string of the addon name, and the second is an empty table.  I almost never use the <code>addon</code> parameter, but the <code>ns</code> (or &ldquo;namespace&rdquo;) parameter is key to everything.</p>
<p>You can access these two variables by writing this as the first line of your lua file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> addon, ns <span style="color:#f92672">=</span> ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;Hello from, &#34;</span> <span style="color:#f92672">..</span> addon)
</span></span></code></pre></div><p>By using the <code>ns</code>, we can put our own variables into it to access from other files.  For example, we have an event system in one file:</p>
<p><em>eventSystem.lua</em></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> addon, ns <span style="color:#f92672">=</span> ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> events <span style="color:#f92672">=</span> CreateFrame(<span style="color:#e6db74">&#34;Frame&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> handlers <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>events:SetScript(<span style="color:#e6db74">&#34;OnEvent&#34;</span>, <span style="color:#66d9ef">function</span>(self, event, ...)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">local</span> eventHandlers <span style="color:#f92672">=</span> handlers[event] <span style="color:#f92672">or</span> {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">for</span> i, handler <span style="color:#66d9ef">in</span> ipairs(eventHandlers) <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>		handler(event, ...)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>ns.register <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(event, handler)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	handlers[event] <span style="color:#f92672">=</span> handlers[event] <span style="color:#f92672">or</span> {}
</span></span><span style="display:flex;"><span>	table.insert(handlers[event], handler)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	events:RegisterEvent(event)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>Note how the <code>register</code> function is defined on the <code>ns</code>.  This means that any other file in our addon can do this to handle an event:</p>
<p><em>goldPrinter.lua</em></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> addon, ns <span style="color:#f92672">=</span> ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>ns.register(<span style="color:#e6db74">&#34;PLAYER_MONEY&#34;</span>, <span style="color:#66d9ef">function</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">local</span> gold <span style="color:#f92672">=</span> floor(money <span style="color:#f92672">/</span> (COPPER_PER_SILVER <span style="color:#f92672">*</span> SILVER_PER_GOLD))
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">local</span> silver <span style="color:#f92672">=</span> floor((money <span style="color:#f92672">-</span> (gold <span style="color:#f92672">*</span> COPPER_PER_SILVER <span style="color:#f92672">*</span> SILVER_PER_GOLD)) <span style="color:#f92672">/</span> COPPER_PER_SILVER)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">local</span> copper <span style="color:#f92672">=</span> mod(money, COPPER_PER_SILVER)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">local</span> moneyString <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">local</span> separator <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> ( gold <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span> ) <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>		moneyString <span style="color:#f92672">=</span> format(GOLD_AMOUNT_TEXTURE, gold, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>		separator <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34; &#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> ( silver <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span> ) <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>		moneyString <span style="color:#f92672">=</span> moneyString <span style="color:#f92672">..</span> separator <span style="color:#f92672">..</span> format(SILVER_AMOUNT_TEXTURE, silver, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>		separator <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34; &#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> ( copper <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span> <span style="color:#f92672">or</span> moneyString <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;&#34;</span> ) <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>		moneyString <span style="color:#f92672">=</span> moneyString <span style="color:#f92672">..</span> separator <span style="color:#f92672">..</span> format(COPPER_AMOUNT_TEXTURE, copper, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	print(<span style="color:#e6db74">&#34;You now have &#34;</span> <span style="color:#f92672">..</span> moneyString)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>)
</span></span></code></pre></div><p>A pretty trivial example, but we have managed to write a two file addon, without putting <strong>anything</strong> in the global namespace.</p>
<p>We have also managed to separate our concerns - the <code>goldPrinter</code> does not care what raises the events, and the <code>eventSystem</code> knows nothing about gold printing, just how to delegate events.  There is also an efficiency here too - anything else in our addon that needs events uses the same eventSystem, meaning we only need to create one frame for the entire addon to receive events.</p>
<h2 id="structure">Structure</h2>
<p>Now that we can separate things into individual files, we gain a slightly different problem - how to organise those files.  I found over time that I end up with roughly the same structure each time, and others might benefit from it too.</p>
<p>All my addons start with four files:</p>
<ul>
<li>AddonName.toc</li>
<li>initialise.lua</li>
<li>config.lua</li>
<li>run.lua</li>
</ul>
<p>The toc file, other than the usual header information is laid out in the order the files will run, for example this is the file segment of my bags addon&rsquo;s toc file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>initialise.lua
</span></span><span style="display:flex;"><span>config.lua
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>models\classifier.lua
</span></span><span style="display:flex;"><span>models\classifiers\equipmentSet.lua
</span></span><span style="display:flex;"><span>models\itemModel.lua
</span></span><span style="display:flex;"><span>models\model.lua
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>groups\group.lua
</span></span><span style="display:flex;"><span>groups\bagGroup.lua
</span></span><span style="display:flex;"><span>groups\bagContainer.lua
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>views\item.lua
</span></span><span style="display:flex;"><span>views\goldDisplay.lua
</span></span><span style="display:flex;"><span>views\currencyDisplay.lua
</span></span><span style="display:flex;"><span>views\bankBagBar.lua
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sets\container.lua
</span></span><span style="display:flex;"><span>sets\bag.lua
</span></span><span style="display:flex;"><span>sets\bank.lua
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>run.lua
</span></span></code></pre></div><p>The <code>initialise</code> lua file is the first thing to run.  All this tends to do is setup any sub-namespaces on <code>ns</code>, and copy in external dependencies to <code>ns.lib</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> addon, ns <span style="color:#f92672">=</span> ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>ns.models <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>ns.groups <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>ns.views <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>ns.sets <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> core <span style="color:#f92672">=</span> Dark.core
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>ns.lib <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>	fonts <span style="color:#f92672">=</span> core.fonts,
</span></span><span style="display:flex;"><span>	events <span style="color:#f92672">=</span> core.events,
</span></span><span style="display:flex;"><span>	slash <span style="color:#f92672">=</span> core.slash,
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>By copying in the dependencies, we not only save a global lookup each time we need say the event system, but we also have an abstraction point.  If we want to replace the event system, as long as the replacement has the right function names, we can just assign the new one to the lib: <code>ns.lib.events = replacementEvents:new()</code></p>
<p>The sub namespaces correspond to folders on in the addon (much the same practice used by c# developers), so for example the <code>classifier.lua</code> file might have this in it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> addon, ns <span style="color:#f92672">=</span> ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> classifier <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>	new <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>() <span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>	update <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>() <span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>	classify <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(item) <span style="color:#66d9ef">end</span>,
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>ns.models.classifier <span style="color:#f92672">=</span> classifier
</span></span></code></pre></div><p>The config file should be fairly simple, with not much more than a couple of tables in it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> addon, ns <span style="color:#f92672">=</span> ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>ns.config <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>	buttonSize <span style="color:#f92672">=</span> <span style="color:#ae81ff">24</span>,
</span></span><span style="display:flex;"><span>	spacing <span style="color:#f92672">=</span> <span style="color:#ae81ff">4</span>,
</span></span><span style="display:flex;"><span>	screenPadding <span style="color:#f92672">=</span> <span style="color:#ae81ff">10</span>,
</span></span><span style="display:flex;"><span>	currencies <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#ae81ff">823</span>, <span style="color:#75715e">-- apexis</span>
</span></span><span style="display:flex;"><span>		<span style="color:#ae81ff">824</span>,  <span style="color:#75715e">-- garrison resources</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And finally, the <code>run.lua</code> file is what makes your addon come to life:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> addon, ns <span style="color:#f92672">=</span> ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> sets <span style="color:#f92672">=</span> ns.sets
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> pack <span style="color:#f92672">=</span> sets.bag:new()
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> bank <span style="color:#f92672">=</span> sets.bank:new()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> ui <span style="color:#f92672">=</span> ns.controllers.uiIntegration.new(pack.frame, bank.frame)
</span></span><span style="display:flex;"><span>ui.hook()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--expose</span>
</span></span><span style="display:flex;"><span>DarkBags <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>	addClassifier <span style="color:#f92672">=</span> ns.classifiers.add
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>If you need to expose something to the entire UI or other addons, that&rsquo;s fine.  But make sure you only expose what you want to.  In the example above the <code>DarkBags</code> global only has one method - <code>addClassifier</code>, because that is all I want other addons to be able to do.</p>
<h2 id="wrapping-up">Wrapping Up</h2>
<p>I hope this helps other people with their addons - I know I wish that I had gotten to this structure and style a lot sooner than I did.</p>
<p>There will be a few more posts incoming covering encapsulation, objects and inheritance in more detail, so stay tuned.</p>
]]></content:encoded></item><item><title>Edge.js for Embedded Webuis</title><link>https://andydote.co.uk/2014/08/04/edgejs-for-embedded-webuis/</link><pubDate>Mon, 04 Aug 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/08/04/edgejs-for-embedded-webuis/</guid><description>We work we have a number of windows services which each have a lot of stats they could expose. Currently they are only interrogatable by the logfiles and from any notifications we receive.
I have been toying with the idea of hosting a website in-process which would give a simple dashboard ui and access to a live view of the log file. The idea first struck me when I was experimenting with FubuMvc, as they have an EmbeddedFubuMvcServer, which is very easy to use:</description><content:encoded><![CDATA[<p>We work we have a number of windows services which each have a lot of stats they could expose.  Currently they are only interrogatable by the logfiles and from any notifications we receive.</p>
<p>I have been toying with the idea of hosting a website in-process which would give a simple dashboard ui and access to a live view of the log file.  The idea first struck me when I was experimenting with FubuMvc, as they have an <code>EmbeddedFubuMvcServer</code>, which is very easy to use:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>FubuMvcPackageFacility.PhysicalRootPath = <span style="color:#e6db74">@&#34;Backend\&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> server = EmbeddedFubuMvcServer.For&lt;EmbeddedBackend&gt;(FubuMvcPackageFacility.PhysicalRootPath))
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Console.WriteLine(<span style="color:#e6db74">&#34;Some long running process, with a web-backend on :5500&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> p = server.Services.GetInstance&lt;IProcessor&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> t = <span style="color:#66d9ef">new</span> Task(p.Start);
</span></span><span style="display:flex;"><span>    t.Start();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Console.ReadKey();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>But while I like this, FubuMvc embedded seems like overkill.</p>
<p>Wouldn&rsquo;t it be nice if we could host an <code>expressjs</code> app inside our process?  They are very lightweight, and to get one setup is almost no coding (especially if you use the express commandline tool).</p>
<h2 id="enter-edgejs">Enter Edgejs</h2>
<p>The <a href="http://tjanczuk.github.io/edge/">Edge.js</a> project provides an in-process bridge between the .net and nodejs worlds, and allows for communication between the two&hellip;</p>
<p>Steps:</p>
<ul>
<li>
<p>Create a new application (eg: ServiceWithEdge)</p>
</li>
<li>
<p>Create a subdirectory for the webui in your applications root (eg, next to the csproj file)</p>
<ul>
<li>ServiceWithEdge\ServiceWithEdge\webui</li>
</ul>
</li>
<li>
<p>If you don&rsquo;t have express-generator installed, get it:</p>
<ul>
<li><code>npm install -g express-generator</code></li>
</ul>
</li>
<li>
<p>Cd to your webui directory, and create an express application:</p>
<ul>
<li><code>express</code> - there are some options if you want, see <a href="http://expressjs.com/guide.html#executable">the guide</a></li>
</ul>
</li>
<li>
<p>In visual studio, include the webui directory</p>
<ul>
<li>Mark all files as <code>content</code> and <code>copy if newer</code></li>
</ul>
</li>
<li>
<p>Add a new js file in your webui root:</p>
</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> options;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>exports.<span style="color:#66d9ef">set</span> = function (m) {
</span></span><span style="display:flex;"><span>    options = m;
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>exports.getModel = function (modelName, action) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    options.getModel(modelName, function (error, result) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (error) <span style="color:#66d9ef">throw</span> error;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        action(result);
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><ul>
<li>
<p>add the edgejs package:</p>
<ul>
<li><code>PM&gt; install-package edge.js</code></li>
</ul>
</li>
<li>
<p>The following function will run the webui, and inject a callback for getting models from .net</p>
</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> RunWebui(ModelStore store)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> func = Edge.Func(<span style="color:#e6db74">@&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">		var app = require(&#39;../webui/app&#39;);
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">		var com = require(&#39;../webui/communicator&#39;);
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">		app.set(&#39;port&#39;, process.env.PORT || 3000);
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">		var server = app.listen(app.get(&#39;port&#39;));
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">		return function(options, callback) {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">			com.set(options);
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">		};
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">	&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> getModel = (Func&lt;<span style="color:#66d9ef">object</span>, Task&lt;<span style="color:#66d9ef">object</span>&gt;&gt;)(<span style="color:#66d9ef">async</span> (message) =&gt;
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> store.GetModel((<span style="color:#66d9ef">string</span>)message);
</span></span><span style="display:flex;"><span>	});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	Task.Run(() =&gt; func(<span style="color:#66d9ef">new</span>
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		getModel
</span></span><span style="display:flex;"><span>	}));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><ul>
<li>The last step to getting this to work is running <code>npm install</code> in the webui directory <strong>of the build output folder</strong>.  I use a rake file to build everything, so its just an extra task (see the entire Rakefile <a href="https://github.com/Pondidum/ServiceWithEdge/blob/master/Rakefile">here</a>):</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>task <span style="color:#e6db74">:npm</span> <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>t<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Dir</span><span style="color:#f92672">.</span>chdir <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">#{</span>project_name<span style="color:#e6db74">}</span><span style="color:#e6db74">/bin/debug/webui&#34;</span> <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>		system <span style="color:#e6db74">&#39;npm&#39;</span>, <span style="color:#e6db74">&#39;install&#39;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><pre><code>ny route needing data from .net just needs to require the communicator file and call `getModel`:
</code></pre>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">com</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">&#39;../communicator&#39;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">router</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#39;/&#39;</span>, <span style="color:#66d9ef">function</span> (<span style="color:#a6e22e">req</span>, <span style="color:#a6e22e">res</span>) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">com</span>.<span style="color:#a6e22e">getModel</span>(<span style="color:#e6db74">&#34;index&#34;</span>, <span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">value</span>) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">render</span>(<span style="color:#e6db74">&#39;index&#39;</span>, {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">title</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;Express&#39;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">result</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">value</span>.<span style="color:#a6e22e">Iterations</span>
</span></span><span style="display:flex;"><span>        });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>All the code is <a href="https://github.com/Pondidum/ServiceWithEdge">available on github</a>.</p>
<h2 id="how-i-am-aiming-to-use-it">How I am aiming to use it</h2>
<p>I am planning on constructing a nuget package to do all of this, so that all a developer needs to do is add the package, and configure which statistics they wish to show up on the web ui.</p>
]]></content:encoded></item><item><title>Configuring Dapper to work with custom types</title><link>https://andydote.co.uk/2014/07/22/configuring-dapper-to-work-with-custom-types/</link><pubDate>Tue, 22 Jul 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/07/22/configuring-dapper-to-work-with-custom-types/</guid><description>In the last post we looked at using custom ID types to help abstract the column type from the domain.
This works well until you start trying to load and save entities using an ORM, as the ORM has not way to know how to map a column to a custom type. ORMs provide extension points to allow you to create these mappings. As I tend to favour using Dapper, we will go through setting it up to work with our custom ID types.</description><content:encoded><![CDATA[<p>In the <a href="http://andydote.co.uk/strong-type-your-entity-ids">last post</a> we looked at using custom ID types to help abstract the column type from the domain.</p>
<p>This works well until you start trying to load and save entities using an ORM, as the ORM has not way to know how to map a column to a custom type.  ORMs provide extension points to allow you to create these mappings.  As I tend to favour using <a href="https://github.com/StackExchange/dapper-dot-net">Dapper</a>, we will go through setting it up to work with our custom ID types.</p>
<p>We need to be able to get the raw value out of the id type, but without exposing this to the outside world.  To do this we internal interface:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">internal</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IValueID</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">object</span> Value();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Then update our id struct with a private implementation of the interface, and also mark the only constructor as internal:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">PersonID</span> : IValueID
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Guid _id;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">internal</span> PersonID(Guid id)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_id = id;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">object</span> IValueID.Value()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> _id;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We now can define a class which Dapper can use to do the mapping from uuid to id:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PersonIDHandler</span> : SqlMapper.TypeHandler&lt;PersonID&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> SetValue(IDbDataParameter parameter, PersonID <span style="color:#66d9ef">value</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		parameter.Value = ((IValueID)<span style="color:#66d9ef">value</span>).Value();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> PersonID Parse(<span style="color:#66d9ef">object</span> <span style="color:#66d9ef">value</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> PersonID((Guid)<span style="color:#66d9ef">value</span>);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We then need to regiter the command with Dapper once on start up of our application:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>SqlMapper.AddTypeHandler(<span style="color:#66d9ef">new</span> PersonIDHandler());
</span></span></code></pre></div><p>Now when Dapper loads an object with a property type of <code>PersonID</code> it will invoke the <code>Parse</code> method on <code>PersonIDHandler</code>, and populate the resulting object correctly.  It will also work when getting a value from the <code>PersonID</code> property, invoking the <code>SetValue</code> method on <code>PersonIDHandler</code>.</p>
<h2 id="extension">Extension</h2>
<p>While the <code>PersonIDHandler</code> works, I really don&rsquo;t want to be creating essentially the same class over and over again for each ID type.  We can fix this by using a generic id handler class, and some reflection magic.</p>
<p>We start off by creating a generic class for id handling:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">CustomHandler</span>&lt;T&gt; : SqlMapper.TypeHandler&lt;T&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Func&lt;Object, T&gt; _createInstance;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> CustomHandler()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> ctor = <span style="color:#66d9ef">typeof</span>(T)
</span></span><span style="display:flex;"><span>			.GetConstructors()
</span></span><span style="display:flex;"><span>			.Single(c =&gt; c.GetParameters().Count() == <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> paramType = ctor
</span></span><span style="display:flex;"><span>			.GetParameters()
</span></span><span style="display:flex;"><span>			.First()
</span></span><span style="display:flex;"><span>			.ParameterType;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		_createInstance = (<span style="color:#66d9ef">value</span>) =&gt; (T)ctor.Invoke(<span style="color:#66d9ef">new</span>[] { Convert.ChangeType(<span style="color:#66d9ef">value</span>, paramType) });
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> SetValue(IDbDataParameter parameter, T <span style="color:#66d9ef">value</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		parameter.Value = ((IValueID)<span style="color:#66d9ef">value</span>).Value();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> T Parse(<span style="color:#66d9ef">object</span> <span style="color:#66d9ef">value</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> _createInstance(<span style="color:#66d9ef">value</span>);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The constructor of this class just finds a single constructor on our ID type with one argument, and creates a Func which will create an instance of the id passing in the value.   We put all this constructor discovery logic into the <code>CustomHandler</code>&rsquo;s constructor as this information only needs to be calculated once, and can then be used for every <code>Parse</code> call.</p>
<p>We then need to write something to build an instance of this for each ID type in our system.  As all of our IDs need to implement <code>IValueID</code> to work, we can scan for all types in the assembly implementing this interface, and then operate on those.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">InitialiseDapper</span> : IApplicationStart
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Initialise()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> interfaceType = <span style="color:#66d9ef">typeof</span>(IValueID);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> idTypes = interfaceType
</span></span><span style="display:flex;"><span>			.Assembly
</span></span><span style="display:flex;"><span>			.GetTypes()
</span></span><span style="display:flex;"><span>			.Where(t =&gt; t.IsInterface == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>			.Where(t =&gt; t.IsAbstract == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>			.Where(t =&gt; t.GetInterfaces().Contains(interfaceType));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> handler = <span style="color:#66d9ef">typeof</span>(CustomHandler&lt;&gt;);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">foreach</span> (<span style="color:#66d9ef">var</span> idType <span style="color:#66d9ef">in</span> idTypes)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">var</span> ctor = handler
</span></span><span style="display:flex;"><span>				.MakeGenericType(<span style="color:#66d9ef">new</span>[] { idType })
</span></span><span style="display:flex;"><span>				.GetConstructor(Type.EmptyTypes);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">var</span> instance = (SqlMapper.ITypeHandler)ctor.Invoke(<span style="color:#66d9ef">new</span> <span style="color:#66d9ef">object</span>[] { });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			SqlMapper.AddTypeHandler(idType, instance);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This class first scans the assembly containing <code>IValueID</code> for all types implementing <code>IValueID</code> which are not abstract, and not interfaces themselves.  It then goes through each of these types, and builds a new instance of <code>CustomHandler</code> for each type, and registers it with Dapper.</p>
<p>You might notice this is in a class which implements <code>IApplicationStart</code> - In most of my larger projects, I tend to have an interface like this, which defines a single <code>void Initialise();</code> method.  Implementations of the interface get looked for on startup of the application, and their <code>Initialise</code> method called once each.</p>
]]></content:encoded></item><item><title>Strong Type your entity IDs.</title><link>https://andydote.co.uk/2014/07/17/strong-type-your-entity-ids/</link><pubDate>Thu, 17 Jul 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/07/17/strong-type-your-entity-ids/</guid><description>The Database is just an Implementation Detail A quote from Martin Fowler given during his Architecture talk stated that the Database in your application should just be an implementation detail. I agree on this wholeheartedly and find that its really not that difficult to achieve if you think about your architecture carefully.
Having said that, I still see parts of the database implementation leaking out into the domain, mainly in the form of IDs.</description><content:encoded><![CDATA[<h2 id="the-database-is-just-an-implementation-detail">The Database is just an Implementation Detail</h2>
<p>A quote from Martin Fowler given during his Architecture talk stated that the Database in your application should just be an implementation detail.  I agree on this wholeheartedly and find that its really not that difficult to achieve if you think about your architecture carefully.</p>
<p>Having said that, I still see parts of the database implementation leaking out into the domain, mainly in the form of IDs.  This might not seem like much of a leak, but it does cause a few problems, especially on larger systems.</p>
<p>The first problem ocours when you have a function taking in an ID of some form, and the parameter name is not really forthcoming on what object&rsquo;s ID it&rsquo;s expecting.  This is especially problematic if your ID columns are int based, rather than uuids, as passing any int to the function will return data - just not necessarily the data you were expecting.</p>
<p>The second problem is that it ties you to using the same ID type as the database is using.  If the database is just an implementation detail, then it definitely should not be dictating what types your domain should be using.</p>
<p>For example, take the following two classes:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Account</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> ID { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">//...</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">User</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> ID { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> IEnumerable&lt;Account&gt; Accounts { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The two classes on their own are not unreasonable, but the use of an <code>int</code> for the ID is problematic.  Given the following method:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> DateTime GetLastActiveDate(<span style="color:#66d9ef">int</span> userID)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> ...
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Both of the following calls are valid, and neither the code nor the compiler will tell you which one is correct (if any!):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> date1 = GetLastActiveDate(_user.ID);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> date2 = GetLastActiveDate(_user.Accounts.First().ID);
</span></span></code></pre></div><h2 id="using-the-type-system-to-prevent-bad-arguments">Using the Type System to prevent bad arguments</h2>
<p>We can fix this problem by using the Type System to force the correct ID type to be passed in.</p>
<p>First we need to abstract the notion of an ID to be separate from what type its value is.  To do this we create some structs, one for each ID in our system:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">UserID</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> <span style="color:#66d9ef">int</span> _value;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> UserID(<span style="color:#66d9ef">int</span> <span style="color:#66d9ef">value</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_value = <span style="color:#66d9ef">value</span>;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">int</span> GetHashCode()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> _value;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">bool</span> Equals(<span style="color:#66d9ef">object</span> obj)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> (obj <span style="color:#66d9ef">is</span> UserID) &amp;&amp; (((UserID)obj)._value == _value);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">AccountID</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> <span style="color:#66d9ef">int</span> _value;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> AccountID(<span style="color:#66d9ef">int</span> <span style="color:#66d9ef">value</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_value = <span style="color:#66d9ef">value</span>;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">int</span> GetHashCode()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> _value;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">bool</span> Equals(<span style="color:#66d9ef">object</span> obj)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> obj <span style="color:#66d9ef">is</span> AccountID &amp;&amp; GetHashCode() == obj.GetHashCode();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Both of our structs store their values immutably so that they cannot be changed after creation, and we override <code>GetHashCode</code> and <code>Equals</code> so that separate instances can be compared for equality properly.  Note also that there is no inheritance between the two structs - we do not want the ability for a method to expect a <code>UserID</code> and find someone passing in an <code>AccountID</code> because it inherits.</p>
<p>We can now update our objects to use these IDs:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Account</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> AccountID ID { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">//...</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">User</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> UserID ID { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> IEnumerable&lt;Account&gt; Accounts { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And update any method which expects an ID now gets the specific type:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> DateTime GetLastActiveDate(UserID userID)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> ...
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This means that when someone writes this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> date = GetLastActiveDate(_user.Accounts.First().ID);
</span></span></code></pre></div><p>The compiler will complain with an error: <code>Unable to cast type 'AccountID</code> to type &lsquo;UserID``.</p>
<h2 id="abstracting-column-type">Abstracting column type</h2>
<p>By doing this work to use custom types instead of native types for our IDs gives us another benefit:  we can hide what type the database is using from the domain, meaning we could change our table&rsquo;s key to be a uuid, and the only place we would need to change in code would be the relevant ID class.</p>
<h2 id="extra-functionality">Extra functionality</h2>
<p>One more benefit that comes from this approach is that our IDs are now first class citizens in the type world, and we can imbue them with extra functionality.</p>
<p>A system I use has a table with both a uuid column for the primary key, and an int based refnum column for displaying to users, something like this:</p>
<pre><code>person:
id : uuid, forename : varchar(50), surname : varchar(50), dateofbirth : date, refnum : int
</code></pre>
<p>As we have a <code>PersonID</code> type, we can make that hold both values, and override the <code>ToString</code> method so that when called it displays the user friendly ID:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">PersonID</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Guid _id;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> <span style="color:#66d9ef">int</span> _refnum;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> PersonID(Guid id, <span style="color:#66d9ef">int</span> refnum)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_id = id;
</span></span><span style="display:flex;"><span>		_refnum = refnum;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">int</span> GetHashCode()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode/263416#263416</span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">unchecked</span>
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">int</span> hash = <span style="color:#ae81ff">17</span>;
</span></span><span style="display:flex;"><span>			hash = hash * <span style="color:#ae81ff">23</span> + _id.GetHashCode();
</span></span><span style="display:flex;"><span>			hash = hash * <span style="color:#ae81ff">23</span> + _refnum.GetHashCode();
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span> hash;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">bool</span> Equals(<span style="color:#66d9ef">object</span> obj)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> (obj <span style="color:#66d9ef">is</span> PersonID) &amp;&amp; (((PersonID)obj)._id == _id) &amp;&amp; (((PersonID)obj)._refnum == _refnum);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">string</span> ToString()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> _refnum.ToString()
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This means that if in the future we decided to convert to using the refnum as the primary key, and drop the uuid column, again all we would need to do would be to update the <code>PersonID</code> type, and the rest of our code base would be unaffected.</p>
]]></content:encoded></item><item><title>Specific Interfaces</title><link>https://andydote.co.uk/2014/06/08/specific-interfaces-smaller-abstractions/</link><pubDate>Sun, 08 Jun 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/06/08/specific-interfaces-smaller-abstractions/</guid><description>While writing my CruiseCli project, I needed to do some data storage, and so used my standard method of filesystem access, the IFileSystem. This is an interface and implementation which I tend to copy from project to project, and use as is. The interface looks like the following:
public interface IFileSystem { bool FileExists(string path); void WriteFile(string path, Stream contents); void AppendFile(string path, Stream contents); Stream ReadFile(string path); void DeleteFile(string path); bool DirectoryExists(string path); void CreateDirectory(string path); IEnumerable&amp;lt;string&amp;gt; ListDirectory(string path); void DeleteDirectory(string path); } And the standard implementation looks like the following:</description><content:encoded><![CDATA[<p>While writing my <a href="https://github.com/Pondidum/CruiseCli">CruiseCli</a> project, I needed to do some data storage, and so used my standard method of filesystem access, the <code>IFileSystem</code>.  This is an interface and implementation which I tend to copy from project to project, and use as is.  The interface looks like the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IFileSystem</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">bool</span> FileExists(<span style="color:#66d9ef">string</span> path);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> WriteFile(<span style="color:#66d9ef">string</span> path, Stream contents);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> AppendFile(<span style="color:#66d9ef">string</span> path, Stream contents);
</span></span><span style="display:flex;"><span>	Stream ReadFile(<span style="color:#66d9ef">string</span> path);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> DeleteFile(<span style="color:#66d9ef">string</span> path);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">bool</span> DirectoryExists(<span style="color:#66d9ef">string</span> path);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> CreateDirectory(<span style="color:#66d9ef">string</span> path);
</span></span><span style="display:flex;"><span>	IEnumerable&lt;<span style="color:#66d9ef">string</span>&gt; ListDirectory(<span style="color:#66d9ef">string</span> path);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> DeleteDirectory(<span style="color:#66d9ef">string</span> path);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And the standard implementation looks like the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">FileSystem</span> : IFileSystem
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">bool</span> FileExists(<span style="color:#66d9ef">string</span> path)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> File.Exists(path);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> WriteFile(<span style="color:#66d9ef">string</span> path, Stream contents)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> fs = <span style="color:#66d9ef">new</span> FileStream(path, FileMode.Create, FileAccess.Write))
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			contents.CopyTo(fs);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Stream ReadFile(<span style="color:#66d9ef">string</span> path)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">//snip...</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This (I think) is a very good solution to file system access as I can easily mock the interface and add expectations and stub values to it for testing.</p>
<p>However, on the CruiseCli project, I realised I didn&rsquo;t need most of what the interface provided, so I chopped all the bits off I didn&rsquo;t want, and added a property for a base directory I was using all the time:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IFileSystem</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">string</span> HomePath { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> WriteFile(<span style="color:#66d9ef">string</span> path, Stream contents);
</span></span><span style="display:flex;"><span>	Stream ReadFile(<span style="color:#66d9ef">string</span> path);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">bool</span> FileExists(<span style="color:#66d9ef">string</span> path);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Which was better than the original, as I have a lot less methods to worry about, and thus it is more specific to my use case.</p>
<p>But I got thinking later in the project; &ldquo;what are my use cases?&rdquo;, &ldquo;what do I actually want to do with the filesystem?&rdquo;  The answer to this was simple: Read a config file, and write to the same config file.  Nothing else.</p>
<p>So why not make the interface even more specific in this case:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IConfiguration</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> Write(Stream contents);
</span></span><span style="display:flex;"><span>	Stream Read();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Even simpler, and I now have the benefit of not caring what the filepaths are outside of the implementing class.</p>
<p>This means that in my integration tests, I can write an in-memory <code>IConfiguration</code> with far less hassle, and not need to worry about fun things like character encoding and case sensitivity on filepaths!</p>
<p>In a more complicated system, I would probably keep this new <code>IConfiguration</code> interface for accesing the config file, and make the concrete version depend on the more general <code>IFileSystem</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Configuration</span> : IConfiguration
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">string</span> FileName = <span style="color:#e6db74">&#34;.cruiseconfig&#34;</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IFileSystem _fileSystem;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Configuration(IFileSystem fileSystem)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_fileSystem = fileSystem;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Write(Stream contents)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_fileSystem.WriteFile(Path.Combine(_fileSystem.Home, FileName), contents);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Stream Read()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> _fileSystem.ReadFile(Path.Combine(_fileSystem.Home, FileName));
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>For a small system this would probably be overkill, but for a much larger project, this could help provide a better seperation of responsibilities.</p>
]]></content:encoded></item><item><title>Using StructureMap Registries for better separation</title><link>https://andydote.co.uk/2014/05/19/using-structuremap-registries/</link><pubDate>Mon, 19 May 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/05/19/using-structuremap-registries/</guid><description>When it comes to configuring StructureMap, it supports the use of Registries. Registries support everything that the standard configure method does(new Container(c =&amp;gt; { /* */});).
There are two main reasons that I use the registries rather then doing all my configuration in the Container&amp;rsquo;s lambda: separation of concerns (one registry per area of code) and easier testing (which we will go into shortly).
The only down side I can see to using registries is that it can scatter your configuration across your codebase - but if you have ReSharper, doing a &amp;lsquo;Find Implementations&amp;rsquo; on Registry will find them all for you, so it really isn&amp;rsquo;t much of a down side.</description><content:encoded><![CDATA[<p>When it comes to configuring StructureMap, it supports the use of <a href="http://fubuworld.com/structuremap/registration/registry-dsl/">Registries</a>.  Registries support everything that the standard configure method does(<code>new Container(c =&gt; { /* */});</code>).</p>
<p>There are two main reasons that I use the registries rather then doing all my configuration in the Container&rsquo;s lambda:  separation of concerns (one registry per area of code) and easier testing (which we will go into shortly).</p>
<p>The only down side I can see to using registries is that it can scatter your configuration across your codebase - but if you have ReSharper, doing a &lsquo;Find Implementations&rsquo; on <code>Registry</code> will find them all for you, so it really isn&rsquo;t much of a down side.</p>
<h2 id="separation-of-concerns">Separation of Concerns</h2>
<p>Taking <a href="https://github.com/Pondidum/NuCache">NuCache</a> as an example, in our app start we have <a href="https://github.com/Pondidum/NuCache/blob/master/NuCache/App_Start/ConfigureContainer.cs">ConfigureContainer.cs</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> Register(HttpConfiguration config)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> container = <span style="color:#66d9ef">new</span> Container(c =&gt; c.Scan(a =&gt;
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		a.TheCallingAssembly();
</span></span><span style="display:flex;"><span>		a.WithDefaultConventions();
</span></span><span style="display:flex;"><span>		a.LookForRegistries();
</span></span><span style="display:flex;"><span>	}));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	config.DependencyResolver = <span style="color:#66d9ef">new</span> StructureMapDependencyResolver(container);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This snippet of code gets called as part of the AppStart, and tells StructureMap to use the default conventions (eg: <code>IFileSystem =&gt; FileSystem</code>), and to process any registries it finds.  The app then has multiple Registries with the actual configuration in (usually one per namespace, although not all namespaces have a registry).</p>
<p>For example, we have these two registries:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">InfrastructureRegistry</span> : Registry
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> InfrastructureRegistry()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		For&lt;IPackageCache&gt;()
</span></span><span style="display:flex;"><span>			.Use&lt;FileSystemPackageCache&gt;()
</span></span><span style="display:flex;"><span>			.OnCreation(c =&gt; c.Initialise())
</span></span><span style="display:flex;"><span>			.Singleton();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ProxyBehaviourRegistry</span> : Registry
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> ProxyBehaviourRegistry ()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		Scan(a =&gt;
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			a.TheCallingAssembly();
</span></span><span style="display:flex;"><span>			a.AddAllTypesOf&lt;IProxyBehaviour&gt;();
</span></span><span style="display:flex;"><span>		});
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <a href="https://github.com/Pondidum/NuCache/blob/master/NuCache/Infrastructure/InfrastructureRegistry.cs">InfrastructureRegistry</a> just specifies how to resolve an <code>IPackageCache</code>, as it has requires some extra initialisation and to be treated as a singleton.</p>
<p>The <a href="https://github.com/Pondidum/NuCache/blob/master/NuCache/ProxyBehaviour/ProxyBehaviourRegistry.cs">ProxyBehaviourRegistry</a> tells StructureMap to add all implementations of <code>IProxyBehaviour</code>, so that when we construct as <code>ProxyBehaviourSet</code>, which has a constructor parameter of <code>IEnumerable&lt;IProxyBehaviour&gt;</code> all the implementations are passed in for us.</p>
<h2 id="easier-testing">Easier Testing</h2>
<p>We can use the Registry feature of StructureMap to allow us to test parts of code as they would be in production.  This mostly applies to acceptance style testing, for example when I am testing the XmlRewriter, I want it to behave exactly as it would in production, with the same <code>IXElementTransform</code>s passed in.</p>
<p>To do this, we can use the <code>RewriterRegistry</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> container = <span style="color:#66d9ef">new</span> Container(<span style="color:#66d9ef">new</span> RewriterRegistry());
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> rewriter = container.GetInstance&lt;XmlRewriter&gt;();
</span></span></code></pre></div><p>Here we create a new container with the <code>RewriterRegistry</code> passed directly into the constructor.  This gives us access to a container completely configured for using the <code>XmlRewriter</code>.  We can then fake the inputs and outputs to the method under test, keeping the whole system in a known production-like state.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> inputStream = GetType().Assembly.GetManifestResourceStream(<span style="color:#e6db74">&#34;NuCache.Tests.Packages.xml&#34;</span>))
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> outputStream = <span style="color:#66d9ef">new</span> MemoryStream())
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	rewriter.Rewrite(targetUri, inputStream, outputStream);
</span></span><span style="display:flex;"><span>	outputStream.Position = <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	_result = XDocument.Load(outputStream);
</span></span><span style="display:flex;"><span>	_namespace = _result.Root.Name.Namespace;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Hopefully this shows how useful and powerful feature StructureMap&rsquo;s Registries are.</p>
]]></content:encoded></item><item><title>Writing Rich Domain Models</title><link>https://andydote.co.uk/2014/05/04/rich-domain-modeling/</link><pubDate>Sun, 04 May 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/05/04/rich-domain-modeling/</guid><description>The term Rich Domain Model is used to describe a domain model which really shows you how you should be using and manipulating the model, rather than letting you do anything with it. It is the opposite of an Anaemic Domain Model, which provides a very low abstraction over the data storage (generally), but with little to no enforcing of rules.
The Anaemic Domain Model To take the standard model of a person who has addresses and phone numbers etc seems a little contrite, so lets run through an example using timesheets (bear in mind I don&amp;rsquo;t know what really goes into a timesheet system, this just seems reasonable).</description><content:encoded><![CDATA[<p>The term Rich Domain Model is used to describe a domain model which really shows you how you should be using and manipulating the model, rather than letting you do anything with it.  It is the opposite of an Anaemic Domain Model, which provides a very low abstraction over the data storage (generally), but with little to no enforcing of rules.</p>
<h2 id="the-anaemic-domain-model">The Anaemic Domain Model</h2>
<p>To take the standard model of a person who has addresses and phone numbers etc seems a little contrite, so lets run through an example using timesheets (bear in mind I don&rsquo;t know what really goes into a timesheet system, this just seems reasonable).  The current model looks something like the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TimeSheet</span> : DbEntity
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> DateTime WeekDate { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> TimeSheetStates State { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> TimeSheetLineCollection Lines { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">//...</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TimeSheetLineCollection</span> : DbEntityCollection&lt;TimeSheetLine&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TimeSheetLine</span> : DbEntity
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> DateTime Day { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>;}
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> LineTypes LineType { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">decimal</span> HourlyRate { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">decimal</span> Hours { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">enum</span> TimeSheetStates
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	New,
</span></span><span style="display:flex;"><span>	Saved,
</span></span><span style="display:flex;"><span>	Submitted,
</span></span><span style="display:flex;"><span>	Approved,
</span></span><span style="display:flex;"><span>	Rejected
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">enum</span> LineTypes
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	Normal,
</span></span><span style="display:flex;"><span>	Holiday,
</span></span><span style="display:flex;"><span>	Sick
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The first problem with this model is that the domain entities are inheriting directly from a <code>DbEntity</code> which is coupling our logic directly to our data access, which amongst other things is a violation of <a href="http://andydote.co.uk/solid-principles-srp">SRP</a>.  Putting this aside for the time being, the next issue is that the domain model lets you do anything with the objects and collections.</p>
<p>The model implies that there are rules governing its usage somewhere, but gives no hint as to what these rules are, or where they are located.  Rules such as &lsquo;only allow hours to be entered in increments of half an hour&rsquo; and &rsquo;no more than 5 lines in a given week&rsquo; really should be in the domain model itself, as a Rich Domain Model should not allow itself to get into an invalid state.</p>
<p>The model also is leaking what kind of data store it is built on - after all, if you had an Event Sourcing pattern for storage, a <code>Delete</code> operation on the <code>TimeSheetLineCollection</code> would not make a lot of sense.</p>
<h2 id="the-rich-domain-model">The Rich Domain Model</h2>
<p>A better version of this model is to make all the behaviour explicit, rather than just exposing the collections for external modification:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TimeSheet</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> DateTime WeekDate { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> TimeSheetStates State { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> IEnumerable&lt;TimeSheetLine&gt; Lines { <span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> _lines; } }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> List&lt;TimeSheetLine&gt; _lines;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> TimeSheetRules _rules;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> TimeSheet(TimeSheetRules rules, DateTime weekDate)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_lines = <span style="color:#66d9ef">new</span> List&lt;TimeSheetLine&gt;();
</span></span><span style="display:flex;"><span>		_rules = rules;
</span></span><span style="display:flex;"><span>		WeekDate = weekDate
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> AddLine(DayOfWeek day, LineTypes lineType, <span style="color:#66d9ef">decimal</span> hours, <span style="color:#66d9ef">decimal</span> hourlyRate)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> line = <span style="color:#66d9ef">new</span> TimeSheetLine {
</span></span><span style="display:flex;"><span>			Day = WeekDate.AddDays(day),
</span></span><span style="display:flex;"><span>			LineType = lineType,
</span></span><span style="display:flex;"><span>			Hours = hours,
</span></span><span style="display:flex;"><span>			HourlyRate = hourlyRate
</span></span><span style="display:flex;"><span>		};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		_rules.ValidateAdd(Lines, line);	<span style="color:#75715e">//throws a descriptive error message if you can&#39;t do add.</span>
</span></span><span style="display:flex;"><span>		_lines.Add(line);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The Rich model does a number of interesting things.  The first is that all the properties of the <code>TimeSheet</code> class are now <code>private set</code>.  This allows us to enforce rules on when and how they get set.  For example, the <code>WeekDate</code> property value gets passed in via the constructor, as our domain says that for a week to be valid it must have a weekdate.</p>
<p>The major improvement is in adding lines to the <code>TimeSheet</code>.  In the Anaemic version of the model, you could have just created a <code>TimeSheetLine</code> object and set the <code>Day</code> property to an arbitrary date, rather than one in the given week&rsquo;s range.  The Rich model forces the caller to pass in a <code>DayOfWeek</code> to the function, which ensures that a valid datetime will get stored for the line.  The <code>AddLine</code> method also calls <code>_rules.ValidateAdd()</code> which gives us a central place for putting rules on line actions.</p>
<p>Now that the user has been able to fill out all the lines in their timesheet, the next likely action they want to perform is to submit it for authorization.  We can do this by adding the following method:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> SubmitForApproval(User approver)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	_rules.ValidateTimeSheetIsComplete(<span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	approver.AddWaitingTimeSheet(<span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>	State = TimeSheetStates.Submitted;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note this method only validates if the timesheet is complete enough to be approved - validation for whether the approver can actually approve this timesheet is held within the <code>apperover.AddWaitingTimeSheet</code> method.</p>
<p>The next thing to consider is when the approver rejects the timesheet because the user filled out the wrong weekdate.  Rather than just exposing Weekdate to be publicly setable, we can capture the intent of the adjustment with a set of methods:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> UserEnteredIncorrectWeek(DateTime newDate)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> delta = WeekDate - newDate;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	WeekDate = newDate;
</span></span><span style="display:flex;"><span>	_lines.ForEach(line =&gt; line.Day = line.Day.AddDays(-delta));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note how the method is named to capture the reason for the change.  Although we are not actively storing the reason, if we were using an EventStream for the backing store, or maintaining a separate log of changes we would now have a reason as to why the change was made.  This helps guide UI elements - rather then just having an &ldquo;Edit Week Date&rdquo; button, there could be a UI element which says &ldquo;Change Incorrect Week&rdquo; or similar.</p>
<p>The function also has some logic baked into it - each of the <code>TimeSheetLine</code>s needs its <code>Day</code> property re-calculating.</p>
<p>Hopefully this helps demonstrate why Rich Domain Models are better solutions to complex domain problems than Anaemic Domain Models are.</p>
<p>For a really good video on this subject, check out Jimmy Bogard&rsquo;s <a href="http://vimeo.com/43598193">Crafting Wicked Domain Models</a> talk.</p>
]]></content:encoded></item><item><title>Using a Micro ORM to decouple your DB Access</title><link>https://andydote.co.uk/2014/03/29/using-a-micro-orm-to-decouple-your-db-access/</link><pubDate>Sat, 29 Mar 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/03/29/using-a-micro-orm-to-decouple-your-db-access/</guid><description>One of the databases I use on a regular bases has a rather interesting column naming scheme; all columns have a prefix, based on the table name. For example, the table containing people would have the prefix PEO_, so you would have this:
Select * from People PEO_PersonID, PEO_FirstName, PEO_LastName, PEO_DoB ----------------------------------------------------- 1 John Jones 1984-07-15 I believe the idea was so that when querying, you would not have any column name clashes.</description><content:encoded><![CDATA[<p>One of the databases I use on a regular bases has a rather interesting column naming scheme;  all columns have a prefix, based on the table name.  For example, the table containing people would have the prefix <code>PEO_</code>, so you would have this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">Select</span> <span style="color:#f92672">*</span> <span style="color:#66d9ef">from</span> People
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>PEO_PersonID, PEO_FirstName, PEO_LastName, PEO_DoB
</span></span><span style="display:flex;"><span><span style="color:#75715e">-----------------------------------------------------
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#ae81ff">1</span>             John           Jones         <span style="color:#ae81ff">1984</span><span style="color:#f92672">-</span><span style="color:#ae81ff">07</span><span style="color:#f92672">-</span><span style="color:#ae81ff">15</span>
</span></span></code></pre></div><p>I believe the idea was so that when querying, you would not have any column name clashes.  This of course breaks down if you have to join on the same table twice.</p>
<p>This structure presents a problem when it comes to reading the tables into objects in code, as it removes the ability to use an orm - I have yet to see one which allows you to specify a prefix to be used on all columns in a table.</p>
<p>The existing entities are all manually read, and follow the same pattern:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Entity</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Load()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> reader = SqlHelper.ExecuteReader(<span style="color:#e6db74">&#34;connectionstring&#34;</span>, ReadProcedureName))
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">if</span> (reader.Read())
</span></span><span style="display:flex;"><span>			{
</span></span><span style="display:flex;"><span>				Read(reader);
</span></span><span style="display:flex;"><span>			}
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Person</span> : Entity
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> ID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> FirstName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> LastName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> DateTime DoB { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">override</span> String ReadProcedureName { <span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;p_getPerson&#34;</span>; } }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Read(IDataReader reader)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		ID = reader.GetInt32(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>		FirstName = reader.GetString(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>		LastName = reader.GetString(<span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>		DoB = reader.GetDateTime(<span style="color:#ae81ff">3</span>);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note how columns are read in order, which means two things: you cannot use <code>select *</code> as your query, and you cannot change column order etc.</p>
<p>To help split this so we can start using an ORM to do the mapping for us, we can utilise the <a href="http://www.dofactory.com/Patterns/PatternMemento.aspx">Memento Pattern</a>.  First we create a new object, which will be used to read and write from the database:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PersonDto</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> PEO_ID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> PEO_FirstName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> PEO_LastName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> DateTime PEO_DoB { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note the property names match the column names of the table in the db, our read method could then get changed to this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Entity</span>&lt;TDto&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">string</span> ReadProcedureName { <span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;&#34;</span>; } }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Load()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> results = _connection.Query&lt;TDto&gt;(ReadProcedureName).ToList();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (results.Any())
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			Read(results.First());
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">void</span> Read(TDto dto)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Person</span> : Entity&lt;PersonDto&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> ID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> FirstName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> LastName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> DateTime DoB { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Read(PersonDto dto)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		ID = dto.PEO_ID;
</span></span><span style="display:flex;"><span>		FirstName = dto.PEO_FirstName;
</span></span><span style="display:flex;"><span>		LastName = dto.PEO_LastName;
</span></span><span style="display:flex;"><span>		DoB = dto.PEO_DoB;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This gives us several benefits, in that we can change column naming and ordering freely without effecting the actual <code>Person</code> object, and we have made the class slightly more testable - we can pass it a faked <code>PersonDto</code> if we needed to load it with some data for a test.</p>
<p>We can however make another improvement to this - namely in the <code>Read</code> method, as this is a prime candidate for <a href="http://automapper.org/">AutoMapper</a>.  To get this to work though, have two choices: the first is to manually specify the mappings of one object to the other, and the second is to write a profile which will do the work for us.  Unsurprisingly, I went with the second option:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PrefixProfile</span> : Profile
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IDictionary&lt;Type, Type&gt; _typeMap;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> PrefixProfile(IDictionary&lt;Type, Type&gt; typeMap )
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_typeMap = typeMap;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">string</span> ProfileName
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;PrefixProfile&#34;</span>; }
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Configure()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">foreach</span> (<span style="color:#66d9ef">var</span> pair <span style="color:#66d9ef">in</span> _typeMap)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">var</span> prefix = GetPrefix(pair.Value.GetProperties());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			RecognizeDestinationPrefixes(prefix);
</span></span><span style="display:flex;"><span>			RecognizePrefixes(prefix);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			CreateMap(pair.Key, pair.Value);
</span></span><span style="display:flex;"><span>			CreateMap(pair.Value, pair.Key);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">string</span> GetPrefix(IEnumerable&lt;PropertyInfo&gt; properties)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> properties
</span></span><span style="display:flex;"><span>			.Select(GetPrefixFromProperty)
</span></span><span style="display:flex;"><span>			.FirstOrDefault(p =&gt; String.IsNullOrWhiteSpace(p) == <span style="color:#66d9ef">false</span>);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">string</span> GetPrefixFromProperty(PropertyInfo property)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> name = property.Name;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> name.IndexOf(<span style="color:#e6db74">&#34;_&#34;</span>, StringComparison.OrdinalIgnoreCase) &gt;= <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>			? name.Substring(<span style="color:#ae81ff">0</span>, name.IndexOf(<span style="color:#e6db74">&#34;_&#34;</span>, StringComparison.OrdinalIgnoreCase) + <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>			: String.Empty;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This class takes in a dictionary of types (in this case will be things like <code>Person</code> =&gt; <code>PersonDto</code>).  It goes through each pair in the list and determines the prefix for the destination class (the dto).  The <code>GetPrefixFromProperty</code> is virtual so that I can customise it for other uses later.</p>
<p>To use this we just need to initialise AutoMapper with the class once on start up:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> map = <span style="color:#66d9ef">new</span> Dictionary&lt;Type, Type&gt;();
</span></span><span style="display:flex;"><span>map.Add(<span style="color:#66d9ef">typeof</span> (Person), <span style="color:#66d9ef">typeof</span> (PersonDto));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Mapper.Initialize(config =&gt; config.AddProfile(<span style="color:#66d9ef">new</span> PrefixProfile(map)));
</span></span></code></pre></div><p>This means our <code>Person</code> class becomes very small:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Person</span> : Entity&lt;PersonDto&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> ID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> FirstName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> LastName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> DateTime DoB { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And the <code>Entity</code> class can take care of the mapping for us, but utilising AutoMapper&rsquo;s Type based Map method:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Entity</span>&lt;TDto&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">string</span> ReadProcedureName { <span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;&#34;</span>; } }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Load()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> _connection = <span style="color:#66d9ef">new</span> SqlConnection(<span style="color:#e6db74">&#34;&#34;</span>);
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> results = _connection.Query&lt;TDto&gt;(ReadProcedureName).ToList();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (results.Any())
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			Read(results.First());
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">void</span> Read(TDto dto)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		Mapper.Map(dto, <span style="color:#66d9ef">this</span>, <span style="color:#66d9ef">typeof</span>(TDto), GetType());
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>While the design of having each entity responsible for saving and loading of itself is not the best design, it is what the existing system has in place (around 400 entities exist at last count).  By taking these steps we can remove a lot of boilerplate code from our codebase, which means when we wish to change to a different architecture (such as session or transaction objects in a similar style to RavenDB&rsquo;s ISession), it will be an easier transition.</p>
]]></content:encoded></item><item><title>SOLID Principles - DIP</title><link>https://andydote.co.uk/2014/03/15/solid-principles-dip/</link><pubDate>Sat, 15 Mar 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/03/15/solid-principles-dip/</guid><description>Single Responsibility | Open Closed | Liskov Substitution | Interface Segregation | Dependency Inversion
The Dependency Inversion Principle states that &amp;ldquo;Depend upon Abstractions. Do not depend upon concretions&amp;rdquo;. A good real world example of this is plug sockets around your house; any device you buy can be plugged into any socket in your house. You don&amp;rsquo;t have to buy new set of devices when you move house, and you don&amp;rsquo;t have to buy a new house for your devices!</description><content:encoded><![CDATA[<p><a href="http://andydote.co.uk/solid-principles-srp">Single Responsibility</a> | <a href="http://andydote.co.uk/solid-principles-ocp">Open Closed</a> | <a href="http://andydote.co.uk/solid-principles-lsp">Liskov Substitution</a> | <a href="http://andydote.co.uk/solid-principles-isp">Interface Segregation</a> | <a href="http://andydote.co.uk/solid-principles-dip">Dependency Inversion</a></p>
<p>The Dependency Inversion Principle states that &ldquo;Depend upon Abstractions. Do not depend upon concretions&rdquo;.  A good real world example of this is plug sockets around your house; any device you buy can be plugged into any socket in your house.  You don&rsquo;t have to buy new set of devices when you move house, and you don&rsquo;t have to buy a new house for your devices!</p>
<p>In software terms this means that our higher level classes should not directly depend on lower level classes, but should depend on some intermediary.  The same goes for depending on external resources.  For example, if you have this class which takes a request string, and deserializes it, and does something with the resulting object:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">RequestHandler</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> OnRequestReceived(<span style="color:#66d9ef">string</span> json)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">var</span> data = NewtonSoftJson.Deserialize&lt;RequestData&gt;(json);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>				Console.WriteLine(data.Name + <span style="color:#e6db74">&#34; Received.&#34;</span>);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This has two problems - the first is that it is totally dependant on the <code>NewtonSoftJson</code> class which means we are in violation of the Dependency Inversion Principle, and also we are tied to a specific provider.  We also are using a static method on the <code>NewtonSoftJson</code> class, which makes the method impossible to test, if we didn&rsquo;t want to depend on <code>NewtonSoftJson</code> for our test.</p>
<p>We can move towards fixing both of these problems by adding an interface, and depending on that for serialization instead:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IJsonSerializer</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>		T Deserialize&lt;T&gt;(<span style="color:#66d9ef">string</span> json);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">JsonSerializer</span> : IJsonSerializer
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">public</span> T Deserialize&lt;T&gt;(<span style="color:#66d9ef">string</span> json)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">return</span> NewtonSoftJson.Deserialize&lt;T&gt;(json);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">RequestHandler</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IJsonSerializer _serializer;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">public</span> RequestHandler(IJsonSerializer serializer)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>				_serializer = serializer;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> OnRequestReceived(<span style="color:#66d9ef">string</span> json)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">var</span> data = _serializer.Deserialize&lt;RequestData&gt;(json);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>				Console.WriteLine(data.Name + <span style="color:#e6db74">&#34; Received.&#34;</span>);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>By doing this, the <code>RequestHandler</code> class is now dependant on an abstraction rather than a concretion.  This nets us many benefits:  We are no longer directly dependant on <code>NewtonSoftJson</code>, our <code>OnRequestReceived</code> method has become more testable, and we have also centralised our json serialization logic.</p>
<p>This means that if we wish to change to a different library for json serialization (or use the <code>JavaScriptSerializer</code> built into the .net framework) we can just create a new class which implements <code>IJsonSerializer</code> and pass an instance of the new class to <code>RequestHandler</code>.  It also means that anywhere we want to do json serialization can just take an <code>IJsonSerializer</code> in as a dependency, and not care what the dependency is actually doing when <code>Deserialize</code> is called.</p>
<p>Hopefully this explains a little more on how inverting your dependencies can help make your software more flexible, and more maintainable.</p>
<p>All source code is available on my Github: <a href="https://github.com/Pondidum/Solid.Demo">Solid.Demo Source Code</a></p>
]]></content:encoded></item><item><title>SOLID Principles - ISP</title><link>https://andydote.co.uk/2014/03/01/solid-principles-isp/</link><pubDate>Sat, 01 Mar 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/03/01/solid-principles-isp/</guid><description>Interface Segregation Principle Single Responsibility | Open Closed | Liskov Substitution | Interface Segregation | Dependency Inversion
Interface Segregation I find is often ignored, or people tend not to see the point in. Segregating your Interfaces is a very useful way of reducing compexity in your systems, and comes with a number of benefits, such as making mocking inputs easier, and making your objects smaller and simpler.
So as usual, lets start off with an set of types which don&amp;rsquo;t adhere to the principle.</description><content:encoded><![CDATA[<h2 id="interface-segregation-principle">Interface Segregation Principle</h2>
<p><a href="http://andydote.co.uk/solid-principles-srp">Single Responsibility</a> | <a href="http://andydote.co.uk/solid-principles-ocp">Open Closed</a> | <a href="http://andydote.co.uk/solid-principles-lsp">Liskov Substitution</a> | <a href="http://andydote.co.uk/solid-principles-isp">Interface Segregation</a> | <a href="http://andydote.co.uk/solid-principles-dip">Dependency Inversion</a></p>
<p>Interface Segregation I find is often ignored, or people tend not to see the point in.  Segregating your Interfaces is a very useful way of reducing compexity in your systems, and comes with a number of benefits, such as making mocking inputs easier, and making your objects smaller and simpler.</p>
<p>So as usual, lets start off with an set of types which don&rsquo;t adhere to the principle.  Starting off, we have the following interface, which we are using to write data access classes with:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IEntity</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	Guid ID { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> Save();
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> Load();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And a class which implements the interface:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Entity</span> : IEntity
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Guid ID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Save()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		Database.Save(<span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Load()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> reader = Database.Load(ID))
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			ID = reader.GetGuid(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>			Read(reader);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">void</span> Read(IDataReader reader)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//nothing in the base</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>At first glance, this seems like a pretty reasonable Entity, it doesn&rsquo;t have multiple responsibilities, and it is very simple. However, when we bring the second implementation of <code>IEntity</code> into the mix, it becomes more clear that some segregation would be useful:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ReadOnlyEntity</span> : IEntity
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Guid ID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Save()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//do nothing</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Load()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> reader = Database.Load(ID))
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			ID = reader.GetGuid(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>			Read(reader);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">void</span> Read(IDataReader reader)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//nothing in the base</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Why would a <code>ReadOnlyEntity</code> need a <code>Save()</code> method? What happens if you have a collection of data which gets loaded from your database, but never gets saved back (a list of countries and associated data for example.)  Also, consumers of the <code>IEntity</code> interface get more access to methods than they need, for example the <code>Database</code> class being used here:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Database</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> Save(IEntity entity)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		entity.Load();	<span style="color:#75715e">//?</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>From looking at our usages of our entities, we can see there are two specific roles: something that can be loaded, and something that can be saved.  We start our separation by inheriting our existing interface:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IEntity</span> : ISaveable, ILoadable
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">ISaveable</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	Guid ID { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> Save();
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">ILoadable</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	Guid ID { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> Load();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Here we have pulled the method and properties relevant for saving into one interface, and the methods and properties relevant to loading into another.  By making <code>IEntity</code> inherit both <code>ISaveable</code> and <code>ILoadable</code>, we have no need to change any existing code yet.</p>
<p>Our next step is to change usages of <code>IEntity</code> to take in the more specific interface that they require:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Database</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> Save(ISaveable entity)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Once this is done, we can remove the <code>IEntity</code> interface, and update our implementations to use <code>ISaveable</code> and <code>ILoadable</code> instead:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Entity</span> : ISaveable, ILoadable
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Guid ID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Save()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		Database.Save(<span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Load()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> reader = Database.Load(ID))
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			ID = reader.GetGuid(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>			Read(reader);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">void</span> Read(IDataReader reader)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//nothing in the base</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ReadOnlyEntity</span> : ILoadable
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Guid ID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Load()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> reader = Original.Database.Load(ID))
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			ID = reader.GetGuid(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>			Read(reader);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">void</span> Read(IDataReader reader)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//nothing in the base</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Now our objects are showing specifically what they are capable of - the <code>ReadOnlyEntity</code> doesn&rsquo;t have a <code>Save()</code> method which you are not supposed to call!</p>
<p>If you do have a method which requires an object which is both an <code>ISaveable</code> and an <code>ILoadable</code>, rather than pass in the same object to two parameters, you can achieve it with a generic parameter:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> DoSomething&lt;T&gt;(T entity) <span style="color:#66d9ef">where</span> T : ISaveable, ILoadable
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	entity.Save();
</span></span><span style="display:flex;"><span>	entity.Load();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Hopefully this shows the reasoning of segregating your interfaces and the steps to segregate existing interfaces.</p>
<p>All source code is available on my Github: <a href="https://github.com/Pondidum/Solid.Demo">Solid.Demo Source Code</a></p>
]]></content:encoded></item><item><title>SOLID Principles - LSP</title><link>https://andydote.co.uk/2014/02/23/solid-principles-lsp/</link><pubDate>Sun, 23 Feb 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/02/23/solid-principles-lsp/</guid><description>Liskov Substitution Principle Single Responsibility | Open Closed | Liskov Substitution | Interface Segregation | Dependency Inversion
The Liskov Substitution Principle is states:
If S is a sub-type of T, then objects of type T maybe replaced with objects of type S
At face value, it means that a small class hierarchy like this:
public class FileEntry { } public class DbFileEntry : FileEntry { } And a method which takes in a FileEntry, can be called like this:</description><content:encoded><![CDATA[<h2 id="liskov-substitution-principle">Liskov Substitution Principle</h2>
<p><a href="http://andydote.co.uk/solid-principles-srp">Single Responsibility</a> | <a href="http://andydote.co.uk/solid-principles-ocp">Open Closed</a> | <a href="http://andydote.co.uk/solid-principles-lsp">Liskov Substitution</a> | <a href="http://andydote.co.uk/solid-principles-isp">Interface Segregation</a> | <a href="http://andydote.co.uk/solid-principles-dip">Dependency Inversion</a></p>
<p>The Liskov Substitution Principle is states:</p>
<blockquote>
<p>If <strong>S</strong> is a sub-type of <strong>T</strong>, then objects of type <strong>T</strong> maybe replaced with objects of type <strong>S</strong></p>
</blockquote>
<p>At face value, it means that a small class hierarchy like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">FileEntry</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">DbFileEntry</span> : FileEntry
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And a method which takes in a <code>FileEntry</code>, can be called like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>ProcessFile(<span style="color:#66d9ef">new</span> FileEntry());
</span></span></code></pre></div><p>Or like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>ProcessFile(<span style="color:#66d9ef">new</span> DbFileEntry());
</span></span></code></pre></div><p>This however only takes the principle at face value, and would not provide much value.  However, just because a class implements the expected interface does not necessarily mean that it can be a drop in replacement for another implementation.  This can be down to a number of factors, such as side effects of methods (like different kinds of exception being thrown), and external modification of state.</p>
<h3 id="side-effects">Side Effects</h3>
<p>In this example, you can see that the methods both have a pre-condition on some internal data, but as they throw different kinds of exceptions, they violate the principle:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">FileEntry</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">void</span> Process()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (File.Exists(Path) == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> FileNotFoundException(Path);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//do work</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">DbFileEntry</span> : FileEntry
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Process()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (Database.Contains(_id) == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> KeyNotFoundException(_id.ToString());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//do work</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The reason for this being a violation is due to what the calling code is expecting to handle:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> RunFiles(IEnumerable&lt;FileEntry&gt; files)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">foreach</span> (<span style="color:#66d9ef">var</span> file <span style="color:#66d9ef">in</span> files)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">try</span>
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			file.Process();
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">catch</span> (FileNotFoundException ex)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			_fails.Add(file.Name);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This method when called with a list of <code>FileEntry</code> will run every entry, and add the names of any which failed to a collection for later use.  However if it were called with a list of <code>DbFileEntry</code>, the first file to fail would cause then entire method to fail, and no more files would be processed.</p>
<p>Fixing the classes so they obey the LSP could be done by changing the <code>DbFileEntry</code> to throw the same kind of exception as the <code>FileEntry</code>, but the exception type <code>FileNotFoundException</code> wouldn&rsquo;t make sense in the context of a database.</p>
<p>The solution is to create a new exception type which the <code>Process</code> methods with throw, and that the <code>RunFiles</code> method will catch:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">FileEntry</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">void</span> Process()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (File.Exists(Path) == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> FileEntryProcessException(FileNotFoundException(Path));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//do work</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">DbFileEntry</span> : FileEntry
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Process()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (_database.Contains(_id) == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> FileEntryProcessException(KeyNotFoundException(_id));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//do work</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> RunFiles(IEnumerable&lt;FileEntry&gt; files)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">foreach</span> ( <span style="color:#66d9ef">var</span> file <span style="color:#66d9ef">in</span> files)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">try</span>
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			file.Process();
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">catch</span> (FileEntryProcessException ex)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			_fails.Add(file.Name);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>By keeping the original exceptions we were going to throw as the <code>.InnerException</code> property of our new <code>FileEntryProcessException</code> we can still preserve the more specific exceptions, while allowing the <code>RunFiles</code> method to catch it.</p>
<p>An alternate solution to this would be to have two new specific exception types, which both inherit a single type:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ProcessException</span> : Exception()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">FileNotFoundProcessException</span> : ProcessException
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> FileNotFoundProcessException(String path)
</span></span><span style="display:flex;"><span>	{}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">KeyNotFoundProcessException</span> : ProcessException
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> KeyNotFoundProcessException(Guid id)
</span></span><span style="display:flex;"><span>	{}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The problem with this approach is that you are hoping that all consumers of <code>FileEntry</code> are catching <code>ProcessException</code>, rather than one of it&rsquo;s sub-classes.  By using the first solution, you are forcing the consumer to catch your one exception type.</p>
<h3 id="state-mutation">State Mutation</h3>
<p>Extra methods on a sub class can cause a violation of the Liskov Substitution Principle too; by mutating state, and causing calling code to make un-expected transitions.  Take this for example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">DefaultStateGenerator</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">int</span> _state;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> GetNextStateID(<span style="color:#66d9ef">int</span> currentState)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> Math.Min(++currentState, <span style="color:#ae81ff">3</span>);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">StateMachine</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> StateMachine(IStateGenerator generator)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_generator = generator;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Transition()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> newState = _generator.GetNextStateID(_currentState);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">switch</span> (newState)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">case</span> <span style="color:#ae81ff">0</span>:
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">break</span>; <span style="color:#75715e">//do nothing</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">case</span> <span style="color:#ae81ff">1</span>:
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">break</span>; <span style="color:#75715e">//do nothing</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">case</span> <span style="color:#ae81ff">2</span>:
</span></span><span style="display:flex;"><span>				PayTheMan();
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		_currentState = newState;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Using the <code>DefaultStateGenerator</code> will cause the state machine to work as expected - it will transition through the states, calling <code>PayTheMan</code> one on state 2, and then just sticking at state 3 for subsequent calls.  However, if you were to use the <code>EvilStateGenerator</code> things might be a bit different:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">EvilStateGenerator</span> : IStateGenerator
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">bool</span> _evil;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> GetNextStateID(<span style="color:#66d9ef">int</span> currentState)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> _evil ? <span style="color:#ae81ff">2</span> : Math.Min(++currentState, <span style="color:#ae81ff">3</span>);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> BeEvil()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_evil = <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This <code>EvilStateGenerator</code> works as usual, until a call to its <code>BeEvil</code> method gets called, at which point it will return state 2 every time, causing the <code>PayTheMan</code> method to be called on every <code>Transition</code>.</p>
<p>Hopefully these two examples provide sufficient reason for paying attention to the Liskov Substitution Principle.</p>
<p>All source code is available on my Github: <a href="https://github.com/Pondidum/Solid.Demo">Solid.Demo Source Code</a></p>
]]></content:encoded></item><item><title>SOLID Principles - OCP</title><link>https://andydote.co.uk/2014/02/19/solid-principles-ocp/</link><pubDate>Wed, 19 Feb 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/02/19/solid-principles-ocp/</guid><description>Open Closed Principle Single Responsibility | Open Closed | Liskov Substitution | Interface Segregation | Dependency Inversion
The Open Closed Principle is one that I often find is miss-understood - how can something be open for extension, but closed for modification? A good example of this principle being implemented cropped up at work a while ago, we had a UI element which has a reusable grid, which gets populated with data based on a menu selection.</description><content:encoded><![CDATA[<h2 id="open-closed-principle">Open Closed Principle</h2>
<p><a href="http://andydote.co.uk/solid-principles-srp">Single Responsibility</a> | <a href="http://andydote.co.uk/solid-principles-ocp">Open Closed</a> | <a href="http://andydote.co.uk/solid-principles-lsp">Liskov Substitution</a> | <a href="http://andydote.co.uk/solid-principles-isp">Interface Segregation</a> | <a href="http://andydote.co.uk/solid-principles-dip">Dependency Inversion</a></p>
<p>The Open Closed Principle is one that I often find is miss-understood - how can something be open for extension, but closed for modification?
A good example of this principle being implemented cropped up at work a while ago, we had a UI element which has a reusable grid, which gets populated with data based on a menu selection.  The user can also add, edit and delete items from the grids.</p>
<p>The class was originally implemented something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UserGrid</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> UserGrid()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_menu.Add(<span style="color:#66d9ef">new</span> ToolStripMenuItem { Text = <span style="color:#e6db74">&#34;Emails&#34;</span>, Tag = MenuTypes.Emails });
</span></span><span style="display:flex;"><span>		_menu.Add(<span style="color:#66d9ef">new</span> ToolStripMenuItem { Text = <span style="color:#e6db74">&#34;Addresses&#34;</span>, Tag = MenuTypes.Addresses });
</span></span><span style="display:flex;"><span>		_menu.Add(<span style="color:#66d9ef">new</span> ToolStripMenuItem { Text = <span style="color:#e6db74">&#34;Phone Numbers&#34;</span>, Tag = MenuTypes.Phones });
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Populate()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> selection = GetMenuSelection();
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> rows = <span style="color:#66d9ef">new</span> List&lt;DataGridViewRow&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">switch</span> (selection)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">case</span> MenuTypes.Emails:
</span></span><span style="display:flex;"><span>				rows.AddRange(_user.EmailAddresses);
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">case</span> MenuTypes.Addresses:
</span></span><span style="display:flex;"><span>				rows.AddRange(_user.Addresses);
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">case</span> MenuTypes.Phones:
</span></span><span style="display:flex;"><span>				rows.AddRange(_user.PhoneNumbers);
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		_grid.Rows.Clear();
</span></span><span style="display:flex;"><span>		_grid.Rows.AddRange(rows.ToArray());
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> OnAddClicked()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> selection = GetMenuSelection();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">switch</span> (selection)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">case</span> MenuTypes.Emails:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">var</span> emailEditor = <span style="color:#66d9ef">new</span> EmailEditor(<span style="color:#66d9ef">new</span> Email());
</span></span><span style="display:flex;"><span>				emailEditor.ShowDialog();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">case</span> MenuTypes.Addresses:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">var</span> addressEditor = <span style="color:#66d9ef">new</span> AddressEditor(<span style="color:#66d9ef">new</span> Address());
</span></span><span style="display:flex;"><span>				addressEditor.ShowDialog();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">case</span> MenuTypes.Phones:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">var</span> phoneEditor = <span style="color:#66d9ef">new</span> PhoneEditor(<span style="color:#66d9ef">new</span> Phone());
</span></span><span style="display:flex;"><span>				phoneEditor.ShowDialog();
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I haven&rsquo;t listed all the methods here, but you get the idea - a lot of repeated-ish code (switch statements), and when you want to add a new grid type you have to do the following steps:</p>
<ul>
<li>Add a new entry to the MenuTypes enum.</li>
<li>Add the new menu item in the constructor.</li>
<li>Add an implementation to the Populate method.</li>
<li>Add an implementation for each action to the add, edit and delete methods.</li>
</ul>
<p>This pretty much defines the opposite of the Open Closed Principle - the class has to be edited to add in any new functionality, and grows larger each time.  Throw in some more logic to the class, such as:</p>
<ul>
<li>You cannot edit Addresses, they can only be added or removed.</li>
<li>You can only delete an Email if it was added less than 1 week ago.</li>
<li>A Super User can do anything.</li>
<li>A General User can only view items.</li>
</ul>
<p>and you are asking for trouble, and when those requirements change or get added to, you will have to go back through all the different methods to make sure your logic holds true.</p>
<h2 id="the-solution">The Solution</h2>
<p>In a similar way to how we handled refactoring and improving the code of the <code>JobPostingService</code> in the last post, we can make a set of small steps to improve this class.</p>
<p>Unlike the last solution, we are going to use an abstract class as our base, rather than an Interface.  This is picked as we have some methods which are optional (see the first requirement), so we may not wish to implement all methods.</p>
<p>Our first step is to create our base class:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">GridHandler</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> User User { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> String Title { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> IEnumerable&lt;DataGridViewRow&gt; Populate();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">void</span> Add()
</span></span><span style="display:flex;"><span>	{}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">void</span> Edit(<span style="color:#66d9ef">object</span> item)
</span></span><span style="display:flex;"><span>	{}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">void</span> Delete(<span style="color:#66d9ef">object</span> item)
</span></span><span style="display:flex;"><span>	{}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note that the <code>Title</code> property and <code>Populate</code> method are abstract - you must implement these at the very least to be a <code>GridHandler</code>.
At the same time as this, we will lay our groundwork in the <code>UserGrid</code> class:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UserGrid</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> List&lt;GridHandler&gt; _handlers;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> UserGrid()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_handlers = <span style="color:#66d9ef">new</span> List&lt;GridHandler&gt;();
</span></span><span style="display:flex;"><span>		_grid = <span style="color:#66d9ef">new</span> DataGridView();
</span></span><span style="display:flex;"><span>		_menu = <span style="color:#66d9ef">new</span> List&lt;ToolStripMenuItem&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		_menu.Add(<span style="color:#66d9ef">new</span> ToolStripMenuItem { Text = <span style="color:#e6db74">&#34;Emails&#34;</span>, Tag = MenuTypes.Emails });
</span></span><span style="display:flex;"><span>		_menu.Add(<span style="color:#66d9ef">new</span> ToolStripMenuItem { Text = <span style="color:#e6db74">&#34;Addresses&#34;</span>, Tag = MenuTypes.Addresses });
</span></span><span style="display:flex;"><span>		_menu.Add(<span style="color:#66d9ef">new</span> ToolStripMenuItem { Text = <span style="color:#e6db74">&#34;Phone Numbers&#34;</span>, Tag = MenuTypes.Phones });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> AddHandler(GridHandler handler)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_handlers.Add(handler);
</span></span><span style="display:flex;"><span>		_menu.Add(<span style="color:#66d9ef">new</span> ToolStripMenuItem { Text = handler.Title });
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> SetUser(User user)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_user = user;
</span></span><span style="display:flex;"><span>		_handlers.ForEach(handler =&gt; handler.User = user);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Populate()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> handler = GetHandlerForSelection();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (handler != <span style="color:#66d9ef">null</span>)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			_grid.Rows.Clear();
</span></span><span style="display:flex;"><span>			_grid.Rows.AddRange(handler.Populate().ToArray());
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> selection = GetMenuSelection();
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> rows = <span style="color:#66d9ef">new</span> List&lt;DataGridViewRow&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">switch</span> (selection)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">case</span> MenuTypes.Emails:
</span></span><span style="display:flex;"><span>				rows.AddRange(_user.EmailAddresses);
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">case</span> MenuTypes.Addresses:
</span></span><span style="display:flex;"><span>				rows.AddRange(_user.Addresses);
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">case</span> MenuTypes.Phones:
</span></span><span style="display:flex;"><span>				rows.AddRange(_user.PhoneNumbers);
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		_grid.Rows.Clear();
</span></span><span style="display:flex;"><span>		_grid.Rows.AddRange(rows.ToArray());
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>UserGrid</code> class has had a new method called <code>AddHandler</code>, which allows handlers to be added to the grid.  The <code>SetUser</code> method has been updated to also set the <code>User</code> property on all handlers, and all the <code>Add</code>, <code>Edit</code>, <code>Delete</code> and <code>Populate</code> methods have been updated to attempt to try and use a handler, and if none is found, use the existing implementation.</p>
<p>Our next step is to create the first <code>GridHandler</code>, which will be for Email Addresses:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">EmailGridHandler</span> : GridHandler
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">string</span> Title
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Email Addresses&#34;</span>; }
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> IEnumerable&lt;DataGridViewRow&gt; Populate()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> User.EmailAddresses;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Add()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> email = <span style="color:#66d9ef">new</span> Email();
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> editor = <span style="color:#66d9ef">new</span> EmailEditor(email);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		editor.ShowDialog();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		User.AddEmail(email);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Edit(<span style="color:#66d9ef">object</span> item)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> email = (Email)item;
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> editor = <span style="color:#66d9ef">new</span> EmailEditor(email);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		editor.ShowDialog();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Delete(<span style="color:#66d9ef">object</span> item)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> email = (Email)item;
</span></span><span style="display:flex;"><span>		User.RemoveEmail(email);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As you can see, this class obeys the <a href="http://andydote.co.uk/solid-principles-srp">Single Responsibility Principle</a> as it only deals with how to change data from the <code>User</code> object into data and actions for the grid.</p>
<p>We can now update the usage of our <code>UserGrid</code> to take advantage of the new <code>GridHandler</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Usage</span> : Form
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> UserGrid _grid;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Usage()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_grid = <span style="color:#66d9ef">new</span> UserGrid();
</span></span><span style="display:flex;"><span>		_grid.AddHandler(<span style="color:#66d9ef">new</span> EmailGridHandler());
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>All that remains to be done now is to go through the <code>UserGrid</code> and remove all the code relating to <code>Email</code>s.  The extraction of functionality steps can then be repeated for each of the existing grid types (<code>Address</code> and <code>Phone</code> in our case.)</p>
<p>Once this is done, we can go back to the <code>UserGrid</code> and remove all non-grid code, leaving us with this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UserGrid</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> List&lt;GridHandler&gt; _handlers;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> UserGrid()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_handlers = <span style="color:#66d9ef">new</span> List&lt;GridHandler&gt;();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> AddHandler(GridHandler handler)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_handlers.Add(handler);
</span></span><span style="display:flex;"><span>		_menu.Add(<span style="color:#66d9ef">new</span> ToolStripMenuItem { Text = handler.Title });
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> SetUser(User user)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_handlers.ForEach(handler =&gt; handler.User = user);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Populate()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> handler = GetHandlerForSelection();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (handler != <span style="color:#66d9ef">null</span>)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			_grid.Rows.Clear();
</span></span><span style="display:flex;"><span>			_grid.Rows.AddRange(handler.Populate().ToArray());
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> OnAddClicked()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> handler = GetHandlerForSelection();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (handler != <span style="color:#66d9ef">null</span>)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			handler.Add();
</span></span><span style="display:flex;"><span>			Populate();
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As you can see, the <code>UserGrid</code> class is now much smaller, and has no user specific logic in it.  This means we don&rsquo;t need to modify the class when we want to add a new grid type (it is <strong>closed for modification</strong>), but as adding new functionality to the grid just consists of another call to <code>.AddHandler(new WebsiteGridHandler());</code> we have made it <strong>open for extension</strong>.</p>
<p>All source code is available on my Github: <a href="https://github.com/Pondidum/Solid.Demo">Solid.Demo Source Code</a></p>
]]></content:encoded></item><item><title>SOLID Principles - SRP</title><link>https://andydote.co.uk/2014/02/18/solid-principles-srp/</link><pubDate>Tue, 18 Feb 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/02/18/solid-principles-srp/</guid><description>Single Responsibility Principle Single Responsibility | Open Closed | Liskov Substitution | Interface Segregation | Dependency Inversion
SRP (Single Responsibility Principle) is something I hear a lot of developers agree is a good thing, but when I read their code, they violate it without realising, or don&amp;rsquo;t see the use in their particular case.
A particularly prominent example I find in our code bases is Permissioning and Caching. These two requirements can often slip into classes slowly - especially if requirements are not clear, or change as the task progresses.</description><content:encoded><![CDATA[<h2 id="single-responsibility-principle">Single Responsibility Principle</h2>
<p><a href="http://andydote.co.uk/solid-principles-srp">Single Responsibility</a> | <a href="http://andydote.co.uk/solid-principles-ocp">Open Closed</a> | <a href="http://andydote.co.uk/solid-principles-lsp">Liskov Substitution</a> | <a href="http://andydote.co.uk/solid-principles-isp">Interface Segregation</a> | <a href="http://andydote.co.uk/solid-principles-dip">Dependency Inversion</a></p>
<p>SRP (Single Responsibility Principle) is something I hear a lot of developers agree is a good thing, but when I read their code, they violate it without realising, or don&rsquo;t see the use in their particular case.</p>
<p>A particularly prominent example I find in our code bases is Permissioning and Caching.  These two requirements can often slip into classes slowly - especially if requirements are not clear, or change as the task progresses.  A slightly contrived example is this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">JobPostingService</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">readonly</span> TimeSpan Timeout = <span style="color:#66d9ef">new</span> TimeSpan(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">10</span>, <span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> JobWebService _jobService;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> List&lt;Job&gt; _jobs;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> DateTime _lastLoaded;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> JobPostingService()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_jobService = <span style="color:#66d9ef">new</span> JobWebService();
</span></span><span style="display:flex;"><span>		_lastLoaded = DateTime.MinValue;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> IEnumerable&lt;Job&gt; GetCurrentJobs()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (_lastLoaded - DateTime.Now &gt; Timeout)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			_jobs = _jobService.GetLiveJobs().ToList();
</span></span><span style="display:flex;"><span>			_lastLoaded = DateTime.Now;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> _jobs;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> PostToFreeBoards(Job job)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> jobs = GetCurrentJobs();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (jobs.Any(j =&gt; j.ID == job.ID))
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		_jobService.Post(job, Boards.FreeBoard1 | Boards.FreeBoard2);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> PostToAllBoards(Job job)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> jobs = GetCurrentJobs();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (jobs.Any(j =&gt; j.ID == job.ID))
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		_jobService.Post(job, Boards.PaidBoard1 | Boards.PaidBoard2);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This class is fairly small, but it is already showing the symptoms of doing too many things; it is dealing with caching, as well as posting jobs.  While this is not a major problem at the moment, it is also easier to nip the problem in the bud - before a load of new requirements/changes arrive and complicate things.</p>
<h2 id="the-solution">The Solution</h2>
<p>We start off by changing our class to take it&rsquo;s dependencies in via constructor parameters (Dependency Injection, the &lsquo;D&rsquo; in SOLID):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> JobPostingService(JobWebService jobService)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	_jobService = jobService;
</span></span><span style="display:flex;"><span>	_lastLoaded = DateTime.MinValue;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>So the usage of the <code>JobPostingService</code> goes from this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> poster = <span style="color:#66d9ef">new</span> JobPostingService();
</span></span></code></pre></div><p>To this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> poster = <span style="color:#66d9ef">new</span> JobPostingService(<span style="color:#66d9ef">new</span> JobWebService());
</span></span></code></pre></div><p>Next, we take the <code>JobWebService</code> class and extract &amp; implement an interface of it&rsquo;s methods:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IJobService</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	IEnumerable&lt;Job&gt; GetLiveJobs();
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">bool</span> Post(Job job, Boards boards);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">JobWebService</span> : IJobService
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">//...</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And finally, create a new class which only deals with caching the results of a JobService, by wrapping calls to another instance:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">CachedJobService</span> : IJobService
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> List&lt;Job&gt; _jobs;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> DateTime _lastLoaded;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> TimeSpan _timeout;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IJobService _other;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> CachedJobService(IJobService otherService)
</span></span><span style="display:flex;"><span>		: <span style="color:#66d9ef">this</span>(otherService, <span style="color:#66d9ef">new</span> TimeSpan(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">10</span>, <span style="color:#ae81ff">0</span>))
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> CachedJobService(IJobService otherService, TimeSpan timeout)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_other = otherService;
</span></span><span style="display:flex;"><span>		_timeout = timeout;
</span></span><span style="display:flex;"><span>		_lastLoaded = DateTime.MinValue;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> IEnumerable&lt;Job&gt; GetLiveJobs()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (_lastLoaded - DateTime.Now &gt; _timeout)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			_jobs = _other.GetLiveJobs().ToList();
</span></span><span style="display:flex;"><span>			_lastLoaded = DateTime.Now;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> _jobs;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">bool</span> Post(Job job, Boards boards)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> _other.Post(job, boards);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This class passes all <code>Post()</code> calls to the other implementation, but caches the results of calls to <code>GetLiveJobs()</code>, and we have added a time-out as an optional constructor parameter.  This wrapping calls to another implementation is called <a href="http://en.wikipedia.org/wiki/Decorator_pattern">The Decorator Pattern</a>.</p>
<p>As the JobPostingService class no longer has to cache the results of calls to <code>JobService</code> itself, we can delete all the caching related code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">JobPostingService</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IJobService _jobService;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> JobPostingService(IJobService jobService)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_jobService = jobService;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> IEnumerable&lt;Job&gt; GetCurrentJobs()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> _jobService.GetLiveJobs();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> PostToFreeBoards(Job job)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> jobs = GetCurrentJobs();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (jobs.Any(j =&gt; j.ID == job.ID))
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		_jobService.Post(job, Boards.FreeBoard1 | Boards.FreeBoard2);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> PostToAllBoards(Job job)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> jobs = GetCurrentJobs();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (jobs.Any(j =&gt; j.ID == job.ID))
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		_jobService.Post(job, Boards.PaidBoard1 | Boards.PaidBoard2);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And our usage changes again, from this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> poster = <span style="color:#66d9ef">new</span> JobPostingService(<span style="color:#66d9ef">new</span> JobWebService());
</span></span></code></pre></div><p>To this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> webService = <span style="color:#66d9ef">new</span> CachedJobService(<span style="color:#66d9ef">new</span> JobWebService());
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> poster = <span style="color:#66d9ef">new</span> JobPostingService(webService);
</span></span></code></pre></div><p>We have now successfully extracted all the various pieces of functionality into separate classes, which has gained us the ability to test individual features (caching can be tested with a fake <code>IJobService</code> and checked to see when calls go through to the service), and the ability to adapt more easily to new requirements.  Talking of which&hellip;</p>
<blockquote>
<p>New Requirement:  The third party webservice is not always available, allow use of a fallback webservice.</p>
</blockquote>
<p>Now you could go and modify the <code>JobPostingService</code> class to have a second webservice parameter:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> primaryService = <span style="color:#66d9ef">new</span> CachedJobService(<span style="color:#66d9ef">new</span> JobWebService());
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> secondaryService = <span style="color:#66d9ef">new</span> CachedJobService(<span style="color:#66d9ef">new</span> BackupWebService());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> poster = <span style="color:#66d9ef">new</span> JobPostingService(primaryService, secondaryService);
</span></span></code></pre></div><p>But what happens when a third service is added? and a fourth? Surely there is another way?</p>
<p>As luck would have it, we can use the <code>IJobService</code> interface to create a single class which handles all the logic for switching between the two services:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">FailoverJobService</span> : IJobService
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> List&lt;IJobService&gt; _services;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> FailoverJobService(<span style="color:#66d9ef">params</span> IJobService[] services)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_services = services.ToList();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> IEnumerable&lt;Job&gt; GetLiveJobs()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> _services.SelectMany(s =&gt; s.GetLiveJobs());
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">bool</span> Post(Job job, Boards boards)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> _services.Any(service =&gt; service.Post(job, boards));
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This class takes in a number of <code>IJobService</code>s and will try each one in turn to post jobs, and when listing jobs, gets the results from all services.  In the same manner as the <code>CachedJobService</code>, we have a single class which can easily be tested without effecting any of the other functionality.</p>
<p>The really interesting point comes when we decide when to use caching? do you cache each service passed to the <code>FailoverJobService</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> primaryService = <span style="color:#66d9ef">new</span> CachedJobService(<span style="color:#66d9ef">new</span> JobWebService());
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> secondaryService = <span style="color:#66d9ef">new</span> CachedJobService(<span style="color:#66d9ef">new</span> BackupWebService());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> failover = <span style="color:#66d9ef">new</span> FailoverJobService(primaryService, secondaryService);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> poster = <span style="color:#66d9ef">new</span> JobPostingService(failover);
</span></span></code></pre></div><p>Or do you cache the <code>FailoverJobService</code> itself:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> primaryService = <span style="color:#66d9ef">new</span> JobWebService();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> secondaryService = <span style="color:#66d9ef">new</span> BackupWebService();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> failover = <span style="color:#66d9ef">new</span> CachedJobService(<span style="color:#66d9ef">new</span> FailoverJobService(primaryService, secondaryService));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> poster = <span style="color:#66d9ef">new</span> JobPostingService(failover);
</span></span></code></pre></div><p>Or both?</p>
<p>Hopefully this article has explained 1/5th (maybe a little more, we did do Dependency Injection after all!) of the SOLID principles, and how it can be useful to keep your code as small and modular as possible.</p>
<p>All source code is available on my Github: <a href="https://github.com/Pondidum/Solid.Demo">Solid.Demo Source Code</a></p>
]]></content:encoded></item><item><title>Specialising a General Application</title><link>https://andydote.co.uk/2014/02/02/specialising-a-general-application/</link><pubDate>Sun, 02 Feb 2014 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2014/02/02/specialising-a-general-application/</guid><description>Currently our application at work is used by all employees - sales staff, legal team, marketing, accounts etc. This means we have one very large, and general fit application. It covers everyone&amp;rsquo;s needs just, and the largest group of users (sales in this case) have an application which closely matches what they need. This is at the expense of the other teams having an application that is not quite right - close, but could be better.</description><content:encoded><![CDATA[<p>Currently our application at work is used by all employees - sales staff, legal team, marketing, accounts etc.  This means we have one very large, and general fit application.  It covers everyone&rsquo;s needs <em>just</em>, and the largest group of users (sales in this case) have an application which closely matches what they need.  This is at the expense of the other teams having an application that is not quite right - close, but could be better.</p>
<p>For example, the main UI might look something like this:</p>
<p><img loading="lazy" src="specialised-sales.png" alt="Sales UI"  />
</p>
<p>This is fine for a sales person, who just needs the details on a single person on the system at a time.  However the legal team might only be interested in new contracts and ones which will expire soon.</p>
<p>Adding a report to the existing application which they can then use to find the people with new contracts is one solution, but it still presents them with the same UI - if a person has multiple contracts or many other documents, it won&rsquo;t be particularly helpful to the user.</p>
<p>A better solution would be to give them a separate UI entirely for viewing contracts:</p>
<p><img loading="lazy" src="specialised-legal.png" alt="Legal UI"  />
</p>
<p>This UI has a much closer fit to the Legal team&rsquo;s usage - it only shows the information which is relevant to them, and the actions they can perform are visible and easy to get to.</p>
<p>Implementing UIs like this is a straight forward task - each application has its own data model to display with, which can be a performance increase - each model can be optimized to be as efficient as possible, without having knock-on effects on the other applications.</p>
<p>If this was a web application, you could even make it work out which UI to display based on which user has logged in, rather than deploying one application to some users, and a different application to other users.</p>
<p>Mockups were made using <a href="https://moqups.com/">Moqups.com</a>
Names generated with <a href="http://www.behindthename.com/random/">Behind THe Name</a></p>
]]></content:encoded></item><item><title>Analysis of Frames in World of Warcraft</title><link>https://andydote.co.uk/2013/11/17/analasys-of-frames-in-world-of-warcraft/</link><pubDate>Sun, 17 Nov 2013 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2013/11/17/analasys-of-frames-in-world-of-warcraft/</guid><description>In this post we will be looking at how the Frame and associated objects are (probably) constructed behind the scenes. This will all be done via inspection in lua from the games scripting engine.
The basic display item in Warcraft is the Frame. Frames are not only use for displaying data, but used to listen to events in the background. Another interesting characteristic of a Frame is that you cannot destroy them.</description><content:encoded><![CDATA[<p>In this post we will be looking at how the <code>Frame</code> and associated objects are (probably) constructed behind the scenes.  This will all be done via inspection in lua from the games scripting engine.</p>
<p>The basic display item in Warcraft is the <code>Frame</code>.  Frames are not only use for displaying data, but used to listen to events in the background.  Another interesting characteristic of a <code>Frame</code> is that you cannot destroy them.  Once they are created, Frames exist for the lifetime of the UI (until the player logs out, or reloads their UI.)</p>
<h2 id="first-question">First Question</h2>
<p>A lot of frames are created in the lifetime of the Warcraft UI, so they should be reasonably light weight.  It seems unlikely that all methods are defined on a frame directly, as this would increase a blank/empty frames memory footprint considerably.</p>
<p>Because of this, it would be reasonable to expect that all methods are defined on a metatable, and that a frame created by <code>CreateFrame</code> is just a blank table with a metatable containing all the methods.  A simple implementation of <code>CreateFrame</code> could be:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">CreateFrame</span>(type, name, parent, inherits)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">local</span> widget <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">local</span> meta <span style="color:#f92672">=</span> _metas[type]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	setmetatable(widget, { __index <span style="color:#f92672">=</span> meta })
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	widget:SetName(name)
</span></span><span style="display:flex;"><span>	widget:SetParent(parent)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">--something to handle templates...</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> widget
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>The following function will display all of the methods found on the Frame&rsquo;s metatable:</p>
<h3 id="code">Code:</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> frame <span style="color:#f92672">=</span> CreateFrame(<span style="color:#e6db74">&#34;Frame&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> meta <span style="color:#f92672">=</span> getmetatable(frame)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;meta&#34;</span>, meta)
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;index&#34;</span>, meta.__index)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> name, value <span style="color:#66d9ef">in</span> pairs(meta.__index) <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>	print(name, value)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><h3 id="output">Output:</h3>
<pre><code>meta table: 000000000D42E610
index table: 000000000D42E660
IsMovable function: 000000000D07F140
SetAlpha function: 000000000D07E800
SetScript function: 000000000D07E0C0
...
</code></pre>
<p>Interestingly, if you run this script after reloading your UI, the hash of the meta is the same every time.</p>
<p>The next point to investigate is how other frame types are built up.  As widgets have a hierarchical structure (see the <a href="http://wowprogramming.com/docs/widgets_hierarchy">Widget Hierarchy</a> at wowprogramming.com), it might be the case that the <code>FrameMeta</code> has a metatable of the methods which represent <code>VisibleRegion</code>, <code>Region</code> or <code>ScriptObject</code>. The Widget Hierarchy hints that it won&rsquo;t be a metatable chain, as some widgets inherit multiple other types (e.g. <code>Frame</code> inherits <code>VisibleRegion</code> and <code>ScriptObject</code>).  The following function will recurse metatables, and verify if a <code>Frame</code> and a <code>Button</code> share any metatables:</p>
<h3 id="code-1">Code:</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">printTable</span>(t)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">local</span> meta <span style="color:#f92672">=</span> getmetatable(t)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> meta <span style="color:#66d9ef">then</span> <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> meta.__index <span style="color:#66d9ef">then</span> <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">local</span> index <span style="color:#f92672">=</span> meta.__index
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	print(<span style="color:#e6db74">&#34;meta:&#34;</span>, meta, <span style="color:#e6db74">&#34;meta.index:&#34;</span> index)
</span></span><span style="display:flex;"><span>	printTable(meta)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;Frame:&#34;</span>)
</span></span><span style="display:flex;"><span>printTable(CreateFrame(<span style="color:#e6db74">&#34;Frame&#34;</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;Button:&#34;</span>)
</span></span><span style="display:flex;"><span>printTable(CreateFrame(<span style="color:#e6db74">&#34;Button&#34;</span>))
</span></span></code></pre></div><h3 id="output-1">Output:</h3>
<pre><code>Frame:
meta: table: 000000000C8F8B40 meta.index: table: 000000000C8F8B90
Button:
meta: table: 000000000C8F8BE0 meta.index: table: 000000000C8F8C30
</code></pre>
<p>The output of this indicates that each Widget type has it&rsquo;s own metatable, which helps give a starting point to implementing a new version.</p>
<h2 id="implementing">Implementing</h2>
<p>The <a href="https://github.com/Pondidum/WowInterfakes">WowInterfakes</a> project needs to be able to create all Widgets, so using a similar method as the Warcraft implementation made sense.  As there is no inheritance between Widgets, using a Mixin style for building metatables makes most sense.  The result of building the metatables is stored, and only done once on start up.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> builder <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>builder.init <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	builder.metas <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">local</span> frameMeta <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	builder.applyUIObject(frameMeta)
</span></span><span style="display:flex;"><span>	builder.applyParentedObject(frameMeta)
</span></span><span style="display:flex;"><span>	builder.applyRegion(frameMeta)
</span></span><span style="display:flex;"><span>	builder.applyVisibleRegion(frameMeta)
</span></span><span style="display:flex;"><span>	builder.applyScriptObject(frameMeta)
</span></span><span style="display:flex;"><span>	builder.applyFrame(frameMeta)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	builder.metas.frame <span style="color:#f92672">=</span> { __index <span style="color:#f92672">=</span> frameMeta }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>Each <code>apply</code> method mixes in the functionality for their type.  <code>applyRegion</code> gets reused for a <code>Texture</code> as well as a <code>Frame</code> for example.</p>
<p>Internally, all mixed in methods write and read to a table on the <code>self</code> parameter (called <code>__storage</code>), which holds each widgets values:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span>builder.applyFrame <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(region)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	region.SetBackdrop <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, backdrop)
</span></span><span style="display:flex;"><span>		self.__storage.backdrop <span style="color:#f92672">=</span> backdrop
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	region.RegisterEvent <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, event)
</span></span><span style="display:flex;"><span>		eventRegistry.register(self, event)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	region.CreateTexture <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self, name, layer, inherits, sublevel)
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> builder.createTexture(self, name, layer, inherits, sublevel)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>When <code>createFrame</code> is called, we create a new table with a table in <code>__storage</code>, and apply the standard frame metatable to it.  At this point, the new table is a working <code>Frame</code>, which takes up very little in the way of resources (two tables worth of memory).  Initialisation is finished by populating a few properties (some things like frame name are not publicly accessible, so they are written to the backing <code>__storage</code> directly), and apply any templates specified.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span>builder.createFrame <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(type, name, parent, template)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">local</span> frame <span style="color:#f92672">=</span> { __storage <span style="color:#f92672">=</span> {} }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	setmetatable(frame, builder.metas.frame)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	frame.__storage.name <span style="color:#f92672">=</span> name  <span style="color:#75715e">--no publicly accessable SetName method()</span>
</span></span><span style="display:flex;"><span>	frame:SetParent(parent)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> template <span style="color:#f92672">and</span> template <span style="color:#f92672">~=</span> <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>		templateManager.apply(template, frame)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> frame
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><h2 id="conclusion">Conclusion</h2>
<p>It seems likely that the <code>CreateFrame</code> method in Warcraft is defined in C, rather than in lua somewhere, so where a widget stores it&rsquo;s data internally is unknown.  However for the purpose of re-implementing CreateFrame, we can use a table on each widget.  Another option would have been a single table keyed by the returned widget, and store all the data centrally rather than on the individual frames.</p>
]]></content:encoded></item><item><title>Creating a FubuMvc website</title><link>https://andydote.co.uk/2013/08/26/creating-a-fubumvc-website/</link><pubDate>Mon, 26 Aug 2013 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2013/08/26/creating-a-fubumvc-website/</guid><description>Add new Empty Web Application to your solution PM&amp;gt; Install-package fubumvc Add folder Features Add folder Features\Home Add Features\Home\HomeInputModel.cs Add Features\Home\HomeViewModel.cs Add Features\Home\HomeEndpoint.cs Add Features\Home\Home.spark Setup application (ConfigureFubuMVC.cs) Actions.FindBy(x =&amp;gt; { x.Applies.ToThisAssembly(); x.IncludeClassesSuffixedWithEndpoint(); }); Routes.HomeIs&amp;lt;HomeInputModel&amp;gt;(); Routes.ConstrainToHttpMethod(x =&amp;gt; x.Method.Name.Equals(&amp;#34;Get&amp;#34;, StringComparison.OrdinalIgnoreCase), &amp;#34;GET&amp;#34;); Routes.IgnoreControllerNamespaceEntirely(); //removes /features/home/ from the start of urls Routes.IgnoreMethodSuffix(&amp;#34;Get&amp;#34;); //removes the trailing /get from our urls HomeViewModel.cs: public String Message { get; set; } HomeEndpoint.cs: public HomeViewModel Get(HomeInputModel input) { return new HomeViewModel { Message = &amp;#34;Dave&amp;#34; }; } Home.</description><content:encoded><![CDATA[<ul>
<li>Add new Empty Web Application to your solution</li>
<li>PM&gt; Install-package fubumvc</li>
<li>Add folder Features</li>
<li>Add folder Features\Home</li>
<li>Add Features\Home\HomeInputModel.cs</li>
<li>Add Features\Home\HomeViewModel.cs</li>
<li>Add Features\Home\HomeEndpoint.cs</li>
<li>Add Features\Home\Home.spark</li>
<li>Setup application (ConfigureFubuMVC.cs)</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>Actions.FindBy(x =&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	x.Applies.ToThisAssembly();
</span></span><span style="display:flex;"><span>	x.IncludeClassesSuffixedWithEndpoint();
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Routes.HomeIs&lt;HomeInputModel&gt;();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Routes.ConstrainToHttpMethod(x =&gt; x.Method.Name.Equals(<span style="color:#e6db74">&#34;Get&#34;</span>, StringComparison.OrdinalIgnoreCase), <span style="color:#e6db74">&#34;GET&#34;</span>);
</span></span><span style="display:flex;"><span>Routes.IgnoreControllerNamespaceEntirely();	<span style="color:#75715e">//removes /features/home/ from the start of urls</span>
</span></span><span style="display:flex;"><span>Routes.IgnoreMethodSuffix(<span style="color:#e6db74">&#34;Get&#34;</span>);		<span style="color:#75715e">//removes the trailing /get from our urls</span>
</span></span></code></pre></div><ul>
<li>HomeViewModel.cs:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> String Message { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span></code></pre></div><ul>
<li>HomeEndpoint.cs:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> HomeViewModel Get(HomeInputModel input)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> HomeViewModel { Message = <span style="color:#e6db74">&#34;Dave&#34;</span> };
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><ul>
<li>Home.spark</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>&lt;viewdata model = <span style="color:#e6db74">&#34;Dashboard.Features.Home.HomeViewModel&#34;</span> /&gt;
</span></span><span style="display:flex;"><span>&lt;h1&gt;Hello <span style="color:#960050;background-color:#1e0010">$</span>{Model.Message}&lt;/h1&gt;
</span></span></code></pre></div><ul>
<li>Add folder Features\Test</li>
<li>Add Features\Test\TestInputModel.cs</li>
<li>Add Features\Test\TestViewModel.cs</li>
<li>Add Features\Test\TestEndpoint.cs</li>
<li>Add Features\Test\Test.spark</li>
<li>TestEndpoint.cs:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> TestViewModel Get(TestInputModel input)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> TestViewModel();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><ul>
<li>Test.spark:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>&lt;viewdata model = <span style="color:#e6db74">&#34;Dashboard.Features.Test.TestViewModel&#34;</span> /&gt;
</span></span><span style="display:flex;"><span>&lt;h1&gt;Hello <span style="color:#960050;background-color:#1e0010">$</span>{Model.Message}&lt;/h1&gt;
</span></span></code></pre></div><ul>
<li>Home.spark:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>!{<span style="color:#66d9ef">this</span>.LinkTo&lt;TestInputModel&gt;().Text(<span style="color:#e6db74">&#34;Test&#34;</span>)}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Checking a Type for an Attribute</title><link>https://andydote.co.uk/2012/11/02/checking-a-type-for-an-attribute/</link><pubDate>Fri, 02 Nov 2012 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2012/11/02/checking-a-type-for-an-attribute/</guid><description>I needed to be able to detect at run time if an Enum has a specific Attribute on it. Generalizing it, I came up with this:
Calling:
var hasFlags = typeof(EnumWithFlags).HasAttribute&amp;lt;FlagsAttribute&amp;gt;(); Implementation:
public static Boolean HasAttribute&amp;lt;T&amp;gt;(this Type self) where T : Attribute { if (self == null) { throw new ArgumentNullException(&amp;#34;self&amp;#34;); } return self.GetCustomAttributes(typeof(T), false).Any(); } It may only be two lines, but it is very useful none the less.</description><content:encoded><![CDATA[<p>I needed to be able to detect at run time if an Enum has a specific Attribute on it.  Generalizing it, I came up with this:</p>
<p>Calling:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> hasFlags = <span style="color:#66d9ef">typeof</span>(EnumWithFlags).HasAttribute&lt;FlagsAttribute&gt;();
</span></span></code></pre></div><p>Implementation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> Boolean HasAttribute&lt;T&gt;(<span style="color:#66d9ef">this</span> Type self) <span style="color:#66d9ef">where</span> T : Attribute
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> (self == <span style="color:#66d9ef">null</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> ArgumentNullException(<span style="color:#e6db74">&#34;self&#34;</span>);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> self.GetCustomAttributes(<span style="color:#66d9ef">typeof</span>(T), <span style="color:#66d9ef">false</span>).Any();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>It may only be two lines, but it is very useful none the less.</p>
]]></content:encoded></item><item><title>SqlDataReader.HasRows Problems</title><link>https://andydote.co.uk/2012/10/30/sqldatareaderhasrows-problems/</link><pubDate>Tue, 30 Oct 2012 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2012/10/30/sqldatareaderhasrows-problems/</guid><description>For the last 6 years or so at work, we have had an intermittent bug. In this case, intermittent means around once in 6 months or so. A little background to the problem first:
Our data access is done via what was originally Microsoft&amp;rsquo;s SQLHelper class, passing in a stored procedure (and parameters), and our entities use the reader to load all their properties. Pretty straight forward stuff.
The problemis, on the live system, every few months a sproc will stop returning results, for no apparent reason.</description><content:encoded><![CDATA[<p>For the last 6 years or so at work, we have had an intermittent bug.  In this case, intermittent means around once in 6 months or so.  A little background to the problem first:</p>
<p>Our data access is done via what was originally Microsoft&rsquo;s SQLHelper class, passing in a stored procedure (and parameters), and our entities use the reader to load all their properties.  Pretty straight forward stuff.</p>
<p>The problemis, on the live system, every few months a sproc will stop returning results, for no apparent reason.  Calling the sproc from Sql Management Studio works fine.  We have tried many different fixes: re-applying the sproc, calling the sproc from a different database login, re-pointing to the dev or test systems.  None of it makes any difference, and then as suddenly as it stopped working, it starts working again.</p>
<p>A few days ago, I was attempting to track down some inconsistent search results, this time based around an fts index.  Now this index is pretty large (at least, in my books it is) at around 1.5 million rows, and the column itself being a good few thousand words on average.</p>
<p>The code used for this problem boils down to the following</p>
<p>Sproc &ldquo;ftsSearch&rdquo;:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span>	<span style="color:#66d9ef">Select</span>	id
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">from</span>	ftsTable
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">where</span>	<span style="color:#66d9ef">contains</span>(<span style="color:#f92672">@</span>query, searchColumn)
</span></span></code></pre></div><p>Reader Class:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">FtsSearch</span> : List&lt;<span style="color:#66d9ef">int</span>&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Search(String input)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		Clear();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> param = <span style="color:#66d9ef">new</span> SqlParameter(<span style="color:#e6db74">&#34;@query&#34;</span>, SqlDbType.VarChar);
</span></span><span style="display:flex;"><span>		param.Value = input;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> reader = SqlHelper.ExecuteReader(DbConnection, <span style="color:#e6db74">&#34;ftsSearch&#34;</span>, param))
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">if</span> (reader.HasRows)
</span></span><span style="display:flex;"><span>			{
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">while</span> (reader.Read())
</span></span><span style="display:flex;"><span>				{
</span></span><span style="display:flex;"><span>					Add(reader.GetInt32(<span style="color:#ae81ff">0</span>));
</span></span><span style="display:flex;"><span>				}
</span></span><span style="display:flex;"><span>			}
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Calling this function while the error is occurring, yields the following results:</p>
<pre><code>Query:						Results:
&quot;Project Management&quot;		20,000
&quot;Project Manager&quot;			15,000
&quot;Project Manage*&quot;			0
</code></pre>
<p>The first two queries are fine, the last however I would expect to bring back between 20,000 and ~35,000 results, and when we ran the sql from Management Studio, it brought back 29,000 results.</p>
<p>Now when debugging the function, we double checked everything was being called correctly - correct DB, correct sproc, correct login, correct (parsed) parameter.</p>
<p>Inspecting HasRows returns False.  So we forced a call to Read() anyway, just to see what happened.  An what do you know? Results, all there.</p>
<p>The reason that HasRows was returning false was that the sproc was triggering sql server to also send back a warning - in this case one about too many results (afraid I have lost the exact error code).  Sadly this behaviour does not seem to be documented anywhere.</p>
]]></content:encoded></item><item><title>Winforms Design Time support: exposing sub designers</title><link>https://andydote.co.uk/2012/10/29/winforms-design-time-support-exposing-sub-designers/</link><pubDate>Mon, 29 Oct 2012 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2012/10/29/winforms-design-time-support-exposing-sub-designers/</guid><description>When writing a UserControl, it is often desired to expose one or more of the sub-controls design-time support to the user of your control. It is reasonably straight forward to do, and here is a rundown of how:
We start off with our UserControl, in this case the imaginatively named TestControl:
The code behind looks like this:
[Designer(typeof(TestControlDesigner))] public partial class TestControl : UserControl { public TestControl() { InitializeComponent(); } [DesignerSerializationVisibility(DesignerSerializationVisibility.</description><content:encoded><![CDATA[<p>When writing a <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.usercontrol.aspx">UserControl</a>, it is often desired to expose one or more of the sub-controls design-time support to the user of your control.  It is reasonably straight forward to do, and here is a rundown of how:</p>
<p>We start off with our UserControl, in this case the imaginatively named <code>TestControl</code>:</p>
<p><img loading="lazy" src="sub-designer-control.png" alt="The TestControl"  />
</p>
<p>The code behind looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#a6e22e">[Designer(typeof(TestControlDesigner))]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">partial</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TestControl</span> : UserControl
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> TestControl()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		InitializeComponent();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">	[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> ToolStrip ToolStrip
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> tsMain; }
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The first attribute on the class (<code>[Designer(typeof(TestControlDesigner))]</code>) just instructs that we want it to use our own custom designer file (which we create in a minute).
The next important point is the addition of the <code>ToolStrip</code> property, and the <code>DesignerSerializationVisibility</code> attribute that goes with it.  This informs the winforms designer that any changes made to the ToolStrip should be stored in the hosting container&rsquo;s designer file.  Without this attribute, no changes made in the designer would persist when you closed the designer.</p>
<p>Next, we add a reference to <code>System.Design</code> in the project, and create our <code>TestControlDesigner</code> class, inheriting from <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.design.controldesigner.aspx">ControlDesigner</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TestControlDesigner</span> : ControlDesigner
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Initialize(System.ComponentModel.IComponent component)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">base</span>.Initialize(component);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> control = (TestControl) component;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		EnableDesignMode(control.ToolStrip, <span style="color:#e6db74">&#34;ToolStrip&#34;</span>);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As you can see, we have very little in here.  The <code>Initialize</code> method is overriden, and we call <code>EnableDesignMode</code> on our ToolStrip (the property added to the TestControl earlier).</p>
<p>After compiling, we can go to our form (again, imaginatively named Form1), and add a couple of instances of <code>TestControl</code> to it from the tool box:</p>
<p><img loading="lazy" src="sub-designer-designtime.png" alt="The TestControl"  />
</p>
<p>As you can see, the two control&rsquo;s ToolStrips contents is unique, and we have the ToolStrip&rsquo;s designer exposed in the forms designer.</p>
]]></content:encoded></item><item><title>Designing the EventDistributor</title><link>https://andydote.co.uk/2012/04/23/designing-the-eventdistributor/</link><pubDate>Mon, 23 Apr 2012 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2012/04/23/designing-the-eventdistributor/</guid><description>When it comes to developing a new class, I don&amp;rsquo;t tend to use TDD (Test Driven Development), I favour something I have named TAD - Test Aided Development. In other words, while I am for Unit Testing in general, designing something via writing tests sometimes feels too clunky and slow. I always write classes and methods with testing very much in mind, but I do not generally write the tests until later on in the process.</description><content:encoded><![CDATA[<p>When it comes to developing a new class, I don&rsquo;t tend to use TDD (Test Driven Development), I favour something I have named TAD - Test Aided Development.  In other words, while I am for Unit Testing in general, designing something via writing tests sometimes feels too clunky and slow.  I always write classes and methods with testing very much in mind, but I do not generally write the tests until later on in the process.  This post covers roughly how I wrote the EventDistributor, and what points of note there are along the way.</p>
<p>The first phase in designing it, was the use case:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>events.RegisterFor&lt;PersonSavedEvent&gt;(OnPersonSaved);
</span></span><span style="display:flex;"><span>events.Publish(<span style="color:#66d9ef">new</span> PersonSavedEvent());
</span></span><span style="display:flex;"><span>events.UnRegisterFor&lt;PersonSavedEvent&gt;(OnPersonSaved);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> OnPersonSaved(PersonSavedEvent e)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">/* ... */</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>From this use case, we are able to tell that we will have 0 -&gt; n events, and each event will have 0 -&gt; n subscribers.  This points to some kind of <code>Dictionary</code> based backing field:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">EventDistributor</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Dictionary&lt;Type, List&lt;Action&lt;Object&gt;&gt;&gt; _events;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> EventDistributor()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_events = <span style="color:#66d9ef">new</span> Dictionary&lt;Type, List&lt;Action&lt;Object&gt;&gt;&gt;();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> RegisterFor&lt;TEvent&gt;(Action&lt;TEvent&gt; handler)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> UnRegisterFor&lt;TEvent&gt;(Action&lt;TEvent&gt; handler)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Publish&lt;TEvent&gt;(TEvent @event)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>For populating the dictionary, we need to add an entry for a <code>TEvent</code> if there is not already one (and create a blank list of handlers), and append our new handler:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> RegisterFor&lt;TEvent&gt;(Action&lt;TEvent&gt; handler)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> type = <span style="color:#66d9ef">typeof</span>(TEvent);
</span></span><span style="display:flex;"><span>	List&lt;Action&lt;Object&gt;&gt; handlers;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> (_events.TryGetValue(type, <span style="color:#66d9ef">out</span> handlers) == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		handlers = <span style="color:#66d9ef">new</span> List&lt;Action&lt;Object&gt;&gt;();
</span></span><span style="display:flex;"><span>		_events[type] = handlers;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	handlers.Add(handler);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This gives rise to the first problem: the line <code>handlers.Add(handler);</code> gives us a nice error of: <code>Error Argument '1': cannot convert from 'System.Action&lt;TEvent&gt;' to 'System.Action&lt;Object&gt;'</code>.  To fix this, we need to create a new <code>Action&lt;Object&gt;</code> and inside that, cast the parameter to <code>TEvent</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>handlers.Add(o =&gt; handler((TEvent) o));
</span></span></code></pre></div><p>This does however make the UnRegisterFor method a little more tricky, as doing <code>handlers.Remove(o =&gt; handler((TEvent)o));</code> doesn&rsquo;t work because they refer to different objects.  Thankfully, as the Action&rsquo;s <code>GetHashCode()</code> gives the same result for each instance, providing the content is the same.  We can use this to check for equality:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> UnRegisterFor&lt;TEvent&gt;(Action&lt;TEvent&gt; handler)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> type = <span style="color:#66d9ef">typeof</span>(TEvent);
</span></span><span style="display:flex;"><span>	List&lt;Action&lt;Object&gt;&gt; handlers;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> (_events.TryGetValue(type, <span style="color:#66d9ef">out</span> handlers) == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> hash = <span style="color:#66d9ef">new</span> Action&lt;<span style="color:#66d9ef">object</span>&gt;(o =&gt; handler((TEvent) o)).GetHashCode();
</span></span><span style="display:flex;"><span>	handlers.RemoveAll(h =&gt; h.GetHashCode() == hash);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>Publish</code> method is nice and straight forward; if the event isn&rsquo;t registered, throw an exception, and raise each subscriber&rsquo;s handler.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Publish&lt;TEvent&gt;(TEvent @event)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> type = <span style="color:#66d9ef">typeof</span>(TEvent);
</span></span><span style="display:flex;"><span>	List&lt;Action&lt;Object&gt;&gt; handlers;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> (_events.TryGetValue(type, <span style="color:#66d9ef">out</span> handlers) == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> EventNotRegisteredException(type);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	handlers.ForEach(h =&gt; h.Invoke(@event));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Now that we have a class roughly implemented, we create the first set of tests for it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#a6e22e">[Test]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> When_publishing_an_event_without_a_handler()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> distributor = <span style="color:#66d9ef">new</span> Distributor();
</span></span><span style="display:flex;"><span>	Assert.DoesNotThrow(() =&gt; distributor.Publish(<span style="color:#66d9ef">new</span> PersonSavedEvent()));
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">[Test]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> When_publishing_an_event_with_a_handler()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> wasCalled = <span style="color:#66d9ef">false</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> distributor = <span style="color:#66d9ef">new</span> Distributor();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	distributor.RegisterFor&lt;TestEvent&gt;(e =&gt; wasCalled = <span style="color:#66d9ef">true</span>);
</span></span><span style="display:flex;"><span>	distributor.Publish(<span style="color:#66d9ef">new</span> TestEvent());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	Assert.IsTrue(wasCalled, <span style="color:#e6db74">&#34;The target was not invoked.&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">[Test]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> When_publishing_an_event_and_un_registering()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> callCount = <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> increment = <span style="color:#66d9ef">new</span> Action&lt;TestEvent&gt;(e =&gt; callCount++);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> distributor = <span style="color:#66d9ef">new</span> Distributor();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	distributor.RegisterFor&lt;TestEvent&gt;(increment);
</span></span><span style="display:flex;"><span>	distributor.Publish(<span style="color:#66d9ef">new</span> TestEvent());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	distributor.UnRegisterFor&lt;TestEvent&gt;(increment);
</span></span><span style="display:flex;"><span>	distributor.Publish(<span style="color:#66d9ef">new</span> TestEvent());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	Assert.AreEqual(<span style="color:#ae81ff">1</span>, callCount);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Other than the publish method is currently a blocking operation, there is one major floor to this class: it contains a possible memory leak.  If a class forgets to UnRegisterFor a handler, the EventDistributor will still have a reference stored, preventing the calling class from being garbage collected.  We can demonstrate this with a simple unit test:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#a6e22e">[Test]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> When_the_handling_class_does_not_call_unregister()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> count = <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> increment = <span style="color:#66d9ef">new</span> Action(() =&gt; count++);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> distributor = <span style="color:#66d9ef">new</span> Distributor();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	using(<span style="color:#66d9ef">var</span> l = <span style="color:#66d9ef">new</span> Listener(distributor, increment))
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		distributor.Publish(<span style="color:#66d9ef">new</span> TestEvent());
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	GC.Collect();
</span></span><span style="display:flex;"><span>	GC.WaitForPendingFinalizers();
</span></span><span style="display:flex;"><span>	GC.Collect();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	distributor.Publish(<span style="color:#66d9ef">new</span> TestEvent());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	Assert.AreEqual(<span style="color:#ae81ff">1</span>, count, <span style="color:#e6db74">&#34;OnPersonSaved should have only been called 1 time, was actually {0}&#34;</span>, count);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Listener</span> : IDisposable
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Action _action;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Listener(Distributor events, Action action)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_action = action;
</span></span><span style="display:flex;"><span>		events.RegisterFor&lt;TestEvent&gt;(OnTestEvent);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> OnTestEvent(TestEvent e)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_action.Invoke();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Dispose()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>While it would be simple to just say that it&rsquo;s the responsibility of the calling code to call <code>UnRegisterFor</code>, it would be better to handle that (likely) case ourselves.  Good news is that .net has just the class needed for this built in: <a href="http://msdn.microsoft.com/en-us/library/system.weakreference.aspx">WeakReference</a>.  This class allows the target class to become disposed even while we still hold a reference to it.  We can then act on the disposal, and remove our event registration.</p>
<p>Changing the Dispatcher to use this in its dictionary is fairly straight forward, and we even loose some of the casting needed to add items to the list:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Distributor</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Dictionary&lt;Type, List&lt;WeakReference&gt;&gt; _events;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Distributor()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_events = <span style="color:#66d9ef">new</span> Dictionary&lt;Type, List&lt;WeakReference&gt;&gt;();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> RegisterFor&lt;TEvent&gt;(Action&lt;TEvent&gt; handler)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> type = <span style="color:#66d9ef">typeof</span>(TEvent);
</span></span><span style="display:flex;"><span>		List&lt;WeakReference&gt; recipients;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (!_events.TryGetValue(type, <span style="color:#66d9ef">out</span> recipients))
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			recipients = <span style="color:#66d9ef">new</span> List&lt;WeakReference&gt;();
</span></span><span style="display:flex;"><span>			_events[type] = recipients;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		recipients.Add(<span style="color:#66d9ef">new</span> WeakReference(handler));
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> UnRegisterFor&lt;TEvent&gt;(Action&lt;TEvent&gt; handler)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> type = <span style="color:#66d9ef">typeof</span>(TEvent);
</span></span><span style="display:flex;"><span>		List&lt;WeakReference&gt; recipients;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (_events.TryGetValue(type, <span style="color:#66d9ef">out</span> recipients))
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			recipients.RemoveAll(o =&gt; o.Target.GetHashCode() == handler.GetHashCode());
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Publish&lt;TEvent&gt;(TEvent @event)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> type = <span style="color:#66d9ef">typeof</span>(TEvent);
</span></span><span style="display:flex;"><span>		List&lt;WeakReference&gt; recipients;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (!_events.TryGetValue(type, <span style="color:#66d9ef">out</span> recipients))
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		recipients.RemoveAll(wr =&gt; wr.IsAlive == <span style="color:#66d9ef">false</span>);
</span></span><span style="display:flex;"><span>		recipients.ForEach(wr =&gt; ((Action&lt;TEvent&gt;)wr.Target).Invoke(@event));
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The main points to note with this change is:</p>
<ul>
<li>We no longer need to create a new <code>Action&lt;Object&gt;</code> just to cast the handler in <code>RegisterFor</code>.</li>
<li><code>UnRegisterFor</code> no longer needs to create a new <code>Action&lt;Object&gt;</code> to get the hash code.</li>
<li><code>Publish</code> has an extra line to remove all handlers where the target has become disposed.</li>
</ul>
<p>The next item to work on in this class is making the <code>Publish</code> method non-blocking, which can be done in a variety of ways.</p>
<p>The first option is to create a thread that will invoke all the handlers one after the other.  This has the advantage of only one extra thread to deal with, but has the drawback of a single unresponsive handler will block all other handlers.  Ignoring locking and cross-threading issues for the time being, it could be implemented like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> PublishAsyncV1&lt;TEvent&gt;(TEvent @event)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> type = <span style="color:#66d9ef">typeof</span>(TEvent);
</span></span><span style="display:flex;"><span>	List&lt;WeakReference&gt; recipients;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> (!_events.TryGetValue(type, <span style="color:#66d9ef">out</span> recipients))
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> task = <span style="color:#66d9ef">new</span> Task(() =&gt;
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		recipients.RemoveAll(wr =&gt; wr.IsAlive == <span style="color:#66d9ef">false</span>);
</span></span><span style="display:flex;"><span>		recipients.ForEach(wr =&gt; ((Action&lt;TEvent&gt;) wr.Target).Invoke(@event));
</span></span><span style="display:flex;"><span>	});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	task.Start();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The second option is to have a separate thread/invocation for each handler.  This has the advantage that each of the handlers can take as much time as needed, and will not block any other handlers from being raised, however if you have many handlers to be invoked, it could be slower to return than the first option.  Again, ignoring locking and cross-threading issues, it could be implemented like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> PublishAsyncV2&lt;TEvent&gt;(TEvent @event)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> type = <span style="color:#66d9ef">typeof</span>(TEvent);
</span></span><span style="display:flex;"><span>	List&lt;WeakReference&gt; recipients;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> (!_events.TryGetValue(type, <span style="color:#66d9ef">out</span> recipients))
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	recipients.RemoveAll(wr =&gt; wr.IsAlive == <span style="color:#66d9ef">false</span>);
</span></span><span style="display:flex;"><span>	recipients.ForEach(wr =&gt;
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> handler = (Action&lt;TEvent&gt;)wr.Target;
</span></span><span style="display:flex;"><span>		handler.BeginInvoke(@event, handler.EndInvoke, <span style="color:#66d9ef">null</span>);
</span></span><span style="display:flex;"><span>	});
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Personally, I go for the second method, as the number of handlers to be invoked is usually fairly small.</p>
<p>The next part to consider is what we conveniently ignored earlier - the cross-threading issues.  The main issue we have is handlers being added or removed from the list while we are iterating over it.</p>
<p>Now I cannot remember where I read it, it was either from Jon Skeet, or from the <a href="http://www.amazon.co.uk/Visual-Basic-NET-Threading-Handbook-Programmer/dp/1861007132">Visual Basic .Net Threading Handbook</a>, but the rough idea was &ldquo;You should lock as smaller area of code as possible&rdquo;.  This is to minimise the chance of a deadlock.  Starting with the Publish methods, we only need to lock the parts that iterate over the list:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">lock</span> (Padlock)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	recipients.RemoveAll(wr =&gt; wr.IsAlive == <span style="color:#66d9ef">false</span>);
</span></span><span style="display:flex;"><span>	recipients.ForEach(wr =&gt;
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> handler = (Action&lt;TEvent&gt;)wr.Target;
</span></span><span style="display:flex;"><span>		handler.BeginInvoke(@event, handler.EndInvoke, <span style="color:#66d9ef">null</span>);
</span></span><span style="display:flex;"><span>	});
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The UnRegisterFor method is also very straight forward, as we again only need to worry about the iteration:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (_events.TryGetValue(type, <span style="color:#66d9ef">out</span> recipients))
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">lock</span> (Padlock)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		recipients.RemoveAll(o =&gt; o.Target.GetHashCode() == handler.GetHashCode());
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The RegisterFor method takes a little more locking than the other two, as this will handle the creation of the lists, as well as the addition to the list:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">lock</span> (Padlock)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> (!_events.TryGetValue(type, <span style="color:#66d9ef">out</span> recipients))
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		recipients = <span style="color:#66d9ef">new</span> List&lt;WeakReference&gt;();
</span></span><span style="display:flex;"><span>		_events[type] = recipients;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	recipients.Add(<span style="color:#66d9ef">new</span> WeakReference(handler));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The full code listing and unit tests for this can be found here: <a href="https://gist.github.com/2467463">EventDistributor Gist</a>.</p>
]]></content:encoded></item><item><title>Model View Presenters: Composite Views</title><link>https://andydote.co.uk/2012/03/29/model-view-presenters-composite-views/</link><pubDate>Thu, 29 Mar 2012 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2012/03/29/model-view-presenters-composite-views/</guid><description>Table of Contents: Introduction Presenter to View Communication View to Presenter Communication Composite Views Presenter / Application communication &amp;hellip; When working with MVP, it won&amp;rsquo;t be long before you come across the need for multiple views on one form. There are several ways to achive this, and which you choose is really down to how you intend to (re)use your views.
The first method for dealing with the sub views is to expose them as a property of your main view, and set them up in the main view&amp;rsquo;s presenter:</description><content:encoded><![CDATA[<h2 id="table-of-contents">Table of Contents:</h2>
<ul>
<li><a href="/model-view-presenter-introduction">Introduction</a></li>
<li><a href="/model-view-presenters-presenter-to-view-communication">Presenter to View Communication</a></li>
<li><a href="/model-view-presenters-view-to-presenter-communication">View to Presenter Communication</a></li>
<li><strong>Composite Views</strong></li>
<li>Presenter / Application communication</li>
<li>&hellip;</li>
</ul>
<p>When working with MVP, it won&rsquo;t be long before you come across the need for multiple views on one form.  There are several ways to achive this, and which you choose is really down to how you intend to (re)use your views.</p>
<p><img loading="lazy" src="mvp-sub-view-diagram.jpg" alt="Composite View"  />
</p>
<p>The first method for dealing with the sub views is to expose them as a property of your main view, and set them up in the main view&rsquo;s presenter:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IMainView</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	ISubView1 View1 { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>	ISubView2 View2 { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">/* Other properties/methods etc for MainView */</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MainView</span> : Form, IMainView
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> ISubView1 View1 { <span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">this</span>.subView1; } }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> ISubView2 View2 { <span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">this</span>.subView2; } }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MainPresenter</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IMainView _view;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> SubPresenter1 _pres1;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> SubPresenter2 _pres2;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> MainPresenter(IMainView view)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_view = view;
</span></span><span style="display:flex;"><span>		_pres1 = <span style="color:#66d9ef">new</span> SubPresenter1(view.View1);
</span></span><span style="display:flex;"><span>		_pres2 = <span style="color:#66d9ef">new</span> SubPresenter2(view.View2);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Program</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> Main()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> view = <span style="color:#66d9ef">new</span> MainView())
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> presenter = <span style="color:#66d9ef">new</span> MainPresenter(view))
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			presenter.Display();
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This method&rsquo;s advantage is simplicity, just create a new view and presenter, and call <code>Display</code>.  The disadvantage is that the main presenter is tied to the sub presenters.  A slight modification alleviates this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IMainView</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	ISubView1 View1 { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>	ISubView2 View2 { <span style="color:#66d9ef">get</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">/* Other properties/methods etc for MainView */</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MainView</span> : Form, IMainView
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> ISubView1 View1 { <span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">this</span>.subView1; } }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> ISubView2 View2 { <span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">this</span>.subView2; } }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MainPresenter</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IMainView _view;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> SubPresenter1 _pres1;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> SubPresenter2 _pres2;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> MainPresenter(IMainView view, SubPresenter1 pres1, SubPresenter2 pres2)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_view = view;
</span></span><span style="display:flex;"><span>		_pres1 = pres1;
</span></span><span style="display:flex;"><span>		_pres2 = pres2;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Program</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> Main()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> view = <span style="color:#66d9ef">new</span> MainView())
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> pres1 = <span style="color:#66d9ef">new</span> SubPresenter1(view.View1));
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> pres2 = <span style="color:#66d9ef">new</span> SubPresenter2(view.View2));
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> presenter = <span style="color:#66d9ef">new</span> MainPresenter(view, pres1, pres2))
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			presenter.Display();
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The only change here is to pass our two sub presenters in to the main presenter as constructor parameters.  Ultimately this seems to be the &lsquo;best&rsquo; solution from a coupling point of view, however, if you are unlikely to change the sub presenters out for completely different sub presenters, then I would use the first method.</p>
<p>The final method for composing sub views is to push the responsibility to the actual main view, and make your main view pass any events and data to and from the sub view:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IMainView</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	String FirstName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	String LastName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	String AddressLine1 { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	String PostCode { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">/* Other properties/methods etc for MainView */</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MainView</span> : Form, IMainView
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> SubPresenter1 _pres1;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> SubPresenter2 _pres2;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> MainView()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		InitializeComponent();
</span></span><span style="display:flex;"><span>		_pres1 = <span style="color:#66d9ef">new</span> SubPresenter1(subView1);
</span></span><span style="display:flex;"><span>		_pres2 = <span style="color:#66d9ef">new</span> SubPresenter2(subView2);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	String FirstName
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> subView1.FirstName; }
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">set</span> {subView1.FirstName = <span style="color:#66d9ef">value</span>;}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	String LastName
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> subView1.LastName; }
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">set</span> { subView1.LastName = <span style="color:#66d9ef">value</span>; }
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	String AddressLine1
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> subView2.AddressLine1; }
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">set</span> { subView2.AddressLine1 = <span style="color:#66d9ef">value</span>; }
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	String PostCode
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> subView2.PostCode; }
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">set</span> { subView2.PostCode = <span style="color:#66d9ef">value</span>; }
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The disadvantage to this is that if one of the subViews were to change in anyway, the MainView also has to change to reflect this.</p>
<p>Out of the three methods outlined, Method 2 is my personal preference, especially when not using a DI Container, and Method 2 when I am using one.  The 3rd Method I find is too brittle for most usage, especially during earlier stages of development when the UI is more likely to be changing.</p>
]]></content:encoded></item><item><title>Model View Presenters: View to Presenter Communication</title><link>https://andydote.co.uk/2012/01/31/model-view-presenters-view-to-presenter-communication/</link><pubDate>Tue, 31 Jan 2012 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2012/01/31/model-view-presenters-view-to-presenter-communication/</guid><description>Table of Contents: Introduction Presenter to View Communication View to Presenter Communication Composite Views Presenter / Application communication &amp;hellip; Communicating from the View to the Presenter is a reasonably straight forward affair. To signal something happening, we use an Event, but one with no parameters. We pass no parameters, as we are not going to be using them anyway, so what is the point is raising an event every time with OkayClicked(this, EventArgs.</description><content:encoded><![CDATA[<h2 id="table-of-contents">Table of Contents:</h2>
<ul>
<li><a href="/model-view-presenter-introduction">Introduction</a></li>
<li><a href="/model-view-presenters-presenter-to-view-communication">Presenter to View Communication</a></li>
<li><strong>View to Presenter Communication</strong></li>
<li><a href="/model-view-presenters-composite-views">Composite Views</a></li>
<li>Presenter / Application communication</li>
<li>&hellip;</li>
</ul>
<p>Communicating from the View to the Presenter is a reasonably straight forward affair.  To signal something happening, we use an <code>Event</code>, but one with no parameters.  We pass no parameters, as we are not going to be using them anyway, so what is the point is raising an event every time with <code>OkayClicked(this, EventArgs.Empty)</code>?</p>
<p>To get around this, we define a new event type, so that we can get rid of our redundant parameters:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">delegate</span> <span style="color:#66d9ef">void</span> EventAction();
</span></span></code></pre></div><p>In the View we define our events:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IEmployeesView</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">event</span> EventAction OkayClicked;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">event</span> EventAction CancelClicked;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And in the Presenter we hook up the events:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">EmployeesPresenter</span> : IDisposable
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IEmployeeView _view;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> EmployeesPresenter(IEmployeesView view)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_view = view;
</span></span><span style="display:flex;"><span>		_view.OkayClicked += OnOkayClicked;
</span></span><span style="display:flex;"><span>		_view.CancelClicked += OnCancelClicked;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> OnOkayClicked() { <span style="color:#75715e">/* ... */</span> }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> OnCancelClicked() { <span style="color:#75715e">/* ... */</span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Dispose()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_view.OkayClicked -= OnOkayClicked;
</span></span><span style="display:flex;"><span>		_view.CancelClicked -= OnCancelClicked;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Now I don&rsquo;t know about you, but I dislike having to wire and unwire an event like this - there is too much chance that I will either forget to unwire one of the events, or when copying and pasting the Add code (I know, I know) to the Remove section, I will forget to change a <code>+</code> to a <code>-</code>.</p>
<p>To this end, I created a class that will auto wire events to handlers based on a convention.  It was based off of the Presenter base class written by <a href="http://cre8ivethought.com/blog/index">Mark Nijhof</a> in his <a href="https://github.com/MarkNijhof/Fohjin">Fohjin.DDD</a> sample application, with a few improvements (namely the unwiring of events).  To avoid the need to make your Presenters inherit from a base class (and to not violate SRP!), it is wrapped up into its own class, which can be used like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">EmployeesPresenter</span> : IDisposable
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> IEmployeeView _view;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> EventAutoWirer&lt;IEmployeeView&gt; _autoWire;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> EmployeesPresenter(IEmployeesView view)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_view = view;
</span></span><span style="display:flex;"><span>		_autoWire = <span style="color:#66d9ef">new</span> EventAutoWire&lt;IEmployeeView&gt;(view, <span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>		_autoWire.Wire();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> OnOkayClicked() { <span style="color:#75715e">/* ... */</span> }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> OnCancelClicked() { <span style="color:#75715e">/* ... */</span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Dispose()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_autoWire.Unwire();
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The wirer supports conventions to allow easier hook-up - by default it will only hook events defined in the View&rsquo;s interface to private methods prefixed with &ldquo;On&rdquo; in the presenter.  This means that any events which are only defined in the concrete implementation of the View are not wired automatically - allowing extra view only functionality such as when an item is MouseOver&rsquo;d etc.</p>
]]></content:encoded></item><item><title>Model View Presenters: Introduction</title><link>https://andydote.co.uk/2012/01/26/model-view-presenter-introduction/</link><pubDate>Thu, 26 Jan 2012 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2012/01/26/model-view-presenter-introduction/</guid><description>Table of Contents Introduction Presenter to View Communication View to Presenter Communication Composite Views Presenter / Application communication &amp;hellip; What is MVP? I first came across MVP in Jeremy Miller&amp;rsquo;s Build Your Own Cab series, and have been using and improving how I work with this style ever since. Model View Presenters tend to come in one of two forms: Passive View, and Supervising Controller. I am a fan of the Passive View variety, primarily for the testing aspect, but also as I find it provides me with the best level of separation.</description><content:encoded><![CDATA[<h2 id="table-of-contents">Table of Contents</h2>
<ul>
<li><strong>Introduction</strong></li>
<li><a href="/model-view-presenters-presenter-to-view-communication">Presenter to View Communication</a></li>
<li><a href="/model-view-presenters-view-to-presenter-communication">View to Presenter Communication</a></li>
<li><a href="/model-view-presenters-composite-views">Composite Views</a></li>
<li>Presenter / Application communication</li>
<li>&hellip;</li>
</ul>
<h2 id="what-is-mvp">What is MVP?</h2>
<p>I first came across MVP in <a href="http://codebetter.com/jeremymiller/">Jeremy Miller&rsquo;s</a> <a href="http://codebetter.com/jeremymiller/2007/07/26/the-build-your-own-cab-series-table-of-contents/">Build Your Own Cab series</a>, and have been using and improving how I work with this style ever since.  Model View Presenters tend to come in one of two forms: <a href="http://martinfowler.com/eaaDev/PassiveScreen.html">Passive View</a>, and <a href="http://martinfowler.com/eaaDev/SupervisingPresenter.html">Supervising Controller</a>.  I am a fan of the Passive View variety, primarily for the testing aspect, but also as I find it provides me with the best level of separation.</p>
<p>The code ends up structured like this:</p>
<p><img loading="lazy" src="mvp-diagram.jpg" alt="MVP"  />
</p>
<p>The View contains only code that enables control population and feedback.  This means the odd For loop or similar to fill a grid from a property, or feedback object construction, along the lines of <code>new SelectedRowData {ID = (int)row.Tag, Name = row[0].Value}</code>.  However, it would not contain any decision logic.</p>
<p>The Presenter contains code to transform Model data to something the View can display, and vice-verse.  It also contains any view logic, such as if a CheckBox is selected, then a MenuItem becomes disabled.</p>
<p>The Model is the data to be displayed.  This can either be an abstraction that encompasses several entities and business logic, or can be some entities themselves.</p>
]]></content:encoded></item><item><title>Model View Presenters: Presenter to View Communication</title><link>https://andydote.co.uk/2012/01/26/model-view-presenters-presenter-to-view-communication/</link><pubDate>Thu, 26 Jan 2012 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2012/01/26/model-view-presenters-presenter-to-view-communication/</guid><description>Table of Contents: Introduction Presenter to View Communication View to Presenter Communication Composite Views Presenter / Application communication &amp;hellip; Presenter to View Communication There are two styles utilised for populating the View with data from the Presenter and Model that I have used. The only difference between them is how tightly coupled you mind your View being to the Model. For the example of this, we will have the following as our Model:</description><content:encoded><![CDATA[<h2 id="table-of-contents">Table of Contents:</h2>
<ul>
<li><a href="/model-view-presenter-introduction">Introduction</a></li>
<li><strong>Presenter to View Communication</strong></li>
<li><a href="/model-view-presenters-view-to-presenter-communication">View to Presenter Communication</a></li>
<li><a href="/model-view-presenters-composite-views">Composite Views</a></li>
<li>Presenter / Application communication</li>
<li>&hellip;</li>
</ul>
<h2 id="presenter-to-view-communication">Presenter to View Communication</h2>
<p>There are two styles utilised for populating the View with data from the Presenter and Model that I have used.  The only difference between them is how tightly coupled you mind your View being to the Model.  For the example of this, we will have the following as our Model:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Person</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> ID { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> Age { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> String FirstName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> String LastName { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	Public Genders Gender { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="method-1-using-the-model">Method 1: Using the Model</h2>
<p>Now our View code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IEmployeesView</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> ClearList();
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> PopulateList(IEnumerable&lt;Person&gt; people);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And finally the Presenter:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">IEmployeesPresenter</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Display()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_view.ClearList();
</span></span><span style="display:flex;"><span>		_view.PopulateList(_model.AllEmployees);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This method of population produces a link between the Model and the View; the Person object used as a parameter in <code>PopulateList</code>.</p>
<p>The advantage of this is that the concrete implementation of the IEmployeesView can decide on what to display in its list of people, picking from any or all of the properties on the <code>Person</code>.</p>
<p>There are two disadvantages of this method.  The first is that there is nothing stopping the View from calling methods on the <code>Person</code>, which makes it easy for lazy code to slip in.  The second is that if the model were to change from a <code>List&lt;Person&gt;</code> to a <code>List&lt;Dog&gt;</code> for instance, not only would the Model and the Presenter need to change, but so the View would too.</p>
<h2 id="method-2-using-generic-types">Method 2: Using Generic Types</h2>
<p>The other method population relies on using <code>Tuple&lt;...&gt;</code>, <code>KeyValuePair&lt;,&gt;</code> and custom classes and structs:</p>
<p>Now our View code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IEmployeesView</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> ClearList();
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">void</span> PopulateList(IEnumerable&lt;Tuple&lt;<span style="color:#66d9ef">int</span>, String&gt; names);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And finally the Presenter:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">IEmployeesPresenter</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Display()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">var</span> names = _model.AllEmployees.Select(x =&gt; <span style="color:#66d9ef">new</span> Tuple&lt;<span style="color:#66d9ef">int</span>, String&gt;(x.ID, x.FirstName + <span style="color:#e6db74">&#34; &#34;</span> + x.LastName));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		_view.ClearList();
</span></span><span style="display:flex;"><span>		_view.PopulateList(names);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The advantages of this method of population is that the Model is free to change without needing to update the View, and the View has no decisions to make on what to display.  It also prevents the View from calling any extra methods on the <code>Person</code>, as it does not have a reference to it.</p>
<p>The down sides to this method, are that you loose strong typing, and discoverability - It is quite obvious what a <code>Person</code> is but what a <code>Tuple&lt;int, String&gt;</code> is less obvious.</p>
]]></content:encoded></item><item><title>Working with XmlTextWriter</title><link>https://andydote.co.uk/2011/10/25/working-with-xmltextwriter/</link><pubDate>Tue, 25 Oct 2011 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2011/10/25/working-with-xmltextwriter/</guid><description>I was working on some code today that needs a lot of data writing into an XML document. The documents structure is not repetitive - it is loads of one time data, so templating the document is possible, but not the best route to go.
To that end, it uses an XmlTextWriter. The problem I have with it is the way you must write sub-elements. If you just need a single value wrapped in a tag, you are catered for already:</description><content:encoded><![CDATA[<p>I was working on some code today that needs a lot of data writing into an XML document.  The documents structure is not repetitive - it is loads of one time data, so templating the document is possible, but not the best route to go.</p>
<p>To that end, it uses an <code>XmlTextWriter</code>.  The problem I have with it is the way you must write sub-elements.  If you just need a single value wrapped in a tag, you are catered for already:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>writer.WriteElementString(<span style="color:#e6db74">&#34;name&#34;</span>, current.Name);
</span></span></code></pre></div><p>However, if you want to embed a composite set of elements, you are left with this lovely chunk:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>writer.WriteStartElement(<span style="color:#e6db74">&#34;composite&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>writer.WriteElementString(<span style="color:#e6db74">&#34;firstName&#34;</span>, current.FirstName);
</span></span><span style="display:flex;"><span>writer.WriteElementString(<span style="color:#e6db74">&#34;lastName&#34;</span>, current.LastName);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>writer.WriteEndElement();
</span></span></code></pre></div><p>And if you have a long document, with many composite elements, good luck remembering which element is being ended by <code>WriteEndElement()</code> (even if you functionalise it, you still run into the issue.)</p>
<p>The solution I came up with for this was a class and an extension method:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">internal</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">WriteElement</span> : IDisposable
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">private</span> XmlTextWriter _writer;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">internal</span> WriteElement(XmlTextWriter writer, String element)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		_writer = writer;
</span></span><span style="display:flex;"><span>		_writer.WriteStartElement(element);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Dispose()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		 _writer.WriteEndElement();
</span></span><span style="display:flex;"><span>		 _writer = <span style="color:#66d9ef">null</span>;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">XmlTextWriterExtensions</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> IDisposable WriteComposite(<span style="color:#66d9ef">this</span> XmlTextWriter self, String element)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> WriteElement(self, element);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This enables me to write composite elements like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">using</span> (writer.WriteComposite(<span style="color:#e6db74">&#34;composite&#34;</span>))
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	writer.WriteElementString(<span style="color:#e6db74">&#34;firstName&#34;</span>, current.FirstName);
</span></span><span style="display:flex;"><span>	writer.WriteElementString(<span style="color:#e6db74">&#34;lastName&#34;</span>, current.LastName);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>With the two benefits of knowing when my composite elements are ending, and I also gain indentation of my elements, which allows me to <em>see</em> where the composites are a lot easier.</p>
]]></content:encoded></item><item><title>Noticing Changes</title><link>https://andydote.co.uk/2011/10/22/noticing-changes/</link><pubDate>Sat, 22 Oct 2011 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2011/10/22/noticing-changes/</guid><description>I work on a piece of software that has been around for about 6 years now, which looks something like this:
The textboxes are validating that their contents, some as decimal, and some as integer. All the textboxes consider no-value to be invalid.
I made a slight change to the control, which was to add a new row. Since adding that row, many users have sent in requests to have the validation changed on the textboxes, so that no-value is considered to be zero.</description><content:encoded><![CDATA[<p>I work on a piece of software that has been around for about 6 years now, which looks something like this:</p>
<p><img loading="lazy" src="form-validation.jpg" alt="Control"  />
</p>
<p>The textboxes are validating that their contents, some as decimal, and some as integer.  All the textboxes consider no-value to be invalid.</p>
<p>I made a slight change to the control, which was to add a new row.  Since adding that row, many users have sent in requests to have the validation changed on the textboxes, so that no-value is considered to be zero.</p>
<p>Now while I have no problem in making the change, I do however wonder what caused all the requests.  Is it because users noticed the control was changed, so a developer is paying attention somewhere, so maybe they can fix a problem?  Had they just not noticed that no-value is invalid, and now it has changed slightly, they have?</p>
<p>Another thing is that while it is a very minor change, it must have been causing user friction for the last 6 years or so, and no one has mentioned it?  Maybe they just didn&rsquo;t think it was changeable, or that it just wasn&rsquo;t that bothersome compared to some other issue they had?</p>
]]></content:encoded></item><item><title>C# and Vb.Net Differences</title><link>https://andydote.co.uk/2011/09/14/c-and-vbnet-differences/</link><pubDate>Wed, 14 Sep 2011 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2011/09/14/c-and-vbnet-differences/</guid><description>So I have been doing some work that involves C# and VB libraries and apps using each other, and have noticed a lot of subtle differences between the two languages.
Declaration of types inside an interface: Public Interface ITesting ReadOnly Property Test() As TestData Class TestData Public Sub New() StringProperty = &amp;#34;testing&amp;#34; IntProperty = 1234 End Sub Public Property StringProperty() As String Public Property IntProperty() As Integer End Class End Interface However in C#, you cannot declare types inside an interface, however it is quite happy to consume one create in a VB project:</description><content:encoded><![CDATA[<p>So I have been doing some work that involves C# and VB libraries and apps using each other, and have noticed a lot of subtle differences between the two languages.</p>
<h2 id="declaration-of-types-inside-an-interface">Declaration of types inside an interface:</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Interface</span> ITesting
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">ReadOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">Test</span>() <span style="color:#f92672">As</span> TestData
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">TestData</span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">New</span>()
</span></span><span style="display:flex;"><span>			StringProperty <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;testing&#34;</span>
</span></span><span style="display:flex;"><span>			IntProperty <span style="color:#f92672">=</span> 1234
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">StringProperty</span>() <span style="color:#f92672">As</span> <span style="color:#66d9ef">String</span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">IntProperty</span>() <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Interface</span>
</span></span></code></pre></div><p>However in C#, you cannot declare types inside an interface, however it is quite happy to consume one create in a VB project:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> test = <span style="color:#66d9ef">new</span> VbLib.ITesting.TestData();
</span></span></code></pre></div><p>That is not to say it is a good thing to do - I have encountered problems with XML Deserialization not working if it needed to deserialize an enum that was declared inside an interface.</p>
<h2 id="indexed-properties">Indexed Properties</h2>
<p>Again, this is perfectly legal in VB:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">CustomCollection</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Inherits</span> List(<span style="color:#66d9ef">Of</span> CustomObject)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Default</span> <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Shadows</span> <span style="color:#66d9ef">ReadOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">Item</span>(<span style="color:#66d9ef">ByVal</span> index <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span>) <span style="color:#f92672">As</span> CustomObject
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">MyBase</span>.Item(index)
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">ReadOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">IndexedReadOnly</span>(<span style="color:#66d9ef">ByVal</span> index <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span>) <span style="color:#f92672">As</span> CustomObject
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">Me</span>(index)
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">IndexedReadWrite</span>(<span style="color:#66d9ef">ByVal</span> index <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span>) <span style="color:#f92672">As</span> CustomObject
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">Me</span>(index)
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Set</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> CustomObject)
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">MyBase</span>.Item(index) <span style="color:#f92672">=</span> value
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Set</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">ReadOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">EnumIndexed</span>(<span style="color:#66d9ef">ByVal</span> type <span style="color:#f92672">As</span> CustomObject.CustomTypes) <span style="color:#f92672">As</span> CustomObject
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">Me</span>.FirstOrDefault(Function(x) x.Type <span style="color:#f92672">=</span> type)
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span></code></pre></div><p>It compiles, and runs fine from VB:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">Test</span>()
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Dim</span> collection <span style="color:#f92672">=</span> <span style="color:#66d9ef">New</span> CustomCollection()
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Dim</span> output <span style="color:#f92672">=</span> collection.EnumIndexed(CustomObject.CustomTypes.Testing)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span></code></pre></div><p>However trying to consume this from C# will not work:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> item = collection.EnumIndexed(VbLib.CustomObject.CustomTypes.Other);
</span></span></code></pre></div><p>But like this will:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> item = collection.get_EnumIndexed(VbLib.CustomObject.CustomTypes.Other);
</span></span></code></pre></div>]]></content:encoded></item><item><title>c# Enum casting</title><link>https://andydote.co.uk/2011/08/09/c-enum-casting/</link><pubDate>Tue, 09 Aug 2011 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2011/08/09/c-enum-casting/</guid><description>I am all for strong typing, and explicit casts, but some things in C# do seem to be a bit over-wordy. For instance, I would quite often have code that looks like the following in VB.Net:
Public Enum Columns Name Value Action End Enum Private Sub InitialiseGrid(ByVal grid as SourceGrid.Grid) grid.ColumnCount = [Enum].GetValues(GetType(Columns)).Count grid.Columns(Columns.Name).AutoSizeMode = SourceGrid.AutoSizeMode.EnableAutoSizeView grid.Columns(Columns.Value).AutoSizeMode = SourceGrid.AutoSizeMode.EnableAutoSizeView | SourceGrid.AutoSizeMode.EnableStretch grid.Columns(Columns.Action).AutoSizeMode = SourceGrid.AutoSizeMode.None grid.Columns(Columns.Action).Width = 30 &amp;#39;etc... End Sub The problem arrives when you try to write the same in C#, specifically the part when accessing the Columns collection using the enum:</description><content:encoded><![CDATA[<p>I am all for strong typing, and explicit casts, but some things in C# do seem to be a bit over-wordy.  For instance, I would quite often have code that looks like the following in VB.Net:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Enum</span> <span style="color:#a6e22e">Columns</span>
</span></span><span style="display:flex;"><span>	Name
</span></span><span style="display:flex;"><span>	Value
</span></span><span style="display:flex;"><span>	Action
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Enum</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">InitialiseGrid</span>(<span style="color:#66d9ef">ByVal</span> grid <span style="color:#f92672">as</span> SourceGrid.Grid)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	grid.ColumnCount <span style="color:#f92672">=</span> <span style="color:#f92672">[</span>Enum<span style="color:#f92672">]</span>.GetValues(<span style="color:#f92672">GetType</span>(Columns)).Count
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	grid.Columns(Columns.Name).AutoSizeMode <span style="color:#f92672">=</span> SourceGrid.AutoSizeMode.EnableAutoSizeView
</span></span><span style="display:flex;"><span>	grid.Columns(Columns.Value).AutoSizeMode <span style="color:#f92672">=</span> SourceGrid.AutoSizeMode.EnableAutoSizeView <span style="color:#960050;background-color:#1e0010">|</span> SourceGrid.AutoSizeMode.EnableStretch
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	grid.Columns(Columns.Action).AutoSizeMode <span style="color:#f92672">=</span> SourceGrid.AutoSizeMode.None
</span></span><span style="display:flex;"><span>	grid.Columns(Columns.Action).Width <span style="color:#f92672">=</span> 30
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">&#39;etc...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span></code></pre></div><p>The problem arrives when you try to write the same in C#, specifically the part when accessing the Columns collection using the enum:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>grid.Columns[Columns.Name].AutoSizeMode = SourceGrid.AutoSizeMode.EnableAutoSizeView;
</span></span></code></pre></div><p>Sorry, no dice, you must cast the enum to an int first.  What? Really? It&rsquo;s an int value at heart anyway (by default at any rate) and you can even specify an Enum to use an Int (or other numeric data type) if you should so wish, so why does this need an explicit cast?  This just looks nasty, in my opinion:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>grid.Columns[(<span style="color:#66d9ef">int</span>)Columns.Name].AutoSizeMode = SourceGrid.AutoSizeMode.EnableAutoSizeView;
</span></span></code></pre></div><p>I can only think of two ways of maintaining the cleanness that the VB provides, and both are more effort.  The first is to create an ExtensionMethod for the Grid with the following signature, doing the casting inside the method, and using type inference to allow the enum to be passed straight in:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> ColumnInfo ColumnAt&lt;T&gt;(self grid Grid, T index) <span style="color:#66d9ef">where</span> T : <span style="color:#66d9ef">struct</span>
</span></span></code></pre></div><p>The second method is to not use an enum to store our column indexes, but to use a class, with constants.  The only down side I can see to this is the lack of being able to count the number of columns, based on the members (without resorting to reflection, or a lambda for finding the Max value):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Columns</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">int</span> Name = <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">int</span> Value = <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">int</span> Action = <span style="color:#ae81ff">2</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I am not a fan of the ExtensionMethod method, and I would use the class personally - usually hard coding the number of columns is fine, but I still prefer the concise and simple version that VB.Net allows you.</p>
]]></content:encoded></item><item><title>Differences between Properties and Auto Properties</title><link>https://andydote.co.uk/2011/07/11/differences-between-properties-and-auto-properties/</link><pubDate>Mon, 11 Jul 2011 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2011/07/11/differences-between-properties-and-auto-properties/</guid><description>While writing some of the specs for ViewWeaver, I noticed that one was failing:
When passed a type with one write only property
it should return no mappings When I stepped through the code, it was indeed not filtering out the write only property. This is the code used to find all readable properties:
var allProperties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public); var readableProperties = allProperties.Where(p =&amp;gt; p.CanRead &amp;amp;&amp;amp; !p.GetIndexParameters().Any()); For some reason CanRead was returning true, then I noticed how I had defined my class under test:</description><content:encoded><![CDATA[<p>While writing some of the specs for <a href="https://github.com/Pondidum/ViewWeaver">ViewWeaver</a>, I noticed that one was failing:</p>
<blockquote>
<p>When passed a type with one write only property<br /></p>
<ul>
<li>it should return no mappings</li>
</ul>
</blockquote>
<p>When I stepped through the code, it was indeed not filtering out the write only property.
This is the code used to find all readable properties:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> allProperties = <span style="color:#66d9ef">typeof</span>(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> readableProperties = allProperties.Where(p =&gt; p.CanRead &amp;&amp; !p.GetIndexParameters().Any());
</span></span></code></pre></div><p>For some reason <code>CanRead</code> was returning true, then I noticed how I had defined my class under test:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">OnePublicWriteonlyProperty</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> String Test { <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>So it turns out that even though I had filtered to all Public Properties, a private Getter (or Setter) still passes through.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> allProperties = <span style="color:#66d9ef">typeof</span>(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> readableProperties = allProperties.Where(p =&gt; p.CanRead &amp;&amp;
</span></span><span style="display:flex;"><span>											 p.GetGetMethod() != <span style="color:#66d9ef">null</span> &amp;&amp;
</span></span><span style="display:flex;"><span>											 p.GetGetMethod().IsPublic &amp;&amp;
</span></span><span style="display:flex;"><span>											 !p.GetIndexParameters().Any());
</span></span></code></pre></div><p>Changing the expression to check for the GetMethod existing, and being public fixed this, and seems obvious in retrospect, but it is worth remembering that an Auto Property is ever so slightly different from a plain property with only a Get or Set method defined.</p>
]]></content:encoded></item><item><title>(Miss)Use of Narrowing-Implicit Operators</title><link>https://andydote.co.uk/2011/03/17/missuse-of-narrowing-implicit-operators/</link><pubDate>Thu, 17 Mar 2011 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2011/03/17/missuse-of-narrowing-implicit-operators/</guid><description>I have covered a use of Narrowing/Implicit Operators before, but I was thinking the other day about use of Fluent Interfaces, and if it was possible to have one on a cache/repository type class, that would allow you to chain options together, but stop at any point and have the result.
I gave it a go, and came up with this:
public class Person { public string Name { get; set; } public int Age { get; set; } public Person(string name, int age) { this.</description><content:encoded><![CDATA[<p>I have covered a use of Narrowing/Implicit Operators before, but I was thinking the other day about use of Fluent Interfaces, and if it was possible to have one on a cache/repository type class, that would allow you to chain options together, but stop at any point and have the result.</p>
<p>I gave it a go, and came up with this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Person</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">string</span> Name { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> Age { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Person(<span style="color:#66d9ef">string</span> name, <span style="color:#66d9ef">int</span> age)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">this</span>.Name = name;
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">this</span>.Age = age;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PersonManager</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> PersonOptions GetPerson()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> PersonOptions(<span style="color:#66d9ef">new</span> Person(<span style="color:#e6db74">&#34;dave&#34;</span>, <span style="color:#ae81ff">21</span>));
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PersonOptions</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> Person Person { <span style="color:#66d9ef">get</span>; <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">set</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> PersonOptions(Person person)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">this</span>.Person = person;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> PersonOptions WaitForFreshResults()
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//...</span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">this</span>;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">implicit</span> <span style="color:#66d9ef">operator</span> Person(PersonOptions options)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> options.Person;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Which can be used like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>Person p1 = PersonManager.GetPerson();
</span></span><span style="display:flex;"><span>Person p2 = PersonManager.GetPerson().WaitForFreshResults();
</span></span></code></pre></div><p>Which is all very well and good - but nowadays, everyone (well nearly everyone) loves the <code>var</code> keyword, so what happens if it is used like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> p3 = PersonManager.GetPerson();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> p4 = PersonManager.GetPerson().WaitForFreshResults();
</span></span></code></pre></div><p>Uh oh.  That&rsquo;s not a person you have in that variable, it&rsquo;s a PersonOptions.  The compiler does help with this, as none of your <code>Person</code> methods will be present, and the PersonOptions class does provide a Person object as a Read Only Property, so the code can be modified to use that:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> p5 = PersonManager.GetPerson().WaitForFreshResults().Person;
</span></span></code></pre></div><p>I&rsquo;m not entirely comfortable with using implicit conversions like this, especially with <code>var</code>, but it does work rather well, as long as you are careful.</p>
]]></content:encoded></item><item><title>Expression Rules, Version 2</title><link>https://andydote.co.uk/2011/02/09/expression-rules-version-2/</link><pubDate>Wed, 09 Feb 2011 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2011/02/09/expression-rules-version-2/</guid><description>Recently I have written a rules engine for a very large menu system in an application I work on. Many of the rules apply many items, so I didn&amp;rsquo;t wish to have to express the same rule many times. To avoid this, the rule engine DSL was born:
Concerns.When(item =&amp;gt; /* rule of some sort */) .AppliesToAll() .Except(MenuItems.ToggleHidden, MenuItems.Refresh) And rules are rolled together, so a specific menu item must have all of its rules evaluating to true to be displayed.</description><content:encoded><![CDATA[<p>Recently I have written a rules engine for a very large menu system in an application I work on.  Many of the rules apply many items, so I didn&rsquo;t wish to have to express the same rule many times.  To avoid this, the rule engine DSL was born:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>Concerns.When(item =&gt; <span style="color:#75715e">/* rule of some sort */</span>)
</span></span><span style="display:flex;"><span>		.AppliesToAll()
</span></span><span style="display:flex;"><span>		.Except(MenuItems.ToggleHidden, MenuItems.Refresh)
</span></span></code></pre></div><p>And rules are rolled together, so a specific menu item must have all of its rules evaluating to true to be displayed.</p>
<p>The problem arose when an item was displaying when it shouldn&rsquo;t (or vice versa).  Debugging with rules specified like this was a pain, and when I saw the article about <a href="http://daniel.wertheim.se/2011/02/07/c-clean-up-your-linq-queries-and-lambda-expressions/">ExpressionRules</a> by <a href="http://daniel.wertheim.se/">Daniel Wertheim</a>, I thought it would help solve my problem.  He replaces Lambda conditions with a class and implicit operator, allowing code to be changed from something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> bonusCustomers = _customers.Where(c =&gt;
</span></span><span style="display:flex;"><span>		(c.NumOfYearsAsMember == <span style="color:#ae81ff">0</span> &amp;&amp; c.CashSpent &gt;= <span style="color:#ae81ff">3000</span>) ||
</span></span><span style="display:flex;"><span>		(c.NumOfYearsAsMember &gt; <span style="color:#ae81ff">0</span> &amp;&amp; (c.CashSpent / c.NumOfYearsAsMember) &gt;= <span style="color:#ae81ff">5000</span>));
</span></span></code></pre></div><p>To something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> bonusCustomers = _customers.Where(<span style="color:#66d9ef">new</span> IsBonusCustomer());
</span></span></code></pre></div><p>He does this using a base class and then inheriting from it to create the rule:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">IsBonusCustomer</span> : ExpressionRule&lt;Customer&gt;, IIsBonusCustomer
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> IsBonusCustomer()
</span></span><span style="display:flex;"><span>		: <span style="color:#66d9ef">base</span>(c =&gt;
</span></span><span style="display:flex;"><span>				(c.NumOfYearsAsMember == <span style="color:#ae81ff">0</span> &amp;&amp; c.CashSpent &gt;= <span style="color:#ae81ff">3000</span>) ||
</span></span><span style="display:flex;"><span>				(c.NumOfYearsAsMember &gt; <span style="color:#ae81ff">0</span> &amp;&amp; (c.CashSpent / c.NumOfYearsAsMember) &gt;= <span style="color:#ae81ff">5000</span>))
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I took his base class and modified it to this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ExpressionRule</span>&lt;T&gt; <span style="color:#66d9ef">where</span> T : <span style="color:#66d9ef">class</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">bool</span> Rule(T item);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">implicit</span> <span style="color:#66d9ef">operator</span> Func&lt;T, <span style="color:#66d9ef">bool</span>&gt;(ExpressionRule&lt;T&gt; item)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> item.Rule;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">bool</span> Evaluate(T item)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> Rule(item);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This means the IsBonusCustomer now becomes this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">IsBonusCustomer</span> : ExpressionRule&lt;Customer&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">bool</span> Rule(Customer customer)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> (c.NumOfYearsAsMember == <span style="color:#ae81ff">0</span> &amp;&amp; c.CashSpent &gt;= <span style="color:#ae81ff">3000</span>) ||
</span></span><span style="display:flex;"><span>			   (c.NumOfYearsAsMember &gt; <span style="color:#ae81ff">0</span> &amp;&amp; (c.CashSpent / c.NumOfYearsAsMember) &gt;= <span style="color:#ae81ff">5000</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Not only do we still have the readability of the first version, but a full function that can have logging added to it, and easier debugging.</p>
]]></content:encoded></item><item><title>Adding MSpec to your Git Bash</title><link>https://andydote.co.uk/2010/11/13/adding-mspec-to-your-git-bash/</link><pubDate>Sat, 13 Nov 2010 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2010/11/13/adding-mspec-to-your-git-bash/</guid><description>My workflow involves Visual Studio, Notepad++ and Git Bash. I don&amp;rsquo;t use much Visual Studio integration, and prefer to run most things from the command line.
Now when it comes to testing projects, my tool of choice is MSpec (Machine.Specifications), which I decided would be nice if I could run from my Git Bash.
$ mspec bin/project.specs.dll To do this, you need to write a Shell Script with the following contents:</description><content:encoded><![CDATA[<p>My workflow involves Visual Studio, Notepad++ and Git Bash.  I don&rsquo;t use much Visual Studio integration, and prefer to run most things from the command line.</p>
<p>Now when it comes to testing projects, my tool of choice is MSpec (Machine.Specifications), which I decided would be nice if I could run from my Git Bash.</p>
<pre><code>$ mspec bin/project.specs.dll
</code></pre>
<p>To do this, you need to write a Shell Script with the following contents:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>    <span style="color:#75715e">#!/bin/sh</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;D:\dev\downloaded-src\machine.specifications\Build\Release\mspec.exe&#34;</span> <span style="color:#e6db74">&#34;</span>$*<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">#obviously change this to your mspec path...</span>
</span></span></code></pre></div><p>Save it as <code>mspec</code> (no extension), and you can place it in one of two places:</p>
<ul>
<li>Your Home Directory: <code>C:\Users\&lt;name&gt;\</code>, useful if it&rsquo;s just for you</li>
<li>The Git Bin Directory: <code>C:\Program Files\Git\bin</code>, for if you want all users to be able to run the script</li>
</ul>
<p>Restart your git bash, and you can now use the command <code>mspec</code> to run all your specifications.</p>
]]></content:encoded></item><item><title>Databinding to a DataGridView - The order of columns</title><link>https://andydote.co.uk/2010/10/20/databinding-to-a-datagridview-the-order-of-columns/</link><pubDate>Wed, 20 Oct 2010 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2010/10/20/databinding-to-a-datagridview-the-order-of-columns/</guid><description>A while ago I was writing a small history grid in one of our applications at work. It has a single HistoryItem object, which is fairly straightforward, something like this:
Class HistoryItem { public int ID { get{ return _id; } } public DateTime CreateDate { get { return _createDate; } } public String Creator { get { return _creatorName; } } public String Note { get { return _note; } } } This was populated into a List&amp;lt;HistoryItem&amp;gt; and bound to the DataGridView directly:</description><content:encoded><![CDATA[<p>A while ago I was writing a small history grid in one of our applications at work.  It has a single <code>HistoryItem</code> object, which is fairly straightforward, something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>Class HistoryItem
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">int</span> ID { <span style="color:#66d9ef">get</span>{ <span style="color:#66d9ef">return</span> _id; } }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> DateTime CreateDate { <span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> _createDate; } }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> String Creator { <span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> _creatorName; } }
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">public</span> String Note { <span style="color:#66d9ef">get</span> { <span style="color:#66d9ef">return</span> _note; } }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This was populated into a <code>List&lt;HistoryItem&gt;</code> and bound to the <code>DataGridView</code> directly:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>	dgvHistory.DataSource = ScreenEntity.History.ToList();
</span></span></code></pre></div><p>This exposes something interesting about how the DataGridView picks column order: It&rsquo;s not done by Alphabetical Order; it is done by Definition Order.  So the order in which the properties in the class are defined is the order that the grid view will display. Usually.</p>
<p>When the piece of software was deployed (in house software, to be used by about 10 people), one user requested the order of the columns be changed.  She didn&rsquo;t like the fact that the order was this for her: <code>Note, ID, CreateDate, Creator</code>.</p>
<p>After checking my copy of the software and several other users&rsquo; copies, it turned out the order was only different on her machine.  She could login to another machine and it would be fine.  At the time I never got to the bottom of why it was setting the wrong order, but fixed it by manually specifying the column order after binding.</p>
<p>Yesterday however I was reading an article by <a href="http://www.abhisheksur.com/2010/10/hidden-facts-on-c-constructor-in.html">Abhishek Sur on the Hidden Facts of C# Structures in terms of MSIL</a> and noticed this piece of information:</p>
<blockquote>
<p>DemoClass is declared as auto&hellip;Auto allows the loader to change the layout of the class which it sees fit. That means the order of the members will not be kept intact while the object is created. It is also going to ignore any layout information for the class mentioned explicitly.</p>
</blockquote>
<p>Now while I am unable to reproduce this problem currently as I am not near work, I do wonder if the reason column orders were fine on most machines was because the CLR was keeping the properties in definition order, with the exception of one machine, where for whatever reason it was reordering the properties.</p>
<p>If this problem arises again then I will have a go at fixing it by changing to a Structure (which by default are declared as Sequential in IL) and see if that fixes the problem.</p>
]]></content:encoded></item><item><title>Actually, I'll mutate if you don't mind</title><link>https://andydote.co.uk/2010/09/10/actually-i-ll-mutate-if-you-don-t-mind/</link><pubDate>Fri, 10 Sep 2010 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2010/09/10/actually-i-ll-mutate-if-you-don-t-mind/</guid><description>After I had changed all my extension methods to be functions and return a new object rather than mutating the self parameter, I changed them all back to be refs.
Why? Well mainly because the library I am writing is in VB, and these methods are internal. VB supports ByRef parameters as the first param in an extension method, so no problems there. The only reason I was changing them so that they were C# compatible was so that I could test them with MSpec in C#.</description><content:encoded><![CDATA[<p>After I had changed all my extension methods to be functions and return a new object rather than mutating the self parameter, I changed them all back to be refs.</p>
<p>Why? Well mainly because the library I am writing is in VB, and these methods are internal.  VB supports ByRef parameters as the first param in an extension method, so no problems there.  The only reason I was changing them so that they were C# compatible was so that I could test them with MSpec in C#. I solved this little dilemma by just calling the extension method on the static class like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>Because of = () =&gt; EnumExtensions.Add(<span style="color:#66d9ef">ref</span> testEnum, (<span style="color:#66d9ef">int</span>)FlagsTest.Four);
</span></span></code></pre></div><p>This works, and lets me use the extensions how I think they should work.  The real question is why do I think my flags methods (Add, Remove) should mutate the instance, when I am quite happy with <code>string</code> and <code>DateTime</code> methods returning new instances?  I think it might be in the naming conventions.</p>
<p>A <code>List&lt;T&gt;</code> has <code>Add</code> and <code>Remove</code> methods, which modify the existing instance.  SO maybe if I had called my methods <code>WithFlag()</code> and <code>WithoutFlag()</code> I wouldn&rsquo;t have expected mutation?  I&rsquo;m not entirely convinced as <code>DateTime</code> has <code>AddMinutes</code> and <code>AddHours</code>, which don&rsquo;t mutate and return a new instance.  Now that I think about it, that surprised me when I first used them.  I think, as usual, it&rsquo;s down to doing what makes the most sense in the situation.</p>
]]></content:encoded></item><item><title>To mutate or not to mutate</title><link>https://andydote.co.uk/2010/09/08/to-mutate-or-not-to-mutate/</link><pubDate>Wed, 08 Sep 2010 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2010/09/08/to-mutate-or-not-to-mutate/</guid><description>I have been working on a project recently that involves a lot of work with Flags Enums. To aid with this I created a set of Extension Methods:
Add(Of T as Structure)(self as T, value as Int) as T Add(Of T as Structure)(self as T, values() as Int) as T Remove(Of T as Structure)(self as T, value as Int) as T Remove(Of T as Structure)(self as T, values() as Int) as T Has(Of T as Structure)(self as T, value as Int) as Boolean HasAll(Of T as Structure)(self as T, values() as Int) as Boolean HasAny(Of T as Structure)(self as T, values() as Int) as Boolean Now the last 3 methods I am happy with - they are self explanatory and do what&amp;rsquo;s expected.</description><content:encoded><![CDATA[<p>I have been working on a project recently that involves a lot of work with Flags Enums.  To aid with this I created a set of Extension Methods:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span>Add(<span style="color:#66d9ef">Of</span> T <span style="color:#f92672">as</span> Structure)(self <span style="color:#f92672">as</span> T, value <span style="color:#f92672">as</span> Int) <span style="color:#f92672">as</span> T
</span></span><span style="display:flex;"><span>Add(<span style="color:#66d9ef">Of</span> T <span style="color:#f92672">as</span> Structure)(self <span style="color:#f92672">as</span> T, values() <span style="color:#f92672">as</span> Int) <span style="color:#f92672">as</span> T
</span></span><span style="display:flex;"><span>Remove(<span style="color:#66d9ef">Of</span> T <span style="color:#f92672">as</span> Structure)(self <span style="color:#f92672">as</span> T, value <span style="color:#f92672">as</span> Int) <span style="color:#f92672">as</span> T
</span></span><span style="display:flex;"><span>Remove(<span style="color:#66d9ef">Of</span> T <span style="color:#f92672">as</span> Structure)(self <span style="color:#f92672">as</span> T, values() <span style="color:#f92672">as</span> Int) <span style="color:#f92672">as</span> T
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Has(<span style="color:#66d9ef">Of</span> T <span style="color:#f92672">as</span> Structure)(self <span style="color:#f92672">as</span> T, value <span style="color:#f92672">as</span> Int) <span style="color:#f92672">as</span> <span style="color:#66d9ef">Boolean</span>
</span></span><span style="display:flex;"><span>HasAll(<span style="color:#66d9ef">Of</span> T <span style="color:#f92672">as</span> Structure)(self <span style="color:#f92672">as</span> T, values() <span style="color:#f92672">as</span> Int) <span style="color:#f92672">as</span> <span style="color:#66d9ef">Boolean</span>
</span></span><span style="display:flex;"><span>HasAny(<span style="color:#66d9ef">Of</span> T <span style="color:#f92672">as</span> Structure)(self <span style="color:#f92672">as</span> T, values() <span style="color:#f92672">as</span> Int) <span style="color:#f92672">as</span> <span style="color:#66d9ef">Boolean</span>
</span></span></code></pre></div><p>Now the last 3 methods I am happy with - they are self explanatory and do what&rsquo;s expected.  The first four however I am less convinced by.</p>
<p>My main problem is how I wrote some code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Dim</span> state <span style="color:#f92672">=</span> States.Blank
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">If</span> someCondition <span style="color:#66d9ef">Then</span> state.Add(States.Disabled)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">If</span> someOtherCondition <span style="color:#66d9ef">Then</span> state.Add(States.Disconnected)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">return</span> state
</span></span></code></pre></div><p>Which to my surprise always returned <code>States.Blank</code> rather than <code>Disabled</code> or <code>Disconnected</code> or a combination of the two.  After a lot of close looking, I realised it was because the <code>Add</code> method was a function and I was not using the return value.</p>
<p>The logical thing seemed to be changing the extension methods to use a reference parameter rather than a value parameter.  While this worked in my vb.net library, the second I tried to use it in my C# test project (MSpec), it broke with the following error:</p>
<blockquote>
<p>Error	Argument 1 must be passed with the &lsquo;ref&rsquo; keyword</p>
</blockquote>
<p>So it cannot work like this, I have to return the result as a new instance of the enum.  I don&rsquo;t like it, but other Structure based code (such as DateTime, String) work like this too.</p>
<p>On the point of mutability, I think a system like Ruby&rsquo;s of indicating a destructive method would be good:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>stringValue<span style="color:#f92672">.</span>chomp!		<span style="color:#e6db74">//</span><span style="color:#66d9ef">This</span> will modify stringValue
</span></span><span style="display:flex;"><span>stringValue<span style="color:#f92672">.</span>chomp		<span style="color:#e6db74">//</span><span style="color:#66d9ef">This</span> will <span style="color:#66d9ef">return</span> a <span style="color:#66d9ef">new</span> instance which has been chomped
</span></span></code></pre></div><p>But for now I will settle for returning a new instance.</p>
]]></content:encoded></item><item><title>Using Visual Studio's Regex Find and Replace</title><link>https://andydote.co.uk/2010/08/31/using-visual-studio-s-regex-find-and-replace/</link><pubDate>Tue, 31 Aug 2010 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2010/08/31/using-visual-studio-s-regex-find-and-replace/</guid><description>The Visual Studio Find and Replace dialog is often overlooked, and when parts of it are looked at (Regex searching) it often gets a bad rep. Sure it doesn&amp;rsquo;t implement all of the Regex syntax (non greedy search springs to mind), but that&amp;rsquo;s not to say it isn&amp;rsquo;t useful.
For instance, I was working on some code that involved a Model View Presenter type style, but used Subroutines (void methods) rather than WriteOnly properties for brevity (in C# you can do a Set only property in 1 line, VB it takes 5).</description><content:encoded><![CDATA[<p>The Visual Studio Find and Replace dialog is often overlooked, and when parts of it are looked at (Regex searching) it often gets a bad rep.  Sure it doesn&rsquo;t implement all of the Regex syntax (non greedy search springs to mind), but that&rsquo;s not to say it isn&rsquo;t useful.</p>
<p>For instance, I was working on some code that involved a Model View Presenter type style, but used Subroutines (void methods) rather than WriteOnly properties for brevity (in C# you can do a Set only property in 1 line, VB it takes 5).  As the View is doing nothing other than assigning labels from these &ldquo;Setters&rdquo; who cares how many lines it takes?</p>
<p>A quick breakdown of the parts of the expressions used:</p>
<pre><code>Finding:
{}		//Tag an expression, used in replacements.  Numbered sequentially from 1, not 0.
(.*)	//Any character, any number of times, as many as possible.
\		//escape character, allows us to search for a literal '.' or other Regex used symbol.

Replacing:
\1		//The content of a tagged expression.
\n		//New line
\t		//Tab (although after running all these find and replaces, a quick {CTRL+E, CTRL+D} (format document) does most of the tidying for you).
</code></pre>
<p>So we start with the Interface:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Interface</span> IProcessDetailsView
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">FileID</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">SubmittedBy</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> <span style="color:#66d9ef">String</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">ReceivedDate</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> DateTime)
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">//</span>...
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Interface</span>
</span></span></code></pre></div><p>So in the find and replace dialog I enter the following:</p>
<pre><code>Find what:
Sub {(.*)}\(ByVal value As {(.*)}\)

Replace with:
WriteOnly Property \1() As \2
</code></pre>
<p>The interface definition now changes to this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Interface</span> IProcessDetailsView
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">WriteOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">FileID</span>() <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">WriteOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">SubmittedBy</span>() <span style="color:#f92672">As</span> <span style="color:#66d9ef">String</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">WriteOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">ReceivedDate</span>() <span style="color:#f92672">As</span> DateTime
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">//</span>...
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Interface</span>
</span></span></code></pre></div><p>Not too difficult right?  Good. Now onto the View&rsquo;s methods:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">ProcessDetails</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Implements</span> IProcessDetailsView
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">FileID</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span>) <span style="color:#66d9ef">Implements</span> IProcessDetailsView.FileID
</span></span><span style="display:flex;"><span>		lblFileID.Text <span style="color:#f92672">=</span> value.ToString
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">SubmittedBy</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> <span style="color:#66d9ef">String</span>) <span style="color:#66d9ef">Implements</span> IProcessDetailsView.SubmittedBy
</span></span><span style="display:flex;"><span>		lblAccountName.Text <span style="color:#f92672">=</span> value
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">//</span>...
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span></code></pre></div><p>Into the find and replace dialog:</p>
<pre><code>Find what:
Public Sub {(.*)}\(ByVal value As {(.*)}\) Implements IProcessDetailsView\.(.*)

Replace with:
Public WriteOnly Property \1() As \2 Implements IProcessDetailsView.\1\n\t\tSet(ByVal value As \2)

Find what:
End Sub

Replace with:
End Set\n\tEnd Property
</code></pre>
<p>You could do this with one expression, although I have found its far less hassle to use two find and replace runs rather than trying to find new lines etc</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">ProcessDetails</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Implements</span> IProcessDetailsView
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">WriteOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">FileID</span>() <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span> <span style="color:#66d9ef">Implements</span> IProcessDetailsView.FileID
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Set</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span>)
</span></span><span style="display:flex;"><span>			lblFileID.Text <span style="color:#f92672">=</span> value.ToString
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Set</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">WriteOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">SubmittedBy</span>() <span style="color:#f92672">As</span> <span style="color:#66d9ef">String</span> <span style="color:#66d9ef">Implements</span> IProcessDetailsView.SubmittedBy
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Set</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> <span style="color:#66d9ef">String</span>)
</span></span><span style="display:flex;"><span>			lblAccountName.Text <span style="color:#f92672">=</span> value
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Set</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span></code></pre></div><p>Now the main reason for this change was the presenter code, which doesn&rsquo;t sit right with me.  At a glance, am I expecting something to be calculated or what?</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">Display</span>(<span style="color:#66d9ef">ByVal</span> processHistory <span style="color:#f92672">As</span> ICVProcessHistory)
</span></span><span style="display:flex;"><span>	_view.FileID(processHistory.FileID)
</span></span><span style="display:flex;"><span>	_view.SubmittedBy(processHistory.AccountName)
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">//</span>...
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span></code></pre></div><p>Find and replace dialog again:</p>
<pre><code>Find what:
\_view\.{(.*)}\({(.*)}\.{(.*)}\)

Replace with:
_view.\1 = \2.\3
</code></pre>
<p>Which gives us this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">Display</span>(<span style="color:#66d9ef">ByVal</span> processHistory <span style="color:#f92672">As</span> ICVProcessHistory)
</span></span><span style="display:flex;"><span>	_view.FileID <span style="color:#f92672">=</span> processHistory.FileID
</span></span><span style="display:flex;"><span>	_view.SubmittedBy <span style="color:#f92672">=</span> processHistory.AccountName
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">//</span>...
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span></code></pre></div><p>Much better in my opinion.</p>
]]></content:encoded></item><item><title>Multilining If statements conditions should be banned. now.</title><link>https://andydote.co.uk/2010/03/24/multilining-if-statements-conditions-should-be-banned-now/</link><pubDate>Wed, 24 Mar 2010 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2010/03/24/multilining-if-statements-conditions-should-be-banned-now/</guid><description>Multilining if statement conditions is bad. I was modifying some code and came across this:
If String.IsNullOrEmpty(_selectedGUID) OrElse _ _selectedGUID = FeeAgreement.GetDefaultContractAgreementGuid OrElse _ _selectedGUID = FeeAgreement.DefaultPermAgreementGuid Then fgFeeAgreements.SetCellCheck(rowAdded, 0, CheckEnum.Checked) _selectedTitle = ag.Title _lastIndexRowSelected = rowAdded End If Which at a glance looks like this:
Single Line If Variable Assignment Variable Assignment
One person suggested that if someone had to do multiline the condition they could at least indent it.</description><content:encoded><![CDATA[<p>Multilining if statement conditions is bad.  I was modifying some code and came across this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">If</span> <span style="color:#66d9ef">String</span>.IsNullOrEmpty(_selectedGUID) <span style="color:#f92672">OrElse</span> _
</span></span><span style="display:flex;"><span>_selectedGUID <span style="color:#f92672">=</span> FeeAgreement.GetDefaultContractAgreementGuid <span style="color:#f92672">OrElse</span> _
</span></span><span style="display:flex;"><span>_selectedGUID <span style="color:#f92672">=</span> FeeAgreement.DefaultPermAgreementGuid <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	fgFeeAgreements.SetCellCheck(rowAdded, 0, CheckEnum.Checked)
</span></span><span style="display:flex;"><span>	_selectedTitle <span style="color:#f92672">=</span> ag.Title
</span></span><span style="display:flex;"><span>	_lastIndexRowSelected <span style="color:#f92672">=</span> rowAdded
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span></code></pre></div><p>Which at a glance looks like this:</p>
<blockquote>
<p>Single Line If
Variable Assignment
Variable Assignment</p>
</blockquote>
<p>One person suggested that if someone had to do multiline the condition they could at least indent it.  That&rsquo;s not much good either though:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">If</span> <span style="color:#66d9ef">String</span>.IsNullOrEmpty(_selectedGUID) <span style="color:#f92672">OrElse</span> _
</span></span><span style="display:flex;"><span>	_selectedGUID <span style="color:#f92672">=</span> FeeAgreement.GetDefaultContractAgreementGuid <span style="color:#f92672">OrElse</span> _
</span></span><span style="display:flex;"><span>	_selectedGUID <span style="color:#f92672">=</span> FeeAgreement.DefaultPermAgreementGuid <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	fgFeeAgreements.SetCellCheck(rowAdded, 0, CheckEnum.Checked)
</span></span><span style="display:flex;"><span>	_selectedTitle <span style="color:#f92672">=</span> ag.Title
</span></span><span style="display:flex;"><span>	_lastIndexRowSelected <span style="color:#f92672">=</span> rowAdded
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span></code></pre></div><p>Looks like this:</p>
<blockquote>
<p>If Condition Then
Variable Assignment
Variable Assignment</p>
</blockquote>
<p>You could one line the whole thing, which while I think is better than multi line conditionals, still isn&rsquo;t great as I cant see all of it on a normal sized screen (read &ldquo;work supplied screen&rdquo;).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">If</span> <span style="color:#66d9ef">String</span>.IsNullOrEmpty(_selectedGUID) <span style="color:#f92672">OrElse</span> _selectedGUID <span style="color:#f92672">=</span> FeeAgreement.GetDefaultContractAgreementGuid <span style="color:#f92672">OrElse</span> _selectedGUID <span style="color:#f92672">=</span> FeeAgreement.DefaultPermAgreementGuid <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	fgFeeAgreements.SetCellCheck(rowAdded, 0, CheckEnum.Checked)
</span></span><span style="display:flex;"><span>	_selectedTitle <span style="color:#f92672">=</span> ag.Title
</span></span><span style="display:flex;"><span>	_lastIndexRowSelected <span style="color:#f92672">=</span> rowAdded
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span></code></pre></div><p>So, Why not just do it as suggested in Code Complete, which fits on my screen and explains the comparisons:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Dim</span> isContract <span style="color:#f92672">=</span> (_selectedGUID <span style="color:#f92672">=</span> FeeAgreement.GetDefaultContractAgreementGuid)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">Dim</span> isPerm <span style="color:#f92672">=</span> (_selectedGUID <span style="color:#f92672">=</span> FeeAgreement.DefaultPermAgreementGuid)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">If</span> <span style="color:#66d9ef">String</span>.IsNullOrEmpty(_selectedGUID) <span style="color:#f92672">OrElse</span> isContract <span style="color:#f92672">OrElse</span> isPerm <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	fgFeeAgreements.SetCellCheck(rowAdded, 0, CheckEnum.Checked)
</span></span><span style="display:flex;"><span>	_selectedTitle <span style="color:#f92672">=</span> ag.Title
</span></span><span style="display:flex;"><span>	_lastIndexRowSelected <span style="color:#f92672">=</span> rowAdded
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span></code></pre></div><p>I don&rsquo;t know who wrote the above original code, and I don&rsquo;t much care either.
I do however think that the people who like the original style are clinically insane&hellip;and I work with at least one like this!</p>
<p>Some unit tests wouldn&rsquo;t go amiss either.  Well, tests of any kind would be a good start&hellip;</p>
]]></content:encoded></item><item><title>Converting from NUnit to MSTest</title><link>https://andydote.co.uk/2010/01/12/converting-from-nunit-to-mstest/</link><pubDate>Tue, 12 Jan 2010 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2010/01/12/converting-from-nunit-to-mstest/</guid><description>While this is not something I personally would want to do, we (for whatever reason&amp;hellip;) are to use MSTest at work (I think it is due to the whole &amp;ldquo;Its Microsoft, so it&amp;rsquo;s supported&amp;rdquo; argument).
Now as no one else on the team does any kind of unit testing (serious), the only test projects we have are written by me, on the quiet before being told if I wanted to unit test then use MSTest.</description><content:encoded><![CDATA[<p>While this is not something I personally would want to do, we (for whatever reason&hellip;) are to use MSTest at work (I think it is due to the whole &ldquo;Its Microsoft, so it&rsquo;s supported&rdquo; argument).</p>
<p>Now as no one else on the team does any kind of unit testing (serious), the only test projects we have are written by me, on the quiet before being told if I wanted to unit test then use MSTest.  So onto the point of this article.</p>
<p>When you create a project for tests with nunit, you just create a <code>Class Library</code>, add a reference to nunit (and Rhino.Mocks of course), build it and run with your preferred method (I like TDD.Net, but that involves paying for at work&hellip;so no go there).</p>
<p>When you want to do tests with MSTest, you just create a Test Project and start writing tests. On closer inspection, it&rsquo;s just a <code>Class Library</code> with a reference to <code>Microsoft.VisualStudio.QualityTools.UnitTestFramework</code>.  So converting one to the other should be easy, right?</p>
<p>Well not quite.  While there is nothing in the GUI to suggest so, you need to modify the csproj/vbproj file to get it to work.  This post on <a href="http://social.msdn.microsoft.com/Forums/en/vststest/thread/433e4860-b61f-44fd-bef9-a569fb32d244">MSDN</a>, had all the details, but in the interest of having things in more than one place (not very DRY I will admit, but there), here are the steps:</p>
<ol>
<li>Remove Reference to Nunit.Core &amp; Nunit.Framework</li>
<li>Add Reference to Microsoft.VisualStudio.QualityTools.UnitTestFramework</li>
<li>Find and Replace:</li>
</ol>
<ul>
<li><code>using NUnit.Framework;</code> with <code>using Microsoft.VisualStudio.TestTools.UnitTesting;</code> (I actually use a project level import, so I skip this)</li>
<li>[TestFixture] -&gt; [TestClass]</li>
<li>[Test] -&gt; [TestMethod]</li>
<li>[SetUp] -&gt; [TestInitialize]</li>
<li>[TearDown] -&gt; [TestCleanup]</li>
<li>[TestFixtureSetUp] -&gt; [ClassInitialize]</li>
<li>[TestFixtureTearDown] -&gt; [ClassCleanup]</li>
</ul>
<ol start="4">
<li>Change your Asserts:</li>
</ol>
<ul>
<li>Assert.Greater(x, y) -&gt; Assert.IsTrue(x &gt; y)</li>
<li>Assert.AreEqual(x, Is.EqualTo(y).IgnoreCase) -&gt;  Assert.AreEqual(x, y, True)</li>
</ul>
<ol start="5">
<li>The &lsquo;hidden&rsquo; part.  In your project file, locate <code>&lt;PropertyGroup&gt;</code> (not the one specifying debug|release settings), and add the following to it:</li>
</ol>
<ul>
<li><FileAlignment>512</FileAlignment></li>
<li>*.csproj files add:
<code>&lt;ProjectTypeGuids&gt;{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}&lt;/ProjectTypeGuids&gt;</code></li>
<li>*.vbproj files add:
<code>&lt;ProjectTypeGuids&gt;{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}&lt;/ProjectTypeGuids&gt;</code></li>
</ul>
<p>This was all I had to do to get our (my) tests running again under MSTest.  Except they didn&rsquo;t run, with the lovely error of:</p>
<blockquote>
<p>The location of the file or directory &lsquo;D:\Projects\Dev\SDK\Rhino.Mocks.dll&rsquo; is not trusted.</p>
</blockquote>
<p>That&rsquo;s odd, the file is on my hard disk, its not a network share, so what&rsquo;s the problem?  Right click on Rhino.Mocks.dll and:</p>
<p><img loading="lazy" src="unblock-file.jpg" alt="Unblock File"  />
</p>
<p>Click the Unblock button, hit Apply, re-run the tests.  All Working now :)</p>
<p>There are a few other points mentioned on the MSDN post too which you may run into:</p>
<blockquote>
<p>If you have relied on NUnit TestFixtureSetup and TestFixtureTearDown methods to do non-static things, will have to move functions in the former to a constructor and the latter to a destructor.  In MSTest, both of these methods must be declared as static.</p>
</blockquote>
<blockquote>
<p>If you are relying on AppDomain.CurrentDomain.BaseDirectory to get the root directory, your test will break.  The fix is explained at <a href="http://www.ademiller.com/blogs/tech/2008/01/gotchas-mstest-appdomain-changes-in-vs-2008/">http://www.ademiller.com/blogs/tech/2008/01/gotchas-mstest-appdomain-changes-in-vs-2008/</a>.</p>
</blockquote>
<p>Basically, you need to set your BaseDirectory in your MSTest TestClass constructor like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">string</span> currDir = Environment.CurrentDirectory.Substring(<span style="color:#ae81ff">0</span>, Environment.CurrentDirectory.IndexOf(<span style="color:#e6db74">&#34;TestResults&#34;</span>));
</span></span><span style="display:flex;"><span>AppDomain.CurrentDomain.SetData(<span style="color:#e6db74">&#34;APPBASE&#34;</span>, currDir);
</span></span></code></pre></div><blockquote>
<p>MSTest launches each test method in a separate STA thread instead of the MTA thread you may be expecting.  This probably won&rsquo;t give you any problems.</p>
</blockquote>
<p>Hope that helps everyone who has to do this kind of conversion.</p>
]]></content:encoded></item><item><title>Thanks Google for solving my problem!</title><link>https://andydote.co.uk/2009/12/16/thanks-google-for-solving-my-problem/</link><pubDate>Wed, 16 Dec 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/12/16/thanks-google-for-solving-my-problem/</guid><description>Following on from yesterday&amp;rsquo;s post about separation on concerns and where to put some undefined logic for a multi state checkbox, I did a fair amount of research.
I must say the Quince website is a good repository of UI Design Patterns, as is Welie. I couldn&amp;rsquo;t find anything like what I was after, which I guess means I shouldn&amp;rsquo;t be doing it this way?
After a while a brainwave struck me: &amp;ldquo;Gmail lets you select things, how does it do it?</description><content:encoded><![CDATA[<p>Following on from <a href="/functionality-and-seperation-of-concerns">yesterday&rsquo;s</a> post about separation on concerns and where to put some undefined logic for a multi state checkbox, I did a fair amount of research.</p>
<p>I must say the <a href="http://quince.infragistics.com">Quince</a> website is a good repository of UI Design Patterns, as is <a href="http://www.welie.com">Welie</a>.  I couldn&rsquo;t find anything like what I was after, which I guess means I shouldn&rsquo;t be doing it this way?</p>
<p>After a while a brainwave struck me: &ldquo;Gmail lets you select things, how does it do it?  One click on the Gmail icon and I&rsquo;m presented with this:</p>
<p><img loading="lazy" src="gmail-selection.jpg" alt="Gmail Selection"  />
</p>
<p>Perfect.  So I went back to my sponsor and showed them a mock-up with this style of selection.  The reaction was: &ldquo;Oh I like that&rdquo;. Excellent news, for me its easier code to write (I&rsquo;m happy with a for loop setting a grid cell to true in the view) and if they want to add other selections its easy enough (though there is not much else they could select by&hellip;).</p>
<p>The moral of the story?  If in doubt, copy Google.</p>
]]></content:encoded></item><item><title>Functionality and Seperation of Concerns</title><link>https://andydote.co.uk/2009/12/15/functionality-and-seperation-of-concerns/</link><pubDate>Tue, 15 Dec 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/12/15/functionality-and-seperation-of-concerns/</guid><description>When I am writing a winform in an MVP style, I often wonder how far to go with the separation. Say I have the following situation:
A small form which should display a list of messages, and allow the user to select which ones they want processed. It processes each message in turn. If a message has more than one attachment, a dialog is shown to ask the user to select which attachment should be used for that message.</description><content:encoded><![CDATA[<p>When I am writing a winform in an MVP style, I often wonder how far to go with the separation.  Say I have the following situation:</p>
<p>A small form which should display a list of messages, and allow the user to select which ones they want processed.  It processes each message in turn.  If a message has more than one attachment, a dialog is shown to ask the user to select which attachment should be used for that message.</p>
<p>Now while this is fairly simple, my interface for the message dialog looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Interface</span> IMessageSelector
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Event</span> Submit()
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Event</span> Cancel()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">WriteOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">Messages</span>() <span style="color:#f92672">As</span> IList(<span style="color:#66d9ef">Of</span> MessageData)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">ReadOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">Selected</span>() <span style="color:#f92672">As</span> IList(<span style="color:#66d9ef">Of</span> <span style="color:#66d9ef">String</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">ReadOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">AttachmentView</span>() <span style="color:#f92672">As</span> IAttachmentScreen
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">ShowScreen</span>()
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">CloseScreen</span>()
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">DisplayWarning</span>(<span style="color:#66d9ef">ByVal</span> text <span style="color:#f92672">As</span> <span style="color:#66d9ef">String</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Interface</span>
</span></span></code></pre></div><p>In the form I have (roughly) the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">frmMessages</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Implements</span> IMessageSelector
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">&#39;...&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">WriteOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">Messages</span>() <span style="color:#f92672">As</span> IList(<span style="color:#66d9ef">Of</span> MessageData) <span style="color:#66d9ef">Implements</span> IMessageSelector.Messages
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Set</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> IList(<span style="color:#66d9ef">Of</span> MessageData))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">For</span> <span style="color:#66d9ef">Each</span> d <span style="color:#f92672">As</span> MessageData <span style="color:#f92672">In</span> value
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">Dim</span> r <span style="color:#f92672">As</span> Grid.Row <span style="color:#f92672">=</span> grid.Rows.Add
</span></span><span style="display:flex;"><span>				r(<span style="color:#e6db74">&#34;id&#34;</span>) <span style="color:#f92672">=</span> d.ID
</span></span><span style="display:flex;"><span>				r(<span style="color:#e6db74">&#34;subject&#34;</span>) <span style="color:#f92672">=</span> d.Subject
</span></span><span style="display:flex;"><span>				r(<span style="color:#e6db74">&#34;from&#34;</span>) <span style="color:#f92672">=</span> d.Sender
</span></span><span style="display:flex;"><span>				r(<span style="color:#e6db74">&#34;received&#34;</span>) <span style="color:#f92672">=</span> d.SendDate
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">Next</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			flx.AutoSizeCols()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Set</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">ReadOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">Selected</span>() <span style="color:#f92672">As</span> IList(<span style="color:#66d9ef">Of</span> <span style="color:#66d9ef">String</span>) <span style="color:#66d9ef">Implements</span> IMessageSelector.Selected
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">Dim</span> result <span style="color:#f92672">As</span> <span style="color:#66d9ef">New</span> List(<span style="color:#66d9ef">Of</span> <span style="color:#66d9ef">String</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">For</span> i <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span> <span style="color:#f92672">=</span> 1 <span style="color:#66d9ef">To</span> grid.Rows.Count <span style="color:#f92672">-</span> 1
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">If</span> Convert.ToBoolean(grid(i, <span style="color:#e6db74">&#34;selected&#34;</span>)) <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>					result.Add(grid(i, <span style="color:#e6db74">&#34;id&#34;</span>).ToString)
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">Next</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">Return</span> result
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span></code></pre></div><p>Now I think that this is ok.  There is not logic as such in the population property, and the Selected property just determines which rows have had their checkboxes ticked.</p>
<p>However it has been requested that I add a &lsquo;Select All/None&rsquo; checkbox to the form.  Where do I add the code for this?  As they want a checkbox to tick or detick its not as trivial as it could be.  If it were separate buttons, I could just use a for loop in each setting the values to True or False.  A checkbox however has some uncertainties:</p>
<ul>
<li>Checking the master checkbox should make all rows checked. Fine.</li>
<li>DeChecking the master checkbox should make all rows unchecked. Also fine.</li>
<li>Checking one row when none are checked should do what to the master checkbox?</li>
<li>DeChecking one row when all are checked should do what to the master checkbox?</li>
<li>25%/50%/75% of rows are checked, what does the master checkbox look like?</li>
<li>Some rows are checked.  What happens when the checkbox is clicked?</li>
</ul>
<p>So many questions for such a simple looking feature.  With so many possibilities for it maybe it should go into the presenter/interface?  At least it&rsquo;s testable then.  Maybe a separate controller for it as it&rsquo;s not really anything to do with the <em>purpose</em> of the form?</p>
<p>If anyone knows of answers to this I would be very interested to hear them.</p>
]]></content:encoded></item><item><title>Software Fuzzying maybe?</title><link>https://andydote.co.uk/2009/10/07/software-fuzzying-maybe/</link><pubDate>Wed, 07 Oct 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/10/07/software-fuzzying-maybe/</guid><description>This morning I read this post by Alfred Thompson about whether we are Software Engineers or something else. I can&amp;rsquo;t help but agree with him, as I don&amp;rsquo;t feel we are engineers (yet), our discipline is a little fuzzy to be classified as engineering I think.
However I think we are not alone in this boat. Not all engineering disciplines are quite so well cut. My father is an Engineering Pattern Maker.</description><content:encoded><![CDATA[<p>This morning I read <a href="http://blogs.msdn.com/alfredth/archive/2009/10/06/what-sort-of-thing-is-programming-really.aspx">this post</a> by <a href="http://blogs.msdn.com/user/Profile.aspx?UserID=8718">Alfred Thompson</a> about whether we are Software Engineers or something else.  I can&rsquo;t help but agree with him, as I don&rsquo;t feel we are engineers (yet), our discipline is a little fuzzy to be classified as engineering I think.</p>
<p>However I think we are not alone in this boat.  Not all engineering disciplines are quite so well cut.  My father is an Engineering Pattern Maker.  Yet a large proportion of his work involves hand tools to create his forms.  Maybe the designing of the Pattern is engineering, but the creation of it is defiantly crafting as so much practical skill is involved in the creation.  If instead of him making it, the design was given to a nice brainless CNC to make, would that CNC be as skilled and thus a craftsman(machine?), or would it magically become engineering due to the lack of a CNC&rsquo;s skills?</p>
<p>The same goes for science in my mind.  This might be due to Robert M. Pirsig&rsquo;s excellent book <a href="http://www.amazon.co.uk/Zen-Art-Motorcycle-Maintenance-Anniversary/dp/0099322617/">Zen and the Art of Motorcycle Maintenance</a>, where he goes to explain that science is about having a theory(s) then proving or disproving it, and continuing until all theories have been eliminated.  At this point you have &lsquo;fact&rsquo;, or have missed some theories.  His main point on this was &lsquo;where do theories come from? If you are sat there with no theories, and then you suddenly think of one, where did it come from?  It certainly does not seem like a scientific method of theory discovery&rsquo; (I don&rsquo;t have the book to hand, so can&rsquo;t find the exact quote.  I will update later when I get home).  So science is a bit &lsquo;fuzzy&rsquo; too?</p>
<p>This also applies to art.  If a sculpture is to be created, it needs to be structurally sound, else it just won&rsquo;t work.  So some engineering is involved there too.  And possibly science of materials too.</p>
<p>I think my point is that we are just trying to label everything into distinct categories, which just isn&rsquo;t going to work, unless your categories are so wide that they might as well not exist.</p>
]]></content:encoded></item><item><title>Region Hate</title><link>https://andydote.co.uk/2009/10/06/region-hate/</link><pubDate>Tue, 06 Oct 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/10/06/region-hate/</guid><description>There seems to be a lot of negativity towards the #Region in .net at the moment, with many people hating them and calling all usages of them &amp;lsquo;retarded&amp;rsquo;.
I can see their point, especially when you see the odd class with regions like this:
Class Foo { #Private Members #Protected Members #Friend Members #Public Members #Private Constructors #Protected Constructors #Friend Constructors #Public Constructors #Private Methods #Protected Methods #Friend Methods #Public Methods } Clearly the person who wrote this was ill at the time (I hope&amp;hellip;), and besides, where would Protected Friends go?</description><content:encoded><![CDATA[<p>There seems to be a <a href="http://stackoverflow.com/questions/755465/do-you-say-no-to-c-regions">lot of</a> <a href="http://stackoverflow.com/questions/1027504/using-regions-in-c-is-considered-bad-practice">negativity</a> <a href="http://stackoverflow.com/questions/1524248/use-of-region-in-c-closed">towards</a> the <code>#Region</code> in .net at the moment, with many people hating them and calling all usages of them <a href="http://extractmethod.wordpress.com/2008/02/29/just-say-no-to-c-regions/">&lsquo;retarded&rsquo;</a>.</p>
<p>I can see their point, especially when you see the odd class with regions like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>Class Foo
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>Private Members
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>Protected Members
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>Friend Members
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>Public Members
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>Private Constructors
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>Protected Constructors
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>Friend Constructors
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>Public Constructors
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>Private Methods
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>Protected Methods
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>Friend Methods
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>Public Methods
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Clearly the person who wrote this was ill at the time (I hope&hellip;), and besides, where would <code>Protected Friends</code> go? Hmm?</p>
<p>I however find regions useful, especially when writing objects (see what I did there?).  Now while an object might have might be <a href="http://en.wikipedia.org/wiki/DRY">DRY</a> and only have a <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle">Single Responsibility</a>, it might also have many properties.  What I tend to do with regions is hide my getters and setters:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>Class Bar
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	Member1
</span></span><span style="display:flex;"><span>	...
</span></span><span style="display:flex;"><span>	Member2
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>Region Properties
</span></span><span style="display:flex;"><span>		<span style="color:#75715e">//....</span>
</span></span><span style="display:flex;"><span>	<span style="color:#960050;background-color:#1e0010">#</span>End Region
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	Method1(){<span style="color:#75715e">/* */</span>}
</span></span><span style="display:flex;"><span>	...
</span></span><span style="display:flex;"><span>	Method1(){<span style="color:#75715e">/* */</span>}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This way I am hiding standard boiler plate code, and everything that actually matters is visible.  If you don&rsquo;t like hiding properties that have a lot of code in them, then your problem may be the fact that you have lots of code in the properties.  Something like <a href="http://www.postsharp.org/">PostSharp</a> could allow you to inject all your properties with the common code such as <code>PropertyChanging(sender, e)</code>, <code>PropertyChanged(sender, e)</code>.</p>
<p>If you need lots of specific code in a property, then it is surely under unit test?  If it isn&rsquo;t, why not? And if it is, does it matter that you can&rsquo;t see the property without clicking the little + sign?</p>
<p>One other slight point: with my method of <code>#region</code> usage, if you don&rsquo;t like regions, you have one click to expand it (or if you don&rsquo;t like clicking, <code>Ctrl+M, Ctrl+M</code> in VS will expand/collapse whatever is at the cursor position), so it really is not that difficult to cope with.</p>
<p>Like all technologies, use it when it makes sense.  No Regions can be just as bad as many Regions.</p>
]]></content:encoded></item><item><title>Fluency at a cost?</title><link>https://andydote.co.uk/2009/07/29/fluency-at-a-cost/</link><pubDate>Wed, 29 Jul 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/07/29/fluency-at-a-cost/</guid><description>I like fluent interfaces. I find them easy to read, and nice to program with. However the more I write them the more I notice there is a cost associated with them. It&amp;rsquo;s not much of a cost, but it is there none the less. To demonstrate say we have a class called Animator. It has the following properties and methods on it:
+ Control + Distance + DistanceType + AnimationType + Direction + Time + Algorithm - Animate() Now while you could just set all the properties and then call Animate(), a Fluent Interface makes thing nicer:</description><content:encoded><![CDATA[<p>I like fluent interfaces.  I find them easy to read, and nice to program with.  However the more I write them the more I notice there is a cost associated with them.  It&rsquo;s not much of a cost, but it is there none the less.  To demonstrate say we have a class called <code>Animator</code>.  It has the following properties and methods on it:</p>
<pre><code>+ Control
+ Distance
+ DistanceType
+ AnimationType
+ Direction
+ Time
+ Algorithm
- Animate()
</code></pre>
<p>Now while you could just set all the properties and then call <code>Animate()</code>, a Fluent Interface makes thing nicer:</p>
<pre><code>Animate
	.Control(Button1)
	.Slide
	.Right
	.By(60)
	.Using(New ExponentialAlgorithm)
	.Start()
</code></pre>
<p>To make the interface more constrained, there are about 4 classes being used:</p>
<pre><code>Static Class Animate
  - AnimationExpression Control(Control con)

Class AnimationExpression
  - DirectionExpression Slide()
  - DirectionExpression Grow()
  - DirectionExpression Shrink()

Class DirectionExpression
  - DistanceExpression Up()
  - DistanceExpression Down()
  - DistanceExpression Left()
  - DistanceExpression Right()

Class DistanceExpression
  - DistanceExpression Taking(int time)
  - StartExpression To(int position)
  - StartExpression By(int distance)

Class StartExpression
  - StartExpression Using(IAlgorithm algorithm)
  - void Start()
</code></pre>
<p>The first class (Animation Expression) creates an instance of the <code>Animator</code> class, and then that is passed into the constructor of the other classes, after having a property set e.g.:</p>
<pre><code>DistanceExpression Up {
    _animator.DirectionType = Animator.DirectionTypes.Up
    return new DistanceExpression(_animator)
}
</code></pre>
<p>So when you use the Fluent Interface, you end up with around 6 extra instances created rather than just 1 (the animator).  This might not be much of an overhead as each class is fairly small, but if you are doing a lot of animations, it is going to add up (depending on how often the GC sees fit to destroy them).</p>
<p>Compare this fluent interface to the one created for <a href="http://blog.getpaint.net/2008/12/06/a-fluent-approach-to-c-parameter-validation/">parameter validation by Rick Brewster</a> that uses Extension Methods so that he creates no extra instances unless there is an error detected.</p>
<p>I am not entirely sure how much of an impact this would have on a program, but its definitely something worth remembering when writing fluent interfaces for your classes.</p>
]]></content:encoded></item><item><title>Key Bindings</title><link>https://andydote.co.uk/2009/07/17/key-bindings/</link><pubDate>Fri, 17 Jul 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/07/17/key-bindings/</guid><description>When I was at college studying Electronics and Computer Engineering, we used a piece of software called Proteus. This software took a long time to get used to due to its interesting key bindings and mouse usage.
To select a track in Ares (PCB Layout package) you Right Click on it. Hmm not too standard, but okay, I can live with that. Now what happens if you were to right click on that track again?</description><content:encoded><![CDATA[<p>When I was at college studying Electronics and Computer Engineering, we used a piece of software called <a href="http://www.labcenter.co.uk/products/pcb_overview.cfm">Proteus</a>.  This software took a long time to get used to due to its interesting key bindings and mouse usage.</p>
<p>To select a track in Ares (PCB Layout package) you Right Click on it. Hmm not too standard, but okay, I can live with that.  Now what happens if you were to right click on that track again? That&rsquo;s right it deletes it. Here is roughly my thought train while using it (just having deleted a track by accident):</p>
<p>Uh oh, I didn&rsquo;t mean to do that. Ctrl+Z&hellip;nothing, Ctrl+Z&hellip;Ctrl+Z Ctrl+Z Ctrl+Z. Still nothing&hellip;Oh yeah, undo is U in this program&hellip;</p>
<p>It also broke convention on Saving (S), Loading (L), and Printing (P) amongst others.  Admittedly these are kind of logical, but then again I could never remember whether R you Reload or Redo (I still can&rsquo;t remember).</p>
<p>Whenever I needed to make a PCB at university, we used software called <a href="http://www.cadence.com/orcad/">OrCad</a>.  This software is immensely powerful, and can do more things in simulation that I can possibly think of.  However it uses standard key bindings.  And even after several years of not using Proteus, you know what? I still tried to double right click to delete things, S to save et all.</p>
<p>When I needed to make a PCB and the lab was unavailable, I download the latest demo of Proteus, installed it on my laptop and fired it up. Straight away I notice it&rsquo;s slightly different.  Right click is still select, however a second right click now brings a context menu up.  And a third right click deletes. Hmm. Ok I can cope with triple right clicking to delete.  But the real change was the keyboard bindings, which had changed to standard windows style. Ctrl+S saved. Ctrl+O opened.  It was amazing. It did however take me ages to de train my old habits. Sometimes I still hit U to undo.</p>
<p>The real revelation was that a company decided to change something that was obviously a specific decision, and make their product conform more to what is expected.  This software was a bit of a pain to use, but simple once you got past the keyboard bindings.  Now it is standard the difficulty users may have experienced has gone, making it a much better product overall.</p>
<p>Well done Labcenter! Now if only other vendors could be so thoughtful.</p>
]]></content:encoded></item><item><title>CI: Thoughts on CC.Net and Hudson</title><link>https://andydote.co.uk/2009/07/14/ci-thoughts-on-ccnet-and-hudson/</link><pubDate>Tue, 14 Jul 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/07/14/ci-thoughts-on-ccnet-and-hudson/</guid><description>I have been a fan of CI (Continuous Integration) for a long time now, and ever since I started with CI I have been using CruiseControl.Net. CCNet is incredibly powerful; you can make to do practically anything, and writing plugins for it is a breeze.
However, I do find that the config files get rather messy. I have tried many things and the current best solution seems to be to have one &amp;lsquo;master&amp;rsquo; config file with a set of includes to other files.</description><content:encoded><![CDATA[<p>I have been a fan of CI (Continuous Integration) for a long time now, and ever since I started with CI I have been using <a href="http://confluence.public.thoughtworks.org/display/CCNET">CruiseControl.Net</a>. CCNet is incredibly powerful; you can make to do practically anything, and writing plugins for it is a breeze.</p>
<p>However, I do find that the config files get rather messy.  I have tried many things and the current best solution seems to be to have one &lsquo;master&rsquo; config file with a set of includes to other files.  While this splits it all out nicely I find my config files are all very similar especially for projects which I build in Debug mode and in Release mode.  These configs are identical bar Build Location, and the <code>/p:Configuration=Debug</code> flag passed to MSBuild.  I have been reading about <a href="http://confluence.public.thoughtworks.org/display/CCNET/Dynamic+Parameters">Dynamic Parameters</a> and I think I can solve the problems with that, however time is a little short at work, so that is defiantly on the back burner.</p>
<p>I have also been reading a lot of good things about <a href="https://hudson.dev.java.net/">Hudson</a> which while being a Java aimed CI Server, can be used with MSBuild through Nant, or plugins to let you use MSBuild directly (a nice guide is at [redsolo&rsquo;s blog]).  While I also have not had the time to have a proper play with it, I must say it does look very good.</p>
<p>It may still have messy configs (I don&rsquo;t know yet, haven&rsquo;t really looked), but as everything is done through a nice web interface rather than a CLI, who cares?  I was very impressed with how quick it was to get running too: <code>java -DHUDSON_HOME=data -jar hudson.war</code>. It uncompressed itself, and got going straight away. No messing with installers. Very nice.</p>
<p>The only thing I dislike so far is the background picture in the web interface.  So I deleted it.  Other than that (very) minor niggle, I think I like Hudson a lot, and look forward to playing around with it in the future.</p>
]]></content:encoded></item><item><title>Overuse of the Var keyword</title><link>https://andydote.co.uk/2009/06/29/overuse-of-the-var-keyword/</link><pubDate>Mon, 29 Jun 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/06/29/overuse-of-the-var-keyword/</guid><description>When I first got hold of VS2008, and had a play with the new version of C# I loved the Var keyword. To me the most amazing thing was no more declarations like this:
System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex(); Instead I could write the following:
var rx = new System.Text.RegularExpressions.Regex(); Making it akin to VB developers being able to write:
Dim rx As New System.Text.RegularExpressions.Regex() (I have had however to cope with a coding standard that explicitly forbid this declaration in VB&amp;hellip;Backwards or what?</description><content:encoded><![CDATA[<p>When I first got hold of VS2008, and had a play with the new version of C# I loved the Var keyword.  To me the most amazing thing was no more declarations like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>    System.Text.RegularExpressions.Regex rx = <span style="color:#66d9ef">new</span> System.Text.RegularExpressions.Regex();
</span></span></code></pre></div><p>Instead I could write the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> rx = <span style="color:#66d9ef">new</span> System.Text.RegularExpressions.Regex();
</span></span></code></pre></div><p>Making it akin to VB developers being able to write:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span>    <span style="color:#66d9ef">Dim</span> rx <span style="color:#f92672">As</span> <span style="color:#66d9ef">New</span> System.Text.RegularExpressions.Regex()
</span></span></code></pre></div><p>(I have had however to cope with a coding standard that explicitly forbid this declaration in VB&hellip;Backwards or what?)</p>
<p>My only gripe with the var keyword is that it is being overused. Horribly.  Every day I come across people (mainly on StackOverflow, but development blogs, people I know do this too) writing code something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> fileName = <span style="color:#e6db74">&#34;C:\\text.xml&#34;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> itemCount = <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> xml = <span style="color:#66d9ef">new</span> System.Xml.XmlDocument();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">var</span> i = <span style="color:#ae81ff">0</span>; i &lt; <span style="color:#ae81ff">10</span>; ++i) {<span style="color:#75715e">/*...*/</span>}
</span></span></code></pre></div><p>In that code snippet there is <em>one</em> place where var is used well.  Don&rsquo;t declare strings as var, it&rsquo;s a string. Don&rsquo;t declare int as var, not only is it not necessary, it hasn&rsquo;t saved you any typing, they are both 3 characters long.</p>
<p>The other point (one I seem to keep coming back to) is code readability:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> result = something.FunctionThatReturnsSomething();
</span></span></code></pre></div><p>Now, what is the type of result?  Admittedly, this could be improved by <a href="/coming-from-something-as-opposed-to-going-to-something">naming your functions properly</a> and naming variables a little less generically, like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> polar = something.PolarCoordinates();
</span></span></code></pre></div>]]></content:encoded></item><item><title>Coming From Something as opposed to Going To Something</title><link>https://andydote.co.uk/2009/06/19/coming-from-something-as-opposed-to-going-to-something/</link><pubDate>Fri, 19 Jun 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/06/19/coming-from-something-as-opposed-to-going-to-something/</guid><description>Over the last week I have noticed myself preferring methods being called IntegerFromString rather than StringToInteger. Is sometimes takes me a little longer to read (only a few milliseconds, mind) but I think I am getting more used to it, and I do think it enhances readability.
The main point for readability comes from the fact that I work a lot (in my spare time when coding) on graphics processing in GDI.</description><content:encoded><![CDATA[<p>Over the last week I have noticed myself preferring methods being called IntegerFromString rather than StringToInteger.  Is sometimes takes me a little longer to read (only a few milliseconds, mind) but I think I am getting more used to it, and I do think it enhances readability.</p>
<p>The main point for readability comes from the fact that I work a lot (in my spare time when coding) on graphics processing in GDI.  When working with several different sets of coordinates it can get confusing, especially when converting between them, or having to use two different coordinate styles at once.</p>
<p>For instance in my current project, I deal a lot with rotation, so I am using <a href="http://en.wikipedia.org/wiki/Polar_coordinate_system">Polar Coordinate System</a> which specifies an angle and a length.  However as a windows form uses the Raster Coordinate System/Offset <a href="http://en.wikipedia.org/wiki/Cartesian_coordinate_system">Cartesian</a> (e.g. 0, 0 is in the Top Left), I end up converting from Polar to Cartesian to Raster.</p>
<p>When I was writing the functions to do this for me, I ended up naming them things like <code>Point F RasterFromCartesian(PointF pt);</code> which helped a lot as when used in code I end up with something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>PointF locationRaster = RasterFromCartesian(CartesianFromPolar(angle, length));
</span></span></code></pre></div><p>Which keeps the keywords close together and may not seem like a huge advantage with the declaration line, but when later on in the code you see this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span>locationRaster = CartesianDistance(currentCartesian, destinationCartesian);
</span></span></code></pre></div><p>You can see instantly that something is wrong, as the code is assigning a Cartesian straight to a Raster variable.  By having the word Raster on the end of my variable name and the resultant type on the beginning of my function, it is very easy to see what is happening at a glance.</p>
<p>I admit this is probably not the best explanation; Joel Spolsky has a very good article on the subject <a href="http://www.joelonsoftware.com/articles/Wrong.html">Here</a>.</p>
]]></content:encoded></item><item><title>Fluent Validation</title><link>https://andydote.co.uk/2009/06/12/fluent-validation/</link><pubDate>Fri, 12 Jun 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/06/12/fluent-validation/</guid><description>A few days a go i was going through my bookmarks, and came accross this post on the GetPaint.Net blog about using a fluent interface for parameter validation.
After reading the article, I tried the code out at home, and was very impressed. Not only does it read well, but also does not create any objects untill a piece of validation fails. Very nice.
However i wanted to use this at work, and this presented me with a problem.</description><content:encoded><![CDATA[<p>A few days a go i was going through my bookmarks, and came accross <a href="http://blog.getpaint.net/2008/12/06/a-fluent-approach-to-c-parameter-validation/">this post</a> on the GetPaint.Net blog about using a fluent interface for parameter validation.</p>
<p>After reading the article, I tried the code out at home, and was very impressed.  Not only does it read well, but also does not create any objects untill a piece of validation fails.  Very nice.</p>
<p>However i wanted to use this at work, and this presented me with a problem.  Work only has VS2005, which means no extension methods, which are the crux of how this validation method works.</p>
<p>I spent a while trying to see if it was possible to keep the fluent interface and not instantiate any objects until something fails.  In the end i settled for this method which only creates one object.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">Validate</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Shared</span> <span style="color:#66d9ef">Function</span> <span style="color:#a6e22e">Begin</span>() <span style="color:#f92672">As</span> ValidationExpression
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">New</span> ValidationExpression
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Function</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">ValidationExpression</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Private</span> _validation <span style="color:#f92672">As</span> Validation <span style="color:#f92672">=</span> <span style="color:#66d9ef">Nothing</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Friend</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">New</span>()
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Function</span> <span style="color:#a6e22e">IsNotNull</span>(<span style="color:#66d9ef">Of</span> T)(<span style="color:#66d9ef">ByVal</span> obj <span style="color:#f92672">As</span> T, <span style="color:#66d9ef">ByVal</span> name <span style="color:#f92672">As</span> <span style="color:#66d9ef">String</span>) <span style="color:#f92672">As</span> ValidationExpression
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">If</span> obj <span style="color:#f92672">Is</span> <span style="color:#66d9ef">Nothing</span> <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>                Init()
</span></span><span style="display:flex;"><span>                _validation.AddException(<span style="color:#66d9ef">New</span> ArgumentNullException(name))
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">Me</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Function</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Function</span> <span style="color:#a6e22e">IsPositive</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span>, <span style="color:#66d9ef">ByVal</span> name <span style="color:#f92672">As</span> <span style="color:#66d9ef">String</span>) <span style="color:#f92672">As</span> ValidationExpression
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">If</span> value <span style="color:#f92672">&lt;</span> 0 <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>                Init()
</span></span><span style="display:flex;"><span>                _validation.AddException(<span style="color:#66d9ef">New</span> ArgumentOutOfRangeException(name, <span style="color:#e6db74">&#34;must be positive, but was &#34;</span> <span style="color:#f92672">&amp;</span> value.ToString))
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">Me</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Function</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Function</span> <span style="color:#a6e22e">Check</span>() <span style="color:#f92672">As</span> ValidationExpression
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">If</span> _validation <span style="color:#f92672">Is</span> <span style="color:#66d9ef">Nothing</span> <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">Me</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">If</span> _validation.Exceptions.count <span style="color:#f92672">=</span> 1 <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">Throw</span> <span style="color:#66d9ef">New</span> ValidationException(_validation.Exceptions(0))
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">Else</span>
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">Throw</span> <span style="color:#66d9ef">New</span> ValidationException(<span style="color:#66d9ef">New</span> MultiException(_validation.Exceptions))
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Function</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">Init</span>()
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">If</span> _validation <span style="color:#f92672">Is</span> <span style="color:#66d9ef">Nothing</span> <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>                _validation <span style="color:#f92672">=</span> <span style="color:#66d9ef">New</span> Validation
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span></code></pre></div><p>The rest of the code used is identical to Rick Brewster&rsquo;s Article, so <a href="http://blog.getpaint.net/2008/12/06/a-fluent-approach-to-c-parameter-validation/">head over there</a> to see it in all its (well written) glory.</p>
]]></content:encoded></item><item><title>The Reading List</title><link>https://andydote.co.uk/2009/06/05/the-reading-list/</link><pubDate>Fri, 05 Jun 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/06/05/the-reading-list/</guid><description>I have been meaning to write my own version of Jeff Atwood&amp;rsquo;s Reading List for a while now, and have finally managed to find some time to write about the books I have read.
Code Complete 2 I found this book quite tough reading. It wasn&amp;rsquo;t that it had nothing of use in it - far from it, it just was fairly heavy going. There are many things that can be learnt from this to help with the whole process of development, from how to name variables and functions to what the useful methods of development planning are.</description><content:encoded><![CDATA[<p>I have been meaning to write my own version of Jeff Atwood&rsquo;s <a href="http://www.codinghorror.com/blog/archives/000020.html">Reading List</a> for a while now, and have finally managed to find some time to write about the books I have read.</p>
<p><a href="http://www.amazon.co.uk/Code-Complete-Practical-Handbook-Construction/dp/0735619670/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1244194043&amp;sr=8-1">Code Complete 2</a>
I found this book quite tough reading. It wasn&rsquo;t that it had nothing of use in it - far from it, it just was fairly heavy going.  There are many things that can be learnt from this to help with the whole process of development, from how to name variables and functions to what the useful methods of development planning are.  Highly recommended.</p>
<p><a href="http://www.amazon.co.uk/Dont-Make-Me-Think-Usability/dp/0321344758/ref=pd_sim_b_20">Don&rsquo;t Make Me Think</a>
This book by comparison was very easy to read.  It is fairly short (around four hours is plenty to read it) and is crammed with useful succinct information on design.  It is focused at web development, but 90% of the information applies to forms development too.  Highly Recommended.</p>
<p><a href="http://www.amazon.co.uk/Head-First-Design-Patterns-Freeman/dp/0596007124/ref=pd_sim_b_3">Head First Design Patterns</a>
I was about halfway though this book when I realised it was in Java and not C#&hellip;I thought the writers just had a healthy obsession with a particular type of Coffee!  In all seriousness though, this book is well written and provides the basics of each of the patterns covered and then builds on them.  It also compares similar patterns (like Monostate vs. Singleton).  Highly Recommended.</p>
<p><a href="http://www.amazon.co.uk/Refactoring-Improving-Design-Existing-Technology/dp/0201485672/ref=pd_sim_b_6">Refactoring: Improving the Design of Existing Code</a>
This is a useful, yet somewhat odd book.  The first few pages recommend how to read it (usually I just read a book start to finish&hellip;)  but with this one its recommended to read the first few chapters, read the titles of the next chapters and read the last chapter.  This is because the middle part is all of the different refactoring procedures.  Some of them seem so obvious (Sub method a block of code etc) but there are also some very useful techniques mentioned on how to look for areas to refactor, and what order things should be done in.  Recommended.</p>
<p><a href="http://www.amazon.co.uk/Mythical-Month-Essays-Software-Engineering/dp/0201835959/ref=pd_sim_b_29">The Mythical Man Month</a>
I learnt a lot from this book, mainly about the development lifecycle and team interaction.  The points brought up about Men and Months not being interchangeable has been particularly invaluable, as have the reasons behind why they are not interchangeable. Recommended</p>
<p><a href="http://www.amazon.co.uk/Windows-Forms-Programming-Chris-Sells/dp/0321267966/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1244194283&amp;sr=1-1">Windows Forms 2.0 Programming</a>
This is currently being read&hellip;</p>
]]></content:encoded></item><item><title>Converting Code</title><link>https://andydote.co.uk/2009/06/01/converting-code/</link><pubDate>Mon, 01 Jun 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/06/01/converting-code/</guid><description>Quite often (well ok, not that often) I am asked why I convert most C# code I find into VB.Net. The main reason is I find that it helps me to understand the code.
To put it into perspective, my Test Projects directory contains around 50 projects with about a 50/50 split of C# projects and VB.Net projects.
When I come across a sample online (often in a blog) it is either small enough to be understood straight away, or something much larger that needs a lot of thinking and looking at (look at Jeremy Miller&amp;rsquo;s Build Your Own CAB Series) to fully understand.</description><content:encoded><![CDATA[<p>Quite often (well ok, not that often) I am asked why I convert most C# code I find into VB.Net.  The main reason is I find that it helps me to understand the code.</p>
<p>To put it into perspective, my Test Projects directory contains around 50 projects with about a 50/50 split of C# projects and VB.Net projects.</p>
<p>When I come across a sample online (often in a blog) it is either small enough to be understood straight away, or something much larger that needs a lot of thinking and looking at (look at <a href="http://codebetter.com/blogs/jeremy.miller/archive/2007/07/25/the-build-your-own-cab-series-table-of-contents.aspx">Jeremy Miller&rsquo;s Build Your Own CAB Series</a>) to fully understand.  I like to fully understand code so that I may use it intelligently and apply it when it suits.</p>
<p>To this end I find rather than copy and pasting the code into VS and compiling it, converting it to the other .Net language (VB.Net -&gt; C#, C# - VB.Net, F#&hellip;well I haven&rsquo;t got round to that yet) helps me to really understand the code, down to all the constructs and the overall picture of what and how the code works.</p>
<p>So it&rsquo;s not just because I prefer VB.Net (although that has something to do with it) it&rsquo;s because understanding what code is doing is far more important than what language it&rsquo;s written in.</p>
]]></content:encoded></item><item><title>Microcontrollers for MenuItems</title><link>https://andydote.co.uk/2009/05/29/microcontrollers-for-menuitems/</link><pubDate>Fri, 29 May 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/05/29/microcontrollers-for-menuitems/</guid><description>I have been working my way through Jeremy Miller&amp;rsquo;s excellent Build Your Own CAB Series (which would be even better if he felt like finishing!) and was very interested by the article on controlling menus with Microcontrollers.
After reading it and writing a version of it myself, I came to the conclusion that some parts of it seem to be wrong. All of the permissioning is done based on the menu items which fire ICommands, and several menu items could use the same ICommand.</description><content:encoded><![CDATA[<p>I have been working my way through Jeremy Miller&rsquo;s excellent <a href="http://codebetter.com/blogs/jeremy.miller/archive/2007/07/25/the-build-your-own-cab-series-table-of-contents.aspx">Build Your Own CAB Series</a> (which would be even better if he felt like finishing!) and was very interested by the article on controlling menus with <a href="http://codebetter.com/blogs/jeremy.miller/pages/build-your-own-cab-14-managing-menu-state-with-microcontroller-s-command-s-a-layer-supertype-some-structuremap-pixie-dust-and-a-dollop-of-fluent-interface.aspx">Microcontrollers</a>.</p>
<p>After reading it and writing a version of it myself, I came to the conclusion that some parts of it seem to be wrong.  All of the permissioning is done based on the menu items which fire <code>ICommands</code>, and several menu items could use the same <code>ICommand</code>.  This means that you need to use the interface something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span>MenuController.MenuItem(mnuFileNew).Executes(Commands.Open).IsAvailableToRoles(<span style="color:#e6db74">&#34;normal&#34;</span>, <span style="color:#e6db74">&#34;editor&#34;</span>, <span style="color:#e6db74">&#34;su&#34;</span>)<span style="color:#960050;background-color:#1e0010">;</span>
</span></span><span style="display:flex;"><span>MenuController.MenuItem(tsbStandardNew).Executes(Commands.Open).IsAvailableToRoles(<span style="color:#e6db74">&#34;normal&#34;</span>, <span style="color:#e6db74">&#34;editor&#34;</span>, <span style="color:#e6db74">&#34;su&#34;</span>)<span style="color:#960050;background-color:#1e0010">;</span>
</span></span></code></pre></div><p>Now to me this seems somewhat wrong, I would rather have something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span>MenuController.Command(<span style="color:#66d9ef">new</span> MenuCommands.New).IsAttachedTo(mnuFileNew, tsbStandardNew).IsAvailableToRoles(<span style="color:#e6db74">&#34;normal&#34;</span>, <span style="color:#e6db74">&#34;editor&#34;</span>, <span style="color:#e6db74">&#34;su&#34;</span>)<span style="color:#960050;background-color:#1e0010">;</span>
</span></span></code></pre></div><p>So I decided to have a go at re-working it to my liking.  To start with we have the mandatory <code>ICommand</code> interface:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Interface</span> ICommand
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">Execute</span>()
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Interface</span>
</span></span></code></pre></div><p>Then a class that manages the actual <code>ICommand</code> and its menuitem(s):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">NotInheritable</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">CommandItem</span>(<span style="color:#66d9ef">Of</span> T)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Implements</span> IDisposable      <span style="color:#75715e">&#39;used to remove handlers that we dont want to leave lying around
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">ReadOnly</span> _command <span style="color:#f92672">As</span> ICommand
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">ReadOnly</span> _id <span style="color:#f92672">As</span> T
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> _roles <span style="color:#f92672">As</span> <span style="color:#66d9ef">New</span> List(<span style="color:#66d9ef">Of</span> <span style="color:#66d9ef">String</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> _menuItems <span style="color:#f92672">As</span> <span style="color:#66d9ef">New</span> List(<span style="color:#66d9ef">Of</span> ToolStripItem)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> _alwaysEnabled <span style="color:#f92672">As</span> <span style="color:#66d9ef">Boolean</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> _disposed <span style="color:#f92672">As</span> <span style="color:#66d9ef">Boolean</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">AlwaysEnabled</span>() <span style="color:#f92672">As</span> <span style="color:#66d9ef">Boolean</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">Return</span> _alwaysEnabled
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Set</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> <span style="color:#66d9ef">Boolean</span>)
</span></span><span style="display:flex;"><span>            _alwaysEnabled <span style="color:#f92672">=</span> value
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Set</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">Roles</span>() <span style="color:#f92672">As</span> List(<span style="color:#66d9ef">Of</span> <span style="color:#66d9ef">String</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">Return</span> _roles
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Set</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> List(<span style="color:#66d9ef">Of</span> <span style="color:#66d9ef">String</span>))
</span></span><span style="display:flex;"><span>            _roles <span style="color:#f92672">=</span> value
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Set</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">ReadOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">MenuItems</span>() <span style="color:#f92672">As</span> ToolStripItem()
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">Return</span> _menuItems.ToArray
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">ReadOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">IsDisposed</span>() <span style="color:#f92672">As</span> <span style="color:#66d9ef">Boolean</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">Return</span> _disposed
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">New</span>(<span style="color:#66d9ef">ByVal</span> cmd <span style="color:#f92672">As</span> ICommand, <span style="color:#66d9ef">ByVal</span> id <span style="color:#f92672">As</span> T)
</span></span><span style="display:flex;"><span>        _command <span style="color:#f92672">=</span> cmd
</span></span><span style="display:flex;"><span>        _id <span style="color:#f92672">=</span> id
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">AddMenuItem</span>(<span style="color:#66d9ef">ByVal</span> menuItem <span style="color:#f92672">As</span> ToolStripItem)
</span></span><span style="display:flex;"><span>        _menuItems.Add(menuItem)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">AddHandler</span> menuItem.Click, <span style="color:#f92672">AddressOf</span> _item_Click
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">RemoveMenuItem</span>(<span style="color:#66d9ef">ByVal</span> menuItem <span style="color:#f92672">As</span> ToolStripItem)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">RemoveHandler</span> menuItem.Click, <span style="color:#f92672">AddressOf</span> _item_Click
</span></span><span style="display:flex;"><span>        _menuItems.Remove(menuItem)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Function</span> <span style="color:#a6e22e">IsEnabled</span>(<span style="color:#66d9ef">ByVal</span> state <span style="color:#f92672">As</span> CommandState(<span style="color:#66d9ef">Of</span> T)) <span style="color:#f92672">As</span> <span style="color:#66d9ef">Boolean</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">If</span> _alwaysEnabled <span style="color:#66d9ef">Then</span> <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">If</span> <span style="color:#66d9ef">Not</span> state.IsEnabled(_id) <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">For</span> i <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span> <span style="color:#f92672">=</span> 0 <span style="color:#66d9ef">To</span> _roles.Count <span style="color:#f92672">-</span> 1
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">If</span> Thread.CurrentPrincipal.IsInRole(_roles(i)) <span style="color:#66d9ef">Then</span> <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Next</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Function</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">SetState</span>(<span style="color:#66d9ef">ByVal</span> state <span style="color:#f92672">As</span> CommandState(<span style="color:#66d9ef">Of</span> T))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Dim</span> enabled <span style="color:#f92672">As</span> <span style="color:#66d9ef">Boolean</span> <span style="color:#f92672">=</span> IsEnabled(state)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">For</span> <span style="color:#66d9ef">Each</span> ts <span style="color:#f92672">As</span> ToolStripItem <span style="color:#f92672">In</span> _menuItems
</span></span><span style="display:flex;"><span>            ts.Enabled <span style="color:#f92672">=</span> enabled
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Next</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">Dispose</span>(<span style="color:#66d9ef">ByVal</span> disposing <span style="color:#f92672">As</span> <span style="color:#66d9ef">Boolean</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">If</span> <span style="color:#66d9ef">Not</span> _disposed <span style="color:#f92672">AndAlso</span> disposing <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">For</span> <span style="color:#66d9ef">Each</span> menuItem <span style="color:#f92672">As</span> ToolStripItem <span style="color:#f92672">In</span> _menuItems
</span></span><span style="display:flex;"><span>                RemoveMenuItem(menuItem)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">Next</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        _disposed <span style="color:#f92672">=</span> <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">Dispose</span>() <span style="color:#66d9ef">Implements</span> IDisposable.Dispose
</span></span><span style="display:flex;"><span>        Dispose(<span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>        GC.SuppressFinalize(<span style="color:#66d9ef">Me</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">_item_Click</span>(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> <span style="color:#66d9ef">Object</span>, <span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> EventArgs)
</span></span><span style="display:flex;"><span>        _command.Execute()
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span></code></pre></div><p>As you can see, the <code>Dispose</code> Method is used to allow for handlers to be removed, otherwise the objects might be hanging around longer than they should be. We also have a list of menu items that this command controls, and a list of roles that the command is available to.</p>
<p>Next we have the class that holds the state of each menu item, which is generic to allow the end user to use whatever they wish to identify each menu item:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">NotInheritable</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">CommandState</span>(<span style="color:#66d9ef">Of</span> T)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> _enabledCommands <span style="color:#f92672">As</span> <span style="color:#66d9ef">New</span> List(<span style="color:#66d9ef">Of</span> T)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Function</span> <span style="color:#a6e22e">Enable</span>(<span style="color:#66d9ef">ByVal</span> id <span style="color:#f92672">As</span> T) <span style="color:#f92672">As</span> CommandState(<span style="color:#66d9ef">Of</span> T)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">If</span> <span style="color:#66d9ef">Not</span> _enabledCommands.Contains(id) <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>            _enabledCommands.Add(id)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">Me</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Function</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Function</span> <span style="color:#a6e22e">Disable</span>(<span style="color:#66d9ef">ByVal</span> id <span style="color:#f92672">As</span> T) <span style="color:#f92672">As</span> CommandState(<span style="color:#66d9ef">Of</span> T)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">If</span> _enabledCommands.Contains(id) <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>            _enabledCommands.Remove(id)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">Me</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Function</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Function</span> <span style="color:#a6e22e">IsEnabled</span>(<span style="color:#66d9ef">ByVal</span> id <span style="color:#f92672">As</span> T) <span style="color:#f92672">As</span> <span style="color:#66d9ef">Boolean</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Return</span> _enabledCommands.Contains(id)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Function</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span></code></pre></div><p>Finally we have the Manager class which stitches the whole lot together with a health dollop of Fluent Interfaces.  We have a unique list of Commands (as I wrote this in VS2005, I just had to make a unique List class, rather than use a dictionary of <code>CommmandItem</code> and <code>Null</code>) and a sub class which provides the Fluent Interface to the manager. (<code>IDisposeable</code> parts have been trimmed out for brevity, it&rsquo;s just contains a loop that disposes all child objects).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">NotInheritable</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">Manager</span>(<span style="color:#66d9ef">Of</span> T)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> _commands <span style="color:#f92672">As</span> <span style="color:#66d9ef">New</span> UniqueList(<span style="color:#66d9ef">Of</span> CommandItem(<span style="color:#66d9ef">Of</span> T))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Function</span> <span style="color:#a6e22e">Command</span>(<span style="color:#66d9ef">ByVal</span> cmd <span style="color:#f92672">As</span> ICommand, <span style="color:#66d9ef">ByVal</span> id <span style="color:#f92672">As</span> T) <span style="color:#f92672">As</span> CommandExpression
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">New</span> CommandExpression(<span style="color:#66d9ef">Me</span>, cmd, id)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Function</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">SetState</span>(<span style="color:#66d9ef">ByVal</span> state <span style="color:#f92672">As</span> CommandState(<span style="color:#66d9ef">Of</span> T))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">For</span> <span style="color:#66d9ef">Each</span> ci <span style="color:#f92672">As</span> CommandItem(<span style="color:#66d9ef">Of</span> T) <span style="color:#f92672">In</span> _commands
</span></span><span style="display:flex;"><span>            ci.SetState(state)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Next</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">NotInheritable</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">CommandExpression</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">ReadOnly</span> _manager <span style="color:#f92672">As</span> Manager(<span style="color:#66d9ef">Of</span> T)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">ReadOnly</span> _commandItem <span style="color:#f92672">As</span> CommandItem(<span style="color:#66d9ef">Of</span> T)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Friend</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">New</span>(<span style="color:#66d9ef">ByVal</span> mgr <span style="color:#f92672">As</span> Manager(<span style="color:#66d9ef">Of</span> T), <span style="color:#66d9ef">ByVal</span> cmd <span style="color:#f92672">As</span> ICommand, <span style="color:#66d9ef">ByVal</span> id <span style="color:#f92672">As</span> T)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            _manager <span style="color:#f92672">=</span> mgr
</span></span><span style="display:flex;"><span>            _commandItem <span style="color:#f92672">=</span> <span style="color:#66d9ef">New</span> CommandItem(<span style="color:#66d9ef">Of</span> T)(cmd, id)
</span></span><span style="display:flex;"><span>            _manager._commands.Add(_commandItem)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Function</span> <span style="color:#a6e22e">IsAttachedTo</span>(<span style="color:#66d9ef">ByVal</span> menuItem <span style="color:#f92672">As</span> ToolStripItem) <span style="color:#f92672">As</span> CommandExpression
</span></span><span style="display:flex;"><span>            _commandItem.AddMenuItem(menuItem)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">Me</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Function</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Function</span> <span style="color:#a6e22e">IsInRole</span>(<span style="color:#66d9ef">ByVal</span> <span style="color:#66d9ef">ParamArray</span> roles() <span style="color:#f92672">As</span> <span style="color:#66d9ef">String</span>) <span style="color:#f92672">As</span> CommandExpression
</span></span><span style="display:flex;"><span>            _commandItem.Roles.AddRange(roles)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">Me</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Function</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Function</span> <span style="color:#a6e22e">IsAlwaysEnabled</span>() <span style="color:#f92672">As</span> CommandExpression
</span></span><span style="display:flex;"><span>            _commandItem.AlwaysEnabled <span style="color:#f92672">=</span> <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">Me</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Function</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">UniqueList</span>(<span style="color:#66d9ef">Of</span> TKey)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Inherits</span> List(<span style="color:#66d9ef">Of</span> TKey)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Shadows</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">Add</span>(<span style="color:#66d9ef">ByVal</span> item <span style="color:#f92672">As</span> TKey)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">If</span> <span style="color:#66d9ef">Not</span> <span style="color:#66d9ef">MyBase</span>.Contains(item) <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">MyBase</span>.Add(item)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span></code></pre></div><p>In my test application I have a file containing my menuCommands and an Enum used for identification:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Namespace</span> MenuCommands
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Enum</span> <span style="color:#a6e22e">Commands</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">[</span><span style="color:#66d9ef">New</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>        Open
</span></span><span style="display:flex;"><span>        Save
</span></span><span style="display:flex;"><span>        Close
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Enum</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">Open</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Implements</span> ICommand
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">Execute</span>() <span style="color:#66d9ef">Implements</span> ICommand.Execute
</span></span><span style="display:flex;"><span>            MessageBox.Show(<span style="color:#e6db74">&#34;Open&#34;</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Namespace</span>
</span></span></code></pre></div><p>And in the main form I have this code.  The Thread Principle is used for the roles, and the actual roles could (should) be loaded from a database or anywhere other than hard coded constants of course.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Private</span> _menuManager <span style="color:#f92672">As</span> <span style="color:#66d9ef">New</span> Manager(<span style="color:#66d9ef">Of</span> MenuCommands.Commands)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">Private</span> _state <span style="color:#f92672">As</span> <span style="color:#66d9ef">New</span> CommandState(<span style="color:#66d9ef">Of</span> MenuCommands.Commands)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">Form1_Load</span>(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> System.Object, <span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> System.EventArgs) <span style="color:#66d9ef">Handles</span> <span style="color:#66d9ef">MyBase</span>.Load
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Thread.CurrentPrincipal <span style="color:#f92672">=</span> <span style="color:#66d9ef">New</span> GenericPrincipal(Thread.CurrentPrincipal.Identity, <span style="color:#66d9ef">New</span> <span style="color:#66d9ef">String</span>() {<span style="color:#e6db74">&#34;normal&#34;</span>})
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    _menuManager.Command(<span style="color:#66d9ef">New</span> MenuCommands.<span style="color:#f92672">[</span><span style="color:#66d9ef">New</span><span style="color:#f92672">]</span>, MenuCommands.Commands.<span style="color:#f92672">[</span><span style="color:#66d9ef">New</span><span style="color:#f92672">]</span>) _
</span></span><span style="display:flex;"><span>                .IsAttachedTo(mnuFileNew) _
</span></span><span style="display:flex;"><span>                .IsAttachedTo(tsbNew) _
</span></span><span style="display:flex;"><span>                .IsInRole(<span style="color:#e6db74">&#34;normal&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    _menuManager.Command(<span style="color:#66d9ef">New</span> MenuCommands.Open, MenuCommands.Commands.Open) _
</span></span><span style="display:flex;"><span>                .IsAttachedTo(mnuFileOpen) _
</span></span><span style="display:flex;"><span>                .IsAttachedTo(tsbOpen) _
</span></span><span style="display:flex;"><span>                .IsInRole(<span style="color:#e6db74">&#34;normal&#34;</span>, <span style="color:#e6db74">&#34;reviewer&#34;</span>, <span style="color:#e6db74">&#34;viewer&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    _menuManager.Command(<span style="color:#66d9ef">New</span> MenuCommands.Save, MenuCommands.Commands.Save) _
</span></span><span style="display:flex;"><span>                .IsAttachedTo(mnuFileSave) _
</span></span><span style="display:flex;"><span>                .IsAttachedTo(tsbSave) _
</span></span><span style="display:flex;"><span>                .IsInRole(<span style="color:#e6db74">&#34;normal&#34;</span>, <span style="color:#e6db74">&#34;reviewer&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    _menuManager.Command(<span style="color:#66d9ef">New</span> MenuCommands.Close, MenuCommands.Commands.Close) _
</span></span><span style="display:flex;"><span>                .IsAttachedTo(mnuFileExit) _
</span></span><span style="display:flex;"><span>                .IsAlwaysEnabled()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    _state.Enable(MenuCommands.Commands.Open) _
</span></span><span style="display:flex;"><span>          .Enable(MenuCommands.Commands.Save) _
</span></span><span style="display:flex;"><span>          .Enable(MenuCommands.Commands.Close)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    _menuManager.SetState(_state)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span></code></pre></div><p>The state object is used to enable and disable menu items and could be wrapped in another object if it needed to be exposed further than the form.</p>
]]></content:encoded></item><item><title>Generics to the rescue! Again!</title><link>https://andydote.co.uk/2009/05/22/generics-to-the-rescue-again/</link><pubDate>Fri, 22 May 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/05/22/generics-to-the-rescue-again/</guid><description>I was writing a component at work that has many events that all need to be thread safe, and was getting annoyed at the amount of duplicate code I was writing:
Public Event FilterStart(ByVal sender As Object, ByVal e As EventArgs) &amp;#39;... Private Delegate Sub OnFilterCompleteDelegate(ByVal sender As Object, ByVal e As FilterCompleteEventArgs) &amp;#39;... Private Sub OnFilterComplete(ByVal sender As Object, ByVal e As DataAccess.LoadEventArgs) If _parent.InvokeRequired Then _parent.Invoke(new OnFilterCompleteDelegate(AddressOf OnFilterComplete), new Object() {sender, e}) Else RaiseEvent FullResultsStart(sender, e) End If End Sub &amp;#39;.</description><content:encoded><![CDATA[<p>I was writing a component at work that has many events that all need to be thread safe, and was getting annoyed at the amount of duplicate code I was writing:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Event</span> FilterStart(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> <span style="color:#66d9ef">Object</span>, <span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> EventArgs)
</span></span><span style="display:flex;"><span><span style="color:#75715e">&#39;...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Delegate</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">OnFilterCompleteDelegate</span>(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> <span style="color:#66d9ef">Object</span>, <span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> FilterCompleteEventArgs)
</span></span><span style="display:flex;"><span><span style="color:#75715e">&#39;...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">OnFilterComplete</span>(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> <span style="color:#66d9ef">Object</span>, <span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> DataAccess.LoadEventArgs)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">If</span> _parent.InvokeRequired <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>        _parent.Invoke(<span style="color:#66d9ef">new</span> OnFilterCompleteDelegate(<span style="color:#f92672">AddressOf</span> OnFilterComplete), <span style="color:#66d9ef">new</span> <span style="color:#66d9ef">Object</span>() {sender, e})
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Else</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">RaiseEvent</span> FullResultsStart(sender, e)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&#39;... repeat for all
</span></span></span></code></pre></div><p>Hmm. There has to be a better way of doing this. Enter some Generic magic in the form of a Generic Delegate Sub:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Delegate</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">EventAction</span>(<span style="color:#66d9ef">Of</span> TArgs)(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> <span style="color:#66d9ef">Object</span>, <span style="color:#66d9ef">ByVal</span> args <span style="color:#f92672">As</span> TArgs)
</span></span></code></pre></div><p>This then allows me to write my Event Raisers like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Delegate</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">EventAction</span>(<span style="color:#66d9ef">Of</span> TArgs)(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> <span style="color:#66d9ef">Object</span>, <span style="color:#66d9ef">ByVal</span> args <span style="color:#f92672">As</span> TArgs)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">OnFilterStart</span>(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> <span style="color:#66d9ef">Object</span>, <span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> EventArgs)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">If</span> _parent.InvokeRequired <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>        _parent.Invoke(<span style="color:#66d9ef">New</span> EventAction(<span style="color:#66d9ef">Of</span> EventArgs)(<span style="color:#f92672">AddressOf</span> OnFilterStart), <span style="color:#66d9ef">New</span> <span style="color:#66d9ef">Object</span>() {sender, e})
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Else</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">RaiseEvent</span> FilterStart(sender, e)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span></code></pre></div><p>Further optimisation let me do the fiollowing, as the sender is always <code>Me</code> :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">OnFilterStart</span>(<span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> EventArgs)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">If</span> _parent.InvokeRequired <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>        _parent.Invoke(<span style="color:#66d9ef">New</span> Action(<span style="color:#66d9ef">Of</span> EventArgs)(<span style="color:#f92672">AddressOf</span> OnFilterStart), <span style="color:#66d9ef">New</span> <span style="color:#66d9ef">Object</span>() {e})
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Else</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">RaiseEvent</span> FilterStart(<span style="color:#66d9ef">Me</span>, e)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span></code></pre></div><p>Which meant I no longer needed my customer Action Delegate, as there is one for a single parameter in System for this already!</p>
<p>Now if only I could find a way to wrap the thread safe checks and invokes into a single generic function&hellip;</p>
]]></content:encoded></item><item><title>Using Laziness</title><link>https://andydote.co.uk/2009/05/19/using-laziness/</link><pubDate>Tue, 19 May 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/05/19/using-laziness/</guid><description>As I do a lot of forms development, I end up writing something like this a lot:
Try pnlSomething.SuspendLayout() &amp;#39;... Finally pnlSomething.ResumeLayout() End Try Now as I am lazy, I thought I could make a class to do this for me:
Public Class Layout Implements IDisposable Private _control As Control Public Sub New(ByVal control As Control) _control = control _control.SuspendLayout() End Sub Public Sub Dispose() Implements IDisposable.Dispose _control.ResumeLayout() _control = Nothing End Sub End Class It is used like this:</description><content:encoded><![CDATA[<p>As I do a lot of forms development, I end up writing something like this a lot:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Try</span>
</span></span><span style="display:flex;"><span>    pnlSomething.SuspendLayout()
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">&#39;...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">Finally</span>
</span></span><span style="display:flex;"><span>    pnlSomething.ResumeLayout()
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Try</span>
</span></span></code></pre></div><p>Now as I am lazy, I thought I could make a class to do this for me:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">Layout</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Implements</span> IDisposable
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> _control <span style="color:#f92672">As</span> Control
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">New</span>(<span style="color:#66d9ef">ByVal</span> control <span style="color:#f92672">As</span> Control)
</span></span><span style="display:flex;"><span>        _control <span style="color:#f92672">=</span> control
</span></span><span style="display:flex;"><span>        _control.SuspendLayout()
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">Dispose</span>() <span style="color:#66d9ef">Implements</span> IDisposable.Dispose
</span></span><span style="display:flex;"><span>        _control.ResumeLayout()
</span></span><span style="display:flex;"><span>        _control <span style="color:#f92672">=</span> <span style="color:#66d9ef">Nothing</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span></code></pre></div><p>It is used like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Using</span> l <span style="color:#f92672">As</span> <span style="color:#66d9ef">New</span> Layout(FlowLayoutPanel1)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">For</span> I <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span> <span style="color:#f92672">=</span> 0 <span style="color:#66d9ef">To</span> 500
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Dim</span> chk <span style="color:#f92672">As</span> <span style="color:#66d9ef">New</span> CheckBox
</span></span><span style="display:flex;"><span>        chk.Name <span style="color:#f92672">=</span> i.ToString
</span></span><span style="display:flex;"><span>        chk.Text <span style="color:#f92672">=</span> i.ToString
</span></span><span style="display:flex;"><span>        chk.Parent <span style="color:#f92672">=</span> FlowLayoutPanel1
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Next</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Using</span>
</span></span></code></pre></div><p>I suppose I haven&rsquo;t saved any typing, but I think it looks better&hellip;whether I will actually use it is another matter.  I might see if it&rsquo;s possible to extend it to do other things.  On the other hand I might not bother ;\</p>
]]></content:encoded></item><item><title>Finally, I have used a Model View Controller!</title><link>https://andydote.co.uk/2009/05/18/finally-i-have-used-a-model-view-controller/</link><pubDate>Mon, 18 May 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/05/18/finally-i-have-used-a-model-view-controller/</guid><description>Today I actually managed to use a Model View Controller in an application. I have been looking for an opportunity to use one fore a while, and have been reading a lot about them (Jeremy Miller&amp;rsquo;s Build Your Own CAB Series has been a very good guide).
The type of MVC I like most (so far) is the Passive View type, where the View does almost nothing, and has no link to the Model:</description><content:encoded><![CDATA[<p>Today I actually managed to use a Model View Controller in an application.  I have been looking for an opportunity to use one fore a while, and have been reading a lot about them (Jeremy Miller&rsquo;s <a href="http://codebetter.com/blogs/jeremy.miller/archive/2007/07/25/the-build-your-own-cab-series-table-of-contents.aspx">Build Your Own CAB Series</a> has been a very good guide).</p>
<p>The type of MVC I like most (so far) is the <a href="http://martinfowler.com/eaaDev/PassiveScreen.html">Passive View</a> type, where the View does almost nothing, and has no link to the Model:</p>
<p><img loading="lazy" src="passive-view.png" alt="&amp;ldquo;Passive View&amp;rdquo; Model View Presenter"  />
<br />
Image Source: <a href="http://msdn.microsoft.com/en-us/library/cc304760.aspx">Microsoft</a></p>
<p>There are two main ways of wiring your View to the Presenter/Controller: Events and Interfaces.  The advantage of using an Interface is that they are easier to test (using <a href="http://hibernatingrhinos.com/oss/rhino-mocks">Rhino Mocks</a>), but as work does not do unit testing (I&rsquo;m working on it!), that didn&rsquo;t matter too much.  I used events in this case simply because I prefer them.</p>
<p>As we already have a data layer, and I was just designing a form to expose some functionality I didn&rsquo;t really use a Model either (unless a DAL counts, and I&rsquo;m not sure it does).</p>
<p>In the end my Controller and Form looked something like this (much snipped, but you get the idea):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span> <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">SearchController</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> _control <span style="color:#f92672">As</span> ISynchronizeInvoke
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Delegate</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">OnSearchDelegate</span>(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> <span style="color:#66d9ef">Object</span>, <span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> SearchEventArgs)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Event</span> SearchStarted(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> <span style="color:#66d9ef">Object</span>, <span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> SearchEventArgs)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Event</span> SearchProgress(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> <span style="color:#66d9ef">Object</span>, <span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> SearchEventArgs)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Event</span> SearchFinished(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> <span style="color:#66d9ef">Object</span>, <span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> SearchEventArgs)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">New</span>(<span style="color:#66d9ef">ByVal</span> parent <span style="color:#f92672">As</span> ISynchronizeInvoke)
</span></span><span style="display:flex;"><span>        _control <span style="color:#f92672">=</span> parent
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">OnSearchStarted</span>(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> <span style="color:#66d9ef">Object</span>, <span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> SearchEventArgs)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">If</span> _control.InvokeRequired <span style="color:#66d9ef">Then</span>
</span></span><span style="display:flex;"><span>            _control.Invoke(<span style="color:#66d9ef">New</span> OnSearchDelegate(<span style="color:#f92672">AddressOf</span> OnSearchStarted), <span style="color:#66d9ef">New</span> <span style="color:#66d9ef">Object</span>() {sender, e})
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">Else</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">RaiseEvent</span> SearchStarted(sender, e)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">If</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">&#39;snip for other events...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">SetPhrase</span>(<span style="color:#66d9ef">ByVal</span> phrase <span style="color:#f92672">As</span> <span style="color:#66d9ef">String</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">&#39;...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">Search</span>()
</span></span><span style="display:flex;"><span>        OnSearchStarted(<span style="color:#66d9ef">Me</span>, <span style="color:#66d9ef">New</span> SearchEventArgs())
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">&#39;...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">&#39;...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">frmSearch</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> _controller <span style="color:#f92672">as</span> <span style="color:#66d9ef">new</span> SearchController(<span style="color:#66d9ef">Me</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">btnSearch_Click</span>(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> System.Object, <span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> System.EventArgs)
</span></span><span style="display:flex;"><span>        _controller.SetPhrase(txtInput.Text.Trim)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">Private</span> <span style="color:#66d9ef">Sub</span> <span style="color:#a6e22e">controller_SearchStarted</span>(<span style="color:#66d9ef">ByVal</span> sender <span style="color:#f92672">As</span> <span style="color:#66d9ef">Object</span>, <span style="color:#66d9ef">ByVal</span> e <span style="color:#f92672">As</span> SearchEventArgs)
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">&#39;...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Sub</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">&#39;...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span></code></pre></div><p>Hopefully I will get the opportunity to use MVC/MVP more completely in the future.</p>
]]></content:encoded></item><item><title>SQL Like statement</title><link>https://andydote.co.uk/2009/05/15/sql-like-statement/</link><pubDate>Fri, 15 May 2009 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2009/05/15/sql-like-statement/</guid><description>Today I learnt a few new (well to me) SQL commands. The Like statement can do some basic regex type things. It supports character specifiers like this:
Column Like &amp;#39;%[a-z]Test[a-z]%&amp;#39; This will find the word test as long as there is a letter at either end of the word in a block of text. You can also say Not a letter like so:
Column Like &amp;#39;%[^a-z]Test[^a-z]%&amp;#39; This should find any words Test that do not have letters before or after them.</description><content:encoded><![CDATA[<p>Today I learnt a few new (well to me) SQL commands.  The <a href="http://doc.ddart.net/mssql/sql70/la-lz_2.htm">Like statement</a> can do some basic regex type things.  It supports character specifiers like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">Column</span> <span style="color:#66d9ef">Like</span> <span style="color:#e6db74">&#39;%[a-z]Test[a-z]%&#39;</span>
</span></span></code></pre></div><p>This will find the word test as long as there is a letter at either end of the word in a block of text.  You can also say Not a letter like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">Column</span> <span style="color:#66d9ef">Like</span> <span style="color:#e6db74">&#39;%[^a-z]Test[^a-z]%&#39;</span>
</span></span></code></pre></div><p>This should find any words Test that do not have letters before or after them. Very useful for searching for a complete word in a block of text.  However I could not get this to work (MSSQL Server 2005) so I ended up doing this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">Select</span> 	Columns
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">From</span>	TableName
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">Where</span>	BlockOfText <span style="color:#66d9ef">Like</span> <span style="color:#e6db74">&#39;%&#39;</span> <span style="color:#f92672">+</span> <span style="color:#f92672">@</span>word <span style="color:#f92672">+</span><span style="color:#e6db74">&#39;%&#39;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">and</span>	BlockOfText <span style="color:#66d9ef">not</span> <span style="color:#66d9ef">like</span> <span style="color:#e6db74">&#39;%[a-z]&#39;</span> <span style="color:#f92672">+</span> <span style="color:#f92672">@</span>word <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;[a-z]%&#39;</span>
</span></span></code></pre></div><p>Which works well for what I needed and is reasonably quick on a million records or so.</p>
]]></content:encoded></item><item><title>Conflicting Unrelated Options: Alps Trackpad vs Microsoft Mouse</title><link>https://andydote.co.uk/2008/04/17/conflicting-unrelated-options-alps-trackpad-vs-microsoft-mouse/</link><pubDate>Thu, 17 Apr 2008 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2008/04/17/conflicting-unrelated-options-alps-trackpad-vs-microsoft-mouse/</guid><description>Usability. It&amp;rsquo;s one of those things that everyone wants, you know, stuff that &amp;lsquo;just works&amp;rsquo;. It&amp;rsquo;s nice when companies go out of their way to make things &amp;lsquo;just work&amp;rsquo;. It&amp;rsquo;s a shame Sony (and others, but I have a Sony, so it&amp;rsquo;s their fault for this exercise) decided to make things harder for me.
Allow me to explain. I have a Sony Vaio (VGN-FE21M), which has an Alps touch pad, which like all touch pad has tapping enabled by default, and that I switch off straight away.</description><content:encoded><![CDATA[<p>Usability.  It&rsquo;s one of those things that everyone wants, you know, stuff that &lsquo;just works&rsquo;.  It&rsquo;s nice when companies go out of their way to make things &lsquo;just work&rsquo;.  It&rsquo;s a shame Sony (and others, but I have a Sony, so it&rsquo;s their fault for this exercise) decided to make things harder for me.</p>
<p>Allow me to explain.  I have a Sony Vaio (VGN-FE21M), which has an Alps touch pad, which like all touch pad has tapping enabled by default, and that I switch off straight away.  I also have a Microsoft Intellimouse 4, which has smooth scrolling, and scroll acceleration.</p>
<p>Now despite the fact that these two settings are completely unrelated, you can&rsquo;t have both at the same time.  The problem is that if I have the touch pad driver installed, it&rsquo;s scrolling setting overwrites the intellimouse&rsquo;s scroll setting, but I need the touchpad driver to disable tapping.</p>
<p>I tried the Vista drivers for both mice; I tried the XP drivers for both.  I even tried combinations of the drivers, and drivers for the touchpad from IBM and Siemens.  None worked.  I messed around in the registry with settings, broke lots of stuff, which also didn&rsquo;t help (luckily I did a registry backup before I started&hellip;)</p>
<p>Eventually I discovered the &rsquo;latest&rsquo; drivers from Sony, IBM, Fujitsu and Siemens were not as new as they could be.  The Dell drivers which I (eventually) found were newer, and although not designed for my laptop worked a charm.  I now have a tap free track pad, and smooth scrolling.</p>
<p>If anyone else is having this problem, here  is a link to the Dell drivers: <a href="http://support.us.dell.com/support/downloads/download.aspx?c=us&amp;l=en&amp;s=gen&amp;releaseid=R140031&amp;formatcnt=1&amp;libid=0&amp;fileid=187207">32 Bit Vista</a>, <a href="http://support.us.dell.com/support/downloads/download.aspx?c=us&amp;l=en&amp;s=gen&amp;releaseid=R140029&amp;formatcnt=1&amp;libid=0&amp;fileid=187206">64 Bit Vista</a>.</p>
]]></content:encoded></item><item><title>Creating Non resizable controls</title><link>https://andydote.co.uk/2008/04/13/creating-non-resizable-controls/</link><pubDate>Sun, 13 Apr 2008 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2008/04/13/creating-non-resizable-controls/</guid><description>A control I was recently developing required being non-resizable when on the form. When the application is running, this would be easy enough, just set its AutoSize property to False, and don&amp;rsquo;t dock the control.
However, this leaves the problem of resizing in the designer. You could override the resize event of the control, but for reasons outlined earlier, such as flickering, I decided against this.
Somewhere on the internet (where else&amp;hellip;?</description><content:encoded><![CDATA[<p>A control I was recently developing required being non-resizable when on the form.  When the application is running, this would be easy enough, just set its <code>AutoSize</code> property to False, and don&rsquo;t dock the control.</p>
<p>However, this leaves the problem of resizing in the designer.  You could override the resize event of the control, but for <a href="http://www.stormbase.net/index.php?id=32">reasons outlined earlier</a>, such as flickering, I decided against this.</p>
<p>Somewhere on the internet (where else&hellip;?) I can upon the idea of using a custom designer.  The <code>ControlDesigner</code> class allows us to specify the designer behaviours of the control it is attached to.</p>
<p>To do this, we create Friend Class, and make it inherit from <code>System.Windows.Forms.Design.ControlDesigner</code>, then override the <code>SelectionRules</code> property:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Friend</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">NonResizableDesigner</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Inherits</span> System.Windows.Forms.Design.ControlDesigner
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Overrides</span> <span style="color:#66d9ef">ReadOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">SelectionRules</span>() <span style="color:#f92672">As</span> System.Windows.Forms.Design.SelectionRules
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">MyBase</span>.SelectionRules
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span></code></pre></div><p>As SelectionRules is a FlagsEnum, to remove the particular functionality from it, we have to NOT the flag we want to remove, then AND it with the existing flags.  In other words, take the controls existing flags and add <code>And Not SelectionRules.AllSizeable</code> to it.  So the entire designer class becomes this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Friend</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">NonResizableDesigner</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Inherits</span> System.Windows.Forms.Design.ControlDesigner
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Overrides</span> <span style="color:#66d9ef">ReadOnly</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">SelectionRules</span>() <span style="color:#f92672">As</span> System.Windows.Forms.Design.SelectionRules
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">MyBase</span>.SelectionRules <span style="color:#f92672">And</span> <span style="color:#66d9ef">Not</span> SelectionRules.AllSizeable
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span></code></pre></div><p>Simple huh?  Now all we need to do is apply it to the control that we wish to be non-resizable, which just takes one attribute on the class:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#a6e22e">&lt;Designer(GetType(NonResizableDesigner))&gt;</span> _
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Class</span> <span style="color:#a6e22e">Foo</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Function</span> <span style="color:#a6e22e">Bar</span>()
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Function</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Class</span>
</span></span></code></pre></div><p>Now when this control is viewed in the designer, it has the same outline as a label when the AutoSize property is set to true.  You can move the control to your hearts content, but no resizing.</p>
]]></content:encoded></item><item><title>Vaio Event Service and Vista</title><link>https://andydote.co.uk/2008/04/08/vaio-event-service-and-vista/</link><pubDate>Tue, 08 Apr 2008 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2008/04/08/vaio-event-service-and-vista/</guid><description>When I first installed vista onto my laptop (a Sony Vaio VGN-FE21M) I also installed all the Sony stuff that I needed for it, mainly the VES (Vaio Event Service) and Control Panel, although there is a lot of other junk that they give you to install.
In fact the first thing I did when I had the laptop new was to wipe MCE 2005 off it, and install XP Pro.</description><content:encoded><![CDATA[<p>When I first installed vista onto my laptop (a Sony Vaio VGN-FE21M) I also installed all the Sony stuff that I needed for it, mainly the VES (Vaio Event Service) and Control Panel, although there is a lot of other junk that they give you to install.</p>
<p>In fact the first thing I did when I had the laptop new was to wipe MCE 2005 off it, and install XP Pro.  Now I have nothing against MCE, but there is no point on this laptop; there is no remote, no tuner, and the screen is only 15.1 inches (wide screen), so I couldn&rsquo;t see the point in all the extra paraphernalia that MCE needs running in the background.</p>
<p>When I installed all the Vaio stuff on XP, it all worked fine, as it did in Vista too. Sort of.  While the hot keys worked (brightness was the only one I was really interested in), it sapped 50% CPU <em>all the time</em>.  This was worrying, as I have a dual core, and thus if I had single core, it would be using 100% all the time.  Not good.</p>
<p>To solve this problem, I installed the XP version of the Event Service (Version 2.3.00.08110) instead of the Vista version (Version 3.0.00.13110), which solved the problem, and worked 100%.</p>
<p>Now while I am please it works, it begs the question; if it aint broke, why &lsquo;fix&rsquo; it?.  So anyone who&rsquo;s hot keys don&rsquo;t work in Vista, or do work, but slow Vista down (more), just install the XP Versions!</p>
]]></content:encoded></item><item><title>Flow Layout Panel and Scroll Wheel Problem</title><link>https://andydote.co.uk/2008/03/29/flow-layout-panel-and-scroll-wheel-problem/</link><pubDate>Sat, 29 Mar 2008 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2008/03/29/flow-layout-panel-and-scroll-wheel-problem/</guid><description>I came across a problem while writing an application for my parents today. If you have a FlowLayoutPanel on your form, and have many items in it, causing it to overflow and require scroll bars, you are unable to scroll the control&amp;rsquo;s content using the mouse wheel.
This is somewhat trying in today&amp;rsquo;s applications, as nearly everyone has a mouse with a scroll wheel, or a track pad on their laptop with a scroll area.</description><content:encoded><![CDATA[<p>I came across a problem while writing an application for my parents today.  If you have a FlowLayoutPanel on your form, and have many items in it, causing it to overflow and require scroll bars, you are unable to scroll the control&rsquo;s content using the mouse wheel.</p>
<p>This is somewhat trying in today&rsquo;s applications, as nearly everyone has a mouse with a scroll wheel, or a track pad on their laptop with a scroll area.</p>
<p>I came across the solution to the problem at Scott Waldron&rsquo;s <a href="http://www.thewayofcoding.com/2008/02/c-net-programming-tip-flowlayoutpanel.html">blog</a>, where he adds code to the Flow Layout Panel&rsquo;s MouseEnter Event that focuses the Flow Layout Panel, and thus allows it to be scrolled with the wheel.  Many thanks to him for finding the solution and blogging about it.</p>
<p>My real bone of contention with this is that the Flow Layout Panel does not support this behaviour by default.  If it is a feature not everyone wants, just put a Boolean property on the control called &ldquo;Accepts Scroll Wheel&rdquo; or something similar, and have it False by default.</p>
]]></content:encoded></item><item><title>VB.NET &amp;amp; C# Fixed height User Controls</title><link>https://andydote.co.uk/2008/03/29/vbnet-c-fixed-height-user-controls/</link><pubDate>Sat, 29 Mar 2008 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/2008/03/29/vbnet-c-fixed-height-user-controls/</guid><description>Another problem I came across recently was fixed height user controls. Someone at work had created a fixed height user control, by putting the following code in the paint event:
Me.Width = 20 Now while for the majority of cases this works, it doesn&amp;rsquo;t if you dock the control to the left or right of the form, as each time the Layout Engine tries to stick the top of the control to the top of the parent and the bottom of the control to the bottom of the parent, it fires the Paint() event.</description><content:encoded><![CDATA[<p>Another problem I came across recently was fixed height user controls.  Someone at work had created a fixed height user control, by putting the following code in the paint event:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Me</span>.Width <span style="color:#f92672">=</span> 20
</span></span></code></pre></div><p>Now while for the majority of cases this works, it doesn&rsquo;t if you dock the control to the left or right of the form, as each time the Layout Engine tries to stick the top of the control to the top of the parent and the bottom of the control to the bottom of the parent, it fires the <code>Paint()</code> event.  This causes the user control to change its size, which causes the Layout Engine to activate, and the whole cycle starts over, and as a by product, creates a horrid flickering.</p>
<p>Some suggestions were made to fix the problem such as disabling docking (why fix a problem by causing another one?), moving the code to the resize event (same effect, with the added benefit of allowing a resize until it is complete, then resizing&hellip;).</p>
<p>Some googling revealed one very angry fellow on the <a href="http://www.xtremedotnettalk.com/showthread.php?t=94118">xtreme dot net talk</a> forums, and no real answer.  The method he had tried was to set the following flag in the initialize event:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span>Control.SetStyle(ControlStyles.FixedHeight, <span style="color:#66d9ef">true</span>)
</span></span></code></pre></div><p>Which if you read the documentation for ControlStyles.FixedHeight (it&rsquo;s on the intellitype, so there&rsquo;s no reason for not doing so) it says the following:</p>
<p>If true, the control has a fixed height when auto-scaled. For example, if a layout operation attempts to rescale the control to accommodate a new Font, the control&rsquo;s Height remains unchanged.</p>
<p>So another solution was needed.  In the end, I and a fellow developer found that overriding the controls MaximumHeight and MinimumHeight was the way to do it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vb" data-lang="vb"><span style="display:flex;"><span><span style="color:#66d9ef">Const</span> MaxHeight <span style="color:#f92672">As</span> <span style="color:#66d9ef">Integer</span> <span style="color:#f92672">=</span> 20
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Overrides</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">MaximumSize</span>() <span style="color:#f92672">As</span> Drawing.Size
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">New</span> Drawing.Size(<span style="color:#66d9ef">MyBase</span>.MaximumSize.Width, MaxHeight)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Set</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> Drawing.Size)
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">MyBase</span>.MaximumSize <span style="color:#f92672">=</span> <span style="color:#66d9ef">New</span> Drawing.Size(value.Width, MaxHeight)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Set</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">Public</span> <span style="color:#66d9ef">Overrides</span> <span style="color:#66d9ef">Property</span> <span style="color:#a6e22e">MinimumSize</span>() <span style="color:#f92672">As</span> Drawing.Size
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">Return</span> <span style="color:#66d9ef">New</span> Drawing.Size(<span style="color:#66d9ef">MyBase</span>.MinimumSize.Width, MaxHeight)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Get</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">Set</span>(<span style="color:#66d9ef">ByVal</span> value <span style="color:#f92672">As</span> Drawing.Size)
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">MyBase</span>.MinimumSize <span style="color:#f92672">=</span> <span style="color:#66d9ef">New</span> Drawing.Size(value.Width, MaxHeight)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Set</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">End</span> <span style="color:#66d9ef">Property</span>
</span></span></code></pre></div><p>This allows the end user to modify the maximum width (in this case) to their heart&rsquo;s content, and still have a control of fixed height, that can be docked properly, doesn&rsquo;t flicker, and above all resizes properly in the forms designer.</p>
]]></content:encoded></item><item><title>Contact</title><link>https://andydote.co.uk/contact/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/contact/</guid><description>contact</description><content:encoded><![CDATA[<p>I’m usually pretty easy to get hold of, here’s how I use different channels to communicate with people and how best to contact me.</p>
<h2 id="email">Email</h2>
<p>This is the easiest way to contact me.  I&rsquo;ll usually respond quickly. The address is <a href="mailto:andy@andydote.co.uk">andy@andydote.co.uk</a>.</p>
<h2 id="twitter">Twitter</h2>
<p>My DMs are usually open, and I will usually respond.  I tend to announce anything interesting I&rsquo;m going to be doing on Twitter, so follow if you can.  My handle is <a href="https://twitter.com/pondidum">@pondidum</a>.</p>
<h2 id="twitch--youtube">Twitch &amp; YouTube</h2>
<p>I used to stream a lot of software development but had to stop as I just didn&rsquo;t get enough downtime, and something had to give.  I might start again on a much lighter schedule at some point in the future.  It&rsquo;ll be announced on Twitter if I do.  My <a href="https://www.twitch.tv/pondidum">channel is Pondidum</a>.  There is a YouTube channel with <a href="https://www.youtube.com/channel/UCsE6VIFVuJjBowVo49fLchQ">all my past streams</a> too.</p>
<h2 id="linkedin">LinkedIn</h2>
<p>I don&rsquo;t have a LinkedIn account, and I have no intention of getting one.  If you find me on LinkedIn, it&rsquo;s not actually me.</p>
<h2 id="skype">Skype</h2>
<p>I only log into Skype when something is arranged for it.  Email me, and we can work out if Skype is the right medium to communicate.</p>
<h2 id="what-i-will-respond-to">What I will respond to</h2>
<p>Enquiries about speaking at events will always get a response, even if I have to decline.</p>
<p>My rough rules for speaking at events, which are not set in stone are as follows.  All assume I am available on a given date:</p>
<ul>
<li><strong>Local (In Finland)</strong> - I&rsquo;ll gladly come and speak</li>
<li><strong>Non-Profit/Community (abroad)</strong> - Depends on how interesting the location/event looks to me</li>
<li><strong>For-Profit/Corporate (abroad)</strong> - Cover my Hotel &amp; Travel Expenses</li>
</ul>
<h2 id="what-i-might-respond-to">What I might respond to</h2>
<p>I do not do tech-support unless we have a commercial agreement in place.  If it&rsquo;s an issue with a library I maintain, a Github Issue is your best bet.</p>
<p>If your message doesn’t explicitly look like it needs a response or it’s vague or not clear what the purpose is, you may not hear back from me.</p>
]]></content:encoded></item><item><title>Random Notes</title><link>https://andydote.co.uk/notes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/notes/</guid><description>Notes</description><content:encoded><![CDATA[<p>Just little snippets of things which might be useful later, but are not really worthy of a blog post.</p>
<h2 id="fabio">Fabio</h2>
<p>The  <code>urlprefix-</code> in the tags for a service in Consul is a literal constant.
e.g. <code>urlprefix-/</code> -&gt; matches everything</p>
<h2 id="traefik">Traefik</h2>
<p>When you specify a Traefik constraint as <code>--consulcatalog.constraints='tag==service'</code>, the tag it looks for in Consul is <code>traefik.tags=service</code>, NOT <code>service</code>.</p>
<h2 id="packer">Packer</h2>
<p>EC2 (and GCP) instances run scripts on machine start, but Packer won&rsquo;t wait for these to complete before running things, which can break <code>apt</code>.  Add this as a provisioner to wait for AWS Cloud-Init to finish before your scripts which need <code>apt</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;type&#34;</span>:<span style="color:#e6db74">&#34;shell&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;only&#34;</span>: [ <span style="color:#e6db74">&#34;amazon-ebs&#34;</span> ],
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;inline&#34;</span>: [ <span style="color:#e6db74">&#34;/usr/bin/cloud-init status --wait&#34;</span> ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="vagrant">Vagrant</h2>
<p>Override the default smb share in hyper-v with the username and password to use, pulled from environment:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>config<span style="color:#f92672">.</span>vm<span style="color:#f92672">.</span>synced_folder <span style="color:#e6db74">&#34;.&#34;</span>, <span style="color:#e6db74">&#34;/vagrant&#34;</span>, <span style="color:#e6db74">smb_username</span>: <span style="color:#66d9ef">ENV</span><span style="color:#f92672">[</span><span style="color:#e6db74">&#39;VAGRANT_SMB_USER&#39;</span><span style="color:#f92672">]</span>, <span style="color:#e6db74">smb_password</span>: <span style="color:#66d9ef">ENV</span><span style="color:#f92672">[</span><span style="color:#e6db74">&#39;VAGRANT_SMB_PASS&#39;</span><span style="color:#f92672">]</span>
</span></span></code></pre></div><h2 id="jenkins">Jenkins</h2>
<p>Adding build parameters e.g. <code>commit_hash</code> will show up on the <code>params.commit_hash</code> in a pipeline, <strong>but will also</strong> get written as an environment variable, maintaining case, e.g. <code>env.commit_hash</code> or <code>$commit_hash</code>.</p>
<p>If you export in a different case, the original name is preserved, with the new value e.g. <code>env.COMMIT_HASH = 'new'</code> will actually be available as <code>$commit_hash</code>.</p>
<p>If you try to unset the original casing first, then set on the casing you want, it <strong>removes both</strong> e.g.</p>
<pre tabindex="0"><code>env.commit_hash = &#34;&#34;
env.COMMIT_HASH = &#34;yes?&#34;

sh &#34;env | grep -i commit_hash | wc -l&#34; // 0.
</code></pre>]]></content:encoded></item><item><title>Talks</title><link>https://andydote.co.uk/talks/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://andydote.co.uk/talks/</guid><description>talks</description><content:encoded><![CDATA[<h2 id="feature-toggles-the-good-the-bad-and-the-ugly">Feature Toggles: The Good, The Bad and The Ugly</h2>
<p>A Talk on how Feature Toggles can be a great asset or terrible curse. Examples of how the go wrong/right, and what to do about it.</p>
<p><a href="/presentations/index.html?feature-toggles">Slides</a> and <a href="https://github.com/Pondidum/presentations/tree/master/content/feature-toggles">Slide Source</a></p>

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
  <iframe src="https://www.youtube.com/embed/r7VI5x2XKXw" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video"></iframe>
</div>

<h2 id="12-factor-microservices-in-c">12 Factor Microservices (in C#)</h2>
<p>A Talk on how the 12 Factor Application Principles can help simplify development and operations of microservices.  Examples in asp.net core.</p>
<p><a href="/presentations/index.html?twelve">Slides</a> and <a href="https://github.com/Pondidum/presentations/tree/master/content/twelve/">Slide Source</a></p>

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
  <iframe src="https://www.youtube.com/embed/KGIGFHVoZo0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video"></iframe>
</div>

<h2 id="nomad-kubernetes-without-the-complexity">Nomad: Kubernetes without the Complexity</h2>
<p>A talk on Hashicorp&rsquo;s Nomad product, which provides container orchestration, but in a much lighter weight manner than Kubernetes.</p>
<p><a href="/presentations/index.html?nomad">Slides</a> and <a href="https://github.com/Pondidum/presentations/tree/master/content/nomad/">Slide Source</a></p>

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
  <iframe src="https://www.youtube.com/embed/THNgtTsApaE" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video"></iframe>
</div>

<h2 id="how-to-secure-your-microservices">How to Secure Your Microservices</h2>
<p>A talk on how to use Hashicorp&rsquo;s Vault to generate and consume dynamic database credentials.  Examples on the CLI and from a C## application.</p>
<p><a href="/presentations/index.html?vault">Slides</a> and <a href="https://github.com/Pondidum/presentations/tree/master/content/vault/">Slide Source</a></p>

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
  <iframe src="https://www.youtube.com/embed/SCTOXsFGYnM" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video"></iframe>
</div>

<h2 id="streaming-software-development-for-fun-and">Streaming Software Development for Fun and&hellip;?</h2>
<p>A Lightning Talk on my experiences streaming software development on Twitch.</p>
<p><a href="/presentations/index.html?streaming">Slides</a> and <a href="https://github.com/Pondidum/presentations/tree/master/content/streaming">Slide Source</a></p>

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
  <iframe src="https://www.youtube.com/embed/8tpab1xpBSs" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video"></iframe>
</div>

<h2 id="building-a-serverless-eventsourced-slack-clone">Building a Serverless, EventSourced Slack clone</h2>
<p>A talk about the leasons learned trying to make a totally serverless application. Covers terraform, cognito, lambda, api-gateway, dynamodb and s3</p>
<p><a href="/presentations/index.html?serverless-slack">Slides</a> and <a href="https://github.com/Pondidum/presentations/tree/master/content/serverless-slack">Slide Source</a></p>

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
  <iframe src="https://www.youtube.com/embed/8dvzgCcvdGY" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video"></iframe>
</div>

<h2 id="strong-type-all-the-things">Strong Type All The Things!</h2>
<p>A Lightning Talk on Strong Typing, covering configuration, identifiers and value types.</p>
<p><a href="/presentations/index.html?strong-typing">Slides</a> and <a href="https://github.com/Pondidum/presentations/tree/master/content/strong-typing">Slide Source</a></p>

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
  <iframe src="https://www.youtube.com/embed/gTTVirxhETc" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video"></iframe>
</div>

]]></content:encoded></item></channel></rss>