<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>//Todo: Think of name for blog</title>
  
  
  <link href="https://todothinkofname.net/atom.xml" rel="self"/>
  
  <link href="https://todothinkofname.net/"/>
  <updated>2023-02-19T01:46:32.000Z</updated>
  <id>https://todothinkofname.net/</id>
  
  <author>
    <name>Dion Brown</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Using SQS Delay Queue as a Scheduler</title>
    <link href="https://todothinkofname.net/2023/02/18/Using-SQS-as-a-scheduler/"/>
    <id>https://todothinkofname.net/2023/02/18/Using-SQS-as-a-scheduler/</id>
    <published>2023-02-18T19:45:16.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>Recently we have been migrating our pdf generation at work from Prince to Doc Raptor. Doc Raptor has an async flow which will call a web hook when the pdf generation is done. We found that if there is an error generating the pdf Doc Raptor doesn’t call the web hook.</p><p>This led to an interesting issue, we were using the webhook so we didn’t need to poll their API, now we need to poll their API on the off chance there is an error.</p><p>When looking for possible options to implement the polling I thought about using a <a href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-delay-queues.html">SQS delay queue</a>, delaying the message visibility by the polling interval. If the status isn’t completed or failed another message is queued again delaying the message visibility.</p><p>The general flow is below<br><img src="/2023/02/18/Using-SQS-as-a-scheduler/flow.png"></p><p>The GeneratePDF posts a message to the queue containing the status_id that Doc Raptor give us to check the status, our export id and the original queue time with delay seconds set to 30 seconds. The poll lambda picks up the message and checks the sataus. If the status is <code>completed</code> the lambda just returns, if the status is <code>failed</code> it records the failed reason and returns. If the status is something else it posts another messag to the queue with same data and another 30 second delay. If we find that we have been polling for more than 15 minutes we raise an error and exit.</p><p><img src="/2023/02/18/Using-SQS-as-a-scheduler/flow.drawio.png"></p><p>Lastly the code to send the delay message is very simple.</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="variable constant_">SQS</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;aws-sdk&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> config <span class="keyword">from</span> <span class="string">&#x27;../config&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">interface</span> pdfCheckMessage &#123;</span><br><span class="line">  <span class="attr">exportId</span>: <span class="built_in">string</span>;</span><br><span class="line">  <span class="attr">statusId</span>: <span class="built_in">string</span>;</span><br><span class="line">  <span class="attr">startTime</span>: <span class="built_in">string</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">POLL_QUEUE</span> = config.<span class="title function_">get</span>(<span class="string">&#x27;pollQueue&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">DELAY_SECONDS</span> = config.<span class="title function_">get</span>(<span class="string">&#x27;delaySeconds&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> sqs = <span class="keyword">new</span> <span class="title function_">SQS</span>();</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">queueDelayedMessage</span> = <span class="keyword">async</span> (<span class="params">message: pdfCheckMessage</span>) =&gt; &#123;</span><br><span class="line">  <span class="keyword">await</span> sqs</span><br><span class="line">    .<span class="title function_">sendMessage</span>(&#123;</span><br><span class="line">      <span class="title class_">QueueUrl</span>: <span class="variable constant_">POLL_QUEUE</span>,</span><br><span class="line">      <span class="title class_">MessageBody</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(message),</span><br><span class="line">      <span class="title class_">DelaySeconds</span>: <span class="variable constant_">DELAY_SECONDS</span>,</span><br><span class="line">    &#125; <span class="keyword">as</span> <span class="variable constant_">SQS</span>.<span class="property">Types</span>.<span class="property">SendMessageRequest</span>)</span><br><span class="line">    .<span class="title function_">promise</span>();</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>Yes this code needs upgrading to use the AWS SDK V3.</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Recently we have been migrating our pdf generation at work from Prince to Doc Raptor. Doc Raptor has an async flow which will call a web </summary>
      
    
    
    
    
    <category term="AWS" scheme="https://todothinkofname.net/tags/AWS/"/>
    
    <category term="Lambda" scheme="https://todothinkofname.net/tags/Lambda/"/>
    
    <category term="NodeJS" scheme="https://todothinkofname.net/tags/NodeJS/"/>
    
    <category term="SQS" scheme="https://todothinkofname.net/tags/SQS/"/>
    
  </entry>
  
  <entry>
    <title>Tracking Down a File Desciptor Leak in AWS Lambda</title>
    <link href="https://todothinkofname.net/2023/02/18/Tracking-down-a-File-descriptor-leak-in-AWS-Lambda/"/>
    <id>https://todothinkofname.net/2023/02/18/Tracking-down-a-File-descriptor-leak-in-AWS-Lambda/</id>
    <published>2023-02-18T18:48:55.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>Back in last year August we started getting an odd error from the couch-backup lambda. Out of nowhere we started getting error messages like the below.</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;message&quot;</span><span class="punctuation">:</span> <span class="string">&quot;EMFILE: too many open files, open &#x27;/tmp/couchbackup/couchbackup-f..._2022-08-22T17:30:33.642Z.log&#x27;&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;stack&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Error: EMFILE: too many open files, open &#x27;/tmp/couchbackup/couchbackup-f..._2022-08-22T17:30:33.642Z.log&#x27;&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;errno&quot;</span><span class="punctuation">:</span> <span class="number">-24</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;code&quot;</span><span class="punctuation">:</span> <span class="string">&quot;EMFILE&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;syscall&quot;</span><span class="punctuation">:</span> <span class="string">&quot;open&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;path&quot;</span><span class="punctuation">:</span> <span class="string">&quot;/tmp/couchbackup/couchbackup-f..._2022-08-22T17:30:33.642Z.log&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>Looking through our code we don’t directly open any files or sockets which would cause this type of issue.<br>We could see that file descriptors where being left open using Lambda Insights.<br><img src="/images/before.png" alt="before fix"></p><p>So, we Googled to see if anyone else had this issue and discovered this <a href="https://bahr.dev/2021/06/03/lambda-emfile/">blog</a>. It suggested adding a node package called wtfnode wtfnode - npm (npmjs.com). Unfortunately, this didn’t seem to work, the author of the package does say that this package is using undocumented Node apis and could break without warning.</p><p>After a few more weeks of Googling, I came across this package <a href="https://github.com/samswen/lambda-emfiles">samswen&#x2F;lambda-emfiles: solve node AWS lambda EMFILE issue (github.com)</a>. This package handles the EMFILE issue a different way, it causes the Lambda process to exit with a status code of 1. This means that lambda throws away the current lambda environment and starts a new one. While it didn’t fix the issue it meant that we didn’t get the retries when a process ran out of file descriptors.<br>I did a little poking around in the source code of this package to see how it was working out the number of open file descriptors. What I found was</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="title function_">exec</span>(<span class="string">`ls /proc/<span class="subst">$&#123;process.pid&#125;</span>/fd`</span>, <span class="function">(<span class="params">err, stdout, stderr</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (err || stderr) &#123;</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">is_ok</span> = <span class="literal">false</span>;</span><br><span class="line">      <span class="title function_">resolve</span>(<span class="variable language_">this</span>.<span class="property">is_ok</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="keyword">const</span> parts = stdout.<span class="title function_">split</span>(<span class="string">&quot;\n&quot;</span>);</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">emfiles_count</span> = parts.<span class="property">length</span> - <span class="number">1</span>;</span><br><span class="line">      <span class="title function_">resolve</span>(<span class="variable language_">this</span>.<span class="property">is_ok</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>The thing that supprised me was that the Lambda run time has access to the &#x2F;proc virtual directory. I guess that makes sense as it is running on Linux.</p><p>Having found this I had a play around on my machine to see what information you could get. I found that ls -l returned</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">lr-x------ 1 sbx_user1051 990 64 Nov 29 17:46 0 -&gt; /dev/null</span><br><span class="line">l-wx------ 1 sbx_user1051 990 64 Nov 29 17:46 1 -&gt; pipe:[3890]</span><br><span class="line">lrwx------ 1 sbx_user1051 990 64 Nov 29 17:46 10 -&gt; anon_inode:[eventpoll]</span><br><span class="line">lrwx------ 1 sbx_user1051 990 64 Nov 29 17:47 100 -&gt; /tmp/tmp-33-k3p5q3R0D4Fi</span><br><span class="line">lrwx------ 1 sbx_user1051 990 64 Nov 29 17:47 101 -&gt; /tmp/tmp-33-7uD5r8I2FL2J</span><br><span class="line">lrwx------ 1 sbx_user1051 990 64 Nov 29 17:47 102 -&gt; /tmp/tmp-33-x5ZwfUpaOOSp</span><br><span class="line">lrwx------ 1 sbx_user1051 990 64 Nov 29 17:47 103 -&gt; socket:[13171]</span><br><span class="line">lrwx------ 1 sbx_user1051 990 64 Nov 29 17:47 104 -&gt; /tmp/tmp-33-JNd7W44OhPj8</span><br><span class="line">lrwx------ 1 sbx_user1051 990 64 Nov 29 17:47 106 -&gt; socket:[13173]</span><br><span class="line">lrwx------ 1 sbx_user1051 990 64 Nov 29 17:47 108 -&gt; /tmp/tmp-33-I7NKSkv4kw8P</span><br><span class="line">lrwx------ 1 sbx_user1051 990 64 Nov 29 17:47 109 -&gt; /tmp/tmp-33-qymMaVIo1Zga</span><br></pre></td></tr></table></figure><p>After finding this we added some more logging to the lambda to record this before the process finished and what we found was the number of tmp files kept increasing. We now had out smoking gun.</p><p>Now that we knew what we were looking for I had a look to check that our code wan’t creating temp files, and we weren’t.</p><p>Then I started having a look at the <a href="https://github.com/cloudant/couchbackup">Cloudant couchbackup library</a> that we use. The first thing I noticed was in their package.json they referenced a <a href="https://github.com/cloudant/couchbackup/blob/f44a8a3fe2967cd33e32dd911b699f019bbee1a4/package.json#L27">package tmp</a>, so it looks like they use tmp files. Next, I looked for references to that package and found</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">apiDefaults</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    <span class="attr">parallelism</span>: <span class="number">5</span>,</span><br><span class="line">    <span class="attr">bufferSize</span>: <span class="number">500</span>,</span><br><span class="line">    <span class="attr">requestTimeout</span>: <span class="number">120000</span>,</span><br><span class="line">    <span class="attr">log</span>: tmp.<span class="title function_">fileSync</span>().<span class="property">name</span>,</span><br><span class="line">    <span class="attr">resume</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="attr">mode</span>: <span class="string">&quot;full&quot;</span>,</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Ok, so firstly does this get called when we use their backup function and secondaly what does it do? More digging and I found it is <a href="https://github.com/cloudant/couchbackup/blob/f44a8a3fe2967cd33e32dd911b699f019bbee1a4/app.js#L23">aliased app.js</a> and it is called in the backup function.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">backup</span>: <span class="keyword">function</span>(<span class="params">srcUrl, targetStream, opts, callback</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> listenerErrorIndicator = &#123; <span class="attr">errored</span>: <span class="literal">false</span> &#125;;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> callback === <span class="string">&#x27;undefined&#x27;</span> &amp;&amp; <span class="keyword">typeof</span> opts === <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">      callback = opts;</span><br><span class="line">      opts = &#123;&#125;;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (!<span class="title function_">validateArgs</span>(srcUrl, opts, callback)) &#123;</span><br><span class="line">      <span class="comment">// bad args, bail</span></span><br><span class="line">      <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// if there is an error writing to the stream, call the completion</span></span><br><span class="line">    <span class="comment">// callback with the error set</span></span><br><span class="line">    <span class="title function_">addEventListener</span>(listenerErrorIndicator, targetStream, <span class="string">&#x27;error&#x27;</span>, <span class="keyword">function</span>(<span class="params">err</span>) &#123;</span><br><span class="line">      <span class="title function_">debug</span>(<span class="string">&#x27;Error &#x27;</span> + <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(err));</span><br><span class="line">      <span class="keyword">if</span> (callback) <span class="title function_">callback</span>(err);</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    opts = <span class="title class_">Object</span>.<span class="title function_">assign</span>(&#123;&#125;, <span class="title function_">defaults</span>(), opts);</span><br></pre></td></tr></table></figure><p>Right, so it is called in the path we are using what does it do? Next, I dig into the tmp package.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Synchronous version of file.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">Options</span>&#125; <span class="variable">options</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@returns</span> &#123;<span class="type">FileSyncObject</span>&#125; object consists of name, fd and removeCallback</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> &#123;<span class="type">Error</span>&#125; if cannot create a file</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">fileSync</span>(<span class="params">options</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> args = <span class="title function_">_parseArguments</span>(options),</span><br><span class="line">    opts = args[<span class="number">0</span>];</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> discardOrDetachDescriptor =</span><br><span class="line">    opts.<span class="property">discardDescriptor</span> || opts.<span class="property">detachDescriptor</span>;</span><br><span class="line">  <span class="keyword">const</span> name = <span class="title function_">tmpNameSync</span>(opts);</span><br><span class="line">  <span class="keyword">var</span> fd = fs.<span class="title function_">openSync</span>(name, <span class="variable constant_">CREATE_FLAGS</span>, opts.<span class="property">mode</span> || <span class="variable constant_">FILE_MODE</span>);</span><br><span class="line">  <span class="comment">/* istanbul ignore else */</span></span><br><span class="line">  <span class="keyword">if</span> (opts.<span class="property">discardDescriptor</span>) &#123;</span><br><span class="line">    fs.<span class="title function_">closeSync</span>(fd);</span><br><span class="line">    fd = <span class="literal">undefined</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    <span class="attr">name</span>: name,</span><br><span class="line">    <span class="attr">fd</span>: fd,</span><br><span class="line">    <span class="attr">removeCallback</span>: <span class="title function_">_prepareTmpFileRemoveCallback</span>(</span><br><span class="line">      name,</span><br><span class="line">      discardOrDetachDescriptor ? -<span class="number">1</span> : fd,</span><br><span class="line">      opts,</span><br><span class="line">      <span class="literal">true</span></span><br><span class="line">    ),</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>The first thing I noticed was on line 15 it is opening a file and then on like 18 is closes the file only if you pass in <code>opts.discardDescriptor === true</code>. That looks like the issue!!</p><p>Lastly before raising an issue with Cloudant I wanted to test it, so in our couch-backup lambda I went into the node_modules folder, found the Cloudant code and changed tmp.fileSync().name to tmp.fileSync({discardDescriptor : true}).name and push those changes to production.</p><p>The next day this was the graph from Lambda Insights<br><img src="/images/after.png" alt="after fix"></p><p>Yay!!! We have found the problem.</p><p>The last thing was raising an issue with <a href="https://github.com/cloudant/couchbackup/issues/535">Cloudant File descriptor leak · Issue #535 · cloudant&#x2F;couchbackup (github.com)</a> and they are implementing what I suggested fix file descriptor leak in backup by <a href="https://github.com/cloudant/couchbackup/pull/536">emlaver · Pull Request #536 · cloudant&#x2F;couchbackup (github.com)</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Back in last year August we started getting an odd error from the couch-backup lambda. Out of nowhere we started getting error messages l</summary>
      
    
    
    
    
    <category term="AWS" scheme="https://todothinkofname.net/tags/AWS/"/>
    
    <category term="Lambda" scheme="https://todothinkofname.net/tags/Lambda/"/>
    
    <category term="NodeJS" scheme="https://todothinkofname.net/tags/NodeJS/"/>
    
    <category term="Cloudant" scheme="https://todothinkofname.net/tags/Cloudant/"/>
    
  </entry>
  
  <entry>
    <title>Lambda Versioning With CDK</title>
    <link href="https://todothinkofname.net/2022/02/12/Lambda-versioning-with-CDK/"/>
    <id>https://todothinkofname.net/2022/02/12/Lambda-versioning-with-CDK/</id>
    <published>2022-02-12T22:39:31.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>I stublied across this hint in my twitter feed, but forgot to book mark it. Thank you to the person that originally posted it.</p><p>For a litte while I was trying to figure out how to stop CDK from deleting old lambda version so you could roll back quickly.  Turns out it is very simple, you just need to set the rentention policy of the version to retain.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> function = <span class="keyword">new</span> Function(<span class="keyword">this</span>, <span class="string">&quot;example-lambda&quot;</span>, <span class="keyword">new</span> FunctionProps</span><br><span class="line">&#123;</span><br><span class="line">  &lt;other <span class="keyword">set</span> up code&gt;</span><br><span class="line">  CurrentVersionOptions = <span class="keyword">new</span> VersionOptions</span><br><span class="line">  &#123;</span><br><span class="line">      RemovalPolicy = RemovalPolicy.RETAIN</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> version = function.CurrentVersion;</span><br><span class="line">version.AddAlias(<span class="string">&quot;production&quot;</span>);</span><br></pre></td></tr></table></figure><p>Which gives this in the lamba console<br><img src="/images/lambda-versions.png"></p><p><a href="https://github.com/DionBrNz/LambaCdkPipeline/tree/versions">Full code here</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;I stublied across this hint in my twitter feed, but forgot to book mark it. Thank you to the person that originally posted it.&lt;/p&gt;
&lt;p&gt;For</summary>
      
    
    
    
    
    <category term="AWS" scheme="https://todothinkofname.net/tags/AWS/"/>
    
    <category term="C#" scheme="https://todothinkofname.net/tags/C/"/>
    
    <category term="Loambda" scheme="https://todothinkofname.net/tags/Loambda/"/>
    
  </entry>
  
  <entry>
    <title>C# CDK Aspect</title>
    <link href="https://todothinkofname.net/2022/02/06/C-CDK-Aspect/"/>
    <id>https://todothinkofname.net/2022/02/06/C-CDK-Aspect/</id>
    <published>2022-02-06T01:54:33.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>I recently stumbled across CDK Aspects on the <a href="https://blog.beachgeek.co.uk/newsletter/aws-open-source-news-and-updates-98/">AWS open source news and updates new letter</a>. There was a link to an <a href="https://aws.hashnode.com/the-power-of-aws-cdk-aspects">example Tag checker</a> that I thought I would try out in C#.</p><p>I originally had the class defined as  </p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">TagAspect</span> :  <span class="title">IAspect</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">readonly</span> IList&lt;<span class="built_in">string</span>&gt; _requiredTags;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">TagAspect</span>(<span class="params">IList&lt;<span class="built_in">string</span>&gt; requiredTags</span>)</span></span><br><span class="line">    &#123;</span><br><span class="line">        _requiredTags = requiredTags;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">Visit</span>(<span class="params">IConstruct node</span>)</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span> (node <span class="keyword">is</span> Stack stack)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">foreach</span> (<span class="keyword">var</span> requiredTag <span class="keyword">in</span> _requiredTags)</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="keyword">if</span> (!stack.Tags.TagValues().ContainsKey(requiredTag))</span><br><span class="line">                &#123;</span><br><span class="line">                    Annotations.Of(node).AddError(<span class="string">$&quot;Missing required tag <span class="subst">&#123;requiredTag&#125;</span> on stack with id <span class="subst">&#123;stack.StackName&#125;</span>&quot;</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>But when I ran CDK synth I got this error</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Unhandled exception. System.ArgumentException: Could not convert argument <span class="string">&#x27;DeployLambda.TagAspect&#x27;</span> to Jsii (Parameter <span class="string">&#x27;arguments&#x27;</span>)</span><br><span class="line">   at Amazon.JSII.Runtime.Deputy.DeputyBase.&lt;&gt;c__DisplayClass20_0.&lt;ConvertArguments&gt;b__0(Parameter parameter, Object frameworkArgument)</span><br></pre></td></tr></table></figure><p>After a bit of Googling I found there is a <a href="https://github.com/aws/jsii/issues/1029">known issue</a> with an easy fix.  You just need to make sure the aspect class inherites from <code>Amazon.Jsii.Runtime.Deputy.DeputyBase</code></p><p>The working code is</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">TagAspect</span> : <span class="title">Amazon.JSII.Runtime.Deputy.DeputyBase</span>, <span class="title">IAspect</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">readonly</span> IList&lt;<span class="built_in">string</span>&gt; _requiredTags;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">TagAspect</span>(<span class="params">IList&lt;<span class="built_in">string</span>&gt; requiredTags</span>)</span></span><br><span class="line">    &#123;</span><br><span class="line">        _requiredTags = requiredTags;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">Visit</span>(<span class="params">IConstruct node</span>)</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span> (node <span class="keyword">is</span> Stack stack)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">foreach</span> (<span class="keyword">var</span> requiredTag <span class="keyword">in</span> _requiredTags)</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="keyword">if</span> (!stack.Tags.TagValues().ContainsKey(requiredTag))</span><br><span class="line">                &#123;</span><br><span class="line">                    Annotations.Of(node).AddError(<span class="string">$&quot;Missing required tag <span class="subst">&#123;requiredTag&#125;</span> on stack with id <span class="subst">&#123;stack.StackName&#125;</span>&quot;</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>You wire this in to the <code>program.cs</code> </p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Aspects.Of(app).Add(<span class="keyword">new</span> TagAspect(<span class="keyword">new</span> List&lt;<span class="built_in">string</span>&gt;&#123;<span class="string">&quot;owner&quot;</span>&#125;));</span><br></pre></td></tr></table></figure><p>Which gives this error is we don’t have a owner tag set</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[Error at /lambda-pipeline] Missing required tag owner on stack with <span class="built_in">id</span> lambda-pipeline</span><br><span class="line">Found errors</span><br></pre></td></tr></table></figure><p><a href="https://github.com/DionBrNz/LambaCdkPipeline/tree/aspect">Excample code</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;I recently stumbled across CDK Aspects on the &lt;a href=&quot;https://blog.beachgeek.co.uk/newsletter/aws-open-source-news-and-updates-98/&quot;&gt;AWS </summary>
      
    
    
    
    
    <category term="AWS" scheme="https://todothinkofname.net/tags/AWS/"/>
    
    <category term="CDK" scheme="https://todothinkofname.net/tags/CDK/"/>
    
    <category term="C#" scheme="https://todothinkofname.net/tags/C/"/>
    
  </entry>
  
  <entry>
    <title>C# Lambda With CDK Pipelines</title>
    <link href="https://todothinkofname.net/2022/01/31/C-Lambda-with-CDK-Pipelines/"/>
    <id>https://todothinkofname.net/2022/01/31/C-Lambda-with-CDK-Pipelines/</id>
    <published>2022-01-31T01:56:54.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>For a while a colleague and myself have been trying to figure out how to get a .Net lambda deployed using CDK pipelines.  Unfortunately, the AWS documentation only shows how to write the pipeline in C# to deploy a Node lambda. If anyone from AWS is reading this, that isn’t a very useful example, if you are using C# for your pipeline, it is very likely that you will also want to deploy a lambda written in C#.</p><p>There was a new feature added to CDK in 2020 called <a href="https://aws.amazon.com/blogs/devops/building-apps-with-aws-cdk/">bundling</a> which seems to now be the correct way for deploying lambdas via CDK.  With bunding CDK downloads an AWS container, map the source folder to that container, I then use <code>dotnet publish</code> which builds the code in the container.  The output from the the .Net publish command is put in the containers <code>/asset-output</code> folder.  This is used by the pipeline to get the compiled code.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">IEnumerable&lt;<span class="built_in">string</span>&gt; commands = <span class="keyword">new</span>[]</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;cd /asset-input&quot;</span>,</span><br><span class="line">    <span class="string">&quot;dotnet publish -c Release -r linux-arm64 -p:PublishReadyToRun=true -o /asset-output&quot;</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> function = <span class="keyword">new</span> Function(<span class="keyword">this</span>, <span class="string">&quot;example-lambda&quot;</span>, <span class="keyword">new</span> FunctionProps</span><br><span class="line">&#123;</span><br><span class="line">    FunctionName = <span class="string">&quot;ToUpper-Lambda&quot;</span>,</span><br><span class="line">    Description = <span class="string">&quot;Changes input to upper case&quot;</span>,</span><br><span class="line">    Runtime = Runtime.DOTNET_CORE_3_1,</span><br><span class="line">    Handler = <span class="string">&quot;ExampleLambda::ExampleLambda.Function::FunctionHandler&quot;</span>,</span><br><span class="line">    Architecture = Architecture.ARM_64,</span><br><span class="line">    Code = Code.FromAsset(<span class="string">&quot;./ExampleLambda/&quot;</span>, <span class="keyword">new</span> AssetOptions</span><br><span class="line">    &#123;</span><br><span class="line">        Bundling = <span class="keyword">new</span> BundlingOptions</span><br><span class="line">        &#123;</span><br><span class="line">            Image = Runtime.DOTNET_CORE_3_1.BundlingImage,</span><br><span class="line">            Command = <span class="keyword">new</span> []</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="string">&quot;bash&quot;</span>, <span class="string">&quot;-c&quot;</span>, <span class="built_in">string</span>.Join(<span class="string">&quot; &amp;&amp; &quot;</span>, commands)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Once you have the lambda stack set up, create a stage for the lambda deployment. When this is added to the pipeline you will notice that an Assets stage is added to the pipeline.<br><img src="/images/lambda-pipeline.png" alt="Assets"></p><p>The other thing you need to do is make sure the step that <code>synth</code> stack is run in a <code>CodeBuildStep</code>, not a <code>ShellStep</code>. It also needs to be privileged as this is the step that will build the lambda code inside a container as well <code>synth</code> the stack.</p><p>When you run the pipeline you will see the lambda is built in the build stage, then the lambda is taken from the build assets and moved into it’s one asset&#x2F;s3 key so that it can be passed to the cloudformation stack that cdk creates.</p><p>I’ve put the full example on <a href="https://github.com/DionBrNz/LambaCdkPipeline/tree/cdk-pipeline">Github</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;For a while a colleague and myself have been trying to figure out how to get a .Net lambda deployed using CDK pipelines.  Unfortunately, </summary>
      
    
    
    
    
    <category term="AWS" scheme="https://todothinkofname.net/tags/AWS/"/>
    
    <category term="CDK" scheme="https://todothinkofname.net/tags/CDK/"/>
    
    <category term="C#" scheme="https://todothinkofname.net/tags/C/"/>
    
    <category term="Lambda" scheme="https://todothinkofname.net/tags/Lambda/"/>
    
  </entry>
  
  <entry>
    <title>Codespaces With AWS</title>
    <link href="https://todothinkofname.net/2021/07/11/Codespaces-with-AWS/"/>
    <id>https://todothinkofname.net/2021/07/11/Codespaces-with-AWS/</id>
    <published>2021-07-11T04:07:39.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>I’ve been going through the excellent <a href="https://appsyncmasterclass.com/">AppSync Masterclass</a> by Yan Cui. During the course I wanted to give GitHub Codespaces a try.</p><p>While Codespaces will correctly start a container with the the required node tools it doesn’t have the AWS cli which is needed for deployments from the <a href="https://www.serverless.com/">Serverless framework</a>. It tuns out the fix is quite simple and the Github <a href="https://docs.github.com/en/codespaces/setting-up-your-codespace/configuring-codespaces-for-your-project">documenation covers</a> a lot of what you need. </p><p>The main part of it is you need to create a <code>.devcontainer</code> folder in your repo.  Inside this folder you need a Docker file and a <code>devcontainer.json</code> file (Notice there is no . in the file name only in the folder name). Github has a <a href="https://github.com/microsoft/vscode-dev-containers/tree/main/containers">repo</a> with the base conatiners for the language you are using.</p><p>I used the Node container and created this Dockerfile.</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ARG</span> VARIANT=<span class="number">16</span></span><br><span class="line"><span class="keyword">FROM</span> mcr.microsoft.com/vscode/devcontainers/javascript-node:$&#123;VARIANT&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> curl <span class="string">&quot;https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip&quot;</span> -o <span class="string">&quot;awscliv2.zip&quot;</span> &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">        unzip awscliv2.zip &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">        sudo ./aws/install</span></span><br></pre></td></tr></table></figure><p>The devcontainer.json just contains</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Node.js&quot;</span><span class="punctuation">,</span></span><br><span class="line"><span class="attr">&quot;build&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line"><span class="attr">&quot;dockerfile&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Dockerfile&quot;</span><span class="punctuation">,</span></span><br><span class="line"><span class="comment">// Update &#x27;VARIANT&#x27; to pick a Node version: 12, 14, 16</span></span><br><span class="line"><span class="attr">&quot;args&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;VARIANT&quot;</span><span class="punctuation">:</span> <span class="string">&quot;16&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>Which is just copied from the GitHub template.</p><p>The next bit was I didn’t really want to store my credenitals in the container and GitHub and <a href="https://docs.github.com/en/codespaces/managing-your-codespaces/managing-encrypted-secrets-for-your-codespaces">thought of that</a>. I created to variables <code>AWS_ACCESS_KEY_ID</code> and <code>AWS_SECRET_ACCESS_KEY</code> with my credentials from AWS.<br><img src="/images/codespace-secrets.png" alt="CodeSpaces secrets"></p><p>The last thing was rebuilding the CodeSpace and Restarting it, both of wich you do in VSCode from the command pallet.<br><img src="/images/rebuild.png" alt="Rebuild"></p><p>After that try the aws cli.<br><img src="/images/aws-cli.png" alt="AWS Cli"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;I’ve been going through the excellent &lt;a href=&quot;https://appsyncmasterclass.com/&quot;&gt;AppSync Masterclass&lt;/a&gt; by Yan Cui. During the course I w</summary>
      
    
    
    
    
    <category term="AWS" scheme="https://todothinkofname.net/tags/AWS/"/>
    
    <category term="Codespaces" scheme="https://todothinkofname.net/tags/Codespaces/"/>
    
  </entry>
  
  <entry>
    <title>File Watchers and Inotify Instances Has Been Reached</title>
    <link href="https://todothinkofname.net/2020/12/15/File-watchers-and-inotify-instances-has-been-reached/"/>
    <id>https://todothinkofname.net/2020/12/15/File-watchers-and-inotify-instances-has-been-reached/</id>
    <published>2020-12-15T11:00:00.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>During a recent production deployment of one of our applications we had an issue where containers started rolling, this was very odd as the same container had just deployed successfully to our canary environment. After the initial panic, the deployment was cancelled, and old containers started up again, panic over. Now what the heck happened?</p><p>Checking the logs, we had started getting this error.</p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">System.IO.IOException: <span class="function">The configured user <span class="title">limit</span> (<span class="params"><span class="number">128</span></span>) <span class="keyword">on</span> the number of inotify instances has been reached, <span class="keyword">or</span> the per-process limit <span class="keyword">on</span> the number of open file descriptors has been reached.</span></span><br><span class="line"><span class="function">   at System.IO.FileSystemWatcher.<span class="title">StartRaisingEvents</span>()</span></span><br><span class="line"><span class="function">   at Microsoft.Extensions.FileProviders.Physical.PhysicalFilesWatcher.<span class="title">TryEnableFileSystemWatcher</span>()</span></span><br><span class="line"><span class="function">   at Microsoft.Extensions.FileProviders.Physical.PhysicalFilesWatcher.<span class="title">CreateFileChangeToken</span>(<span class="params">String filter</span>)</span></span><br><span class="line"><span class="function">   at Microsoft.Extensions.Primitives.ChangeToken.<span class="title">OnChange</span>(<span class="params">Func`<span class="number">1</span> changeTokenProducer, Action changeTokenConsumer</span>)</span></span><br><span class="line"><span class="function">   at Microsoft.Extensions.Configuration.FileConfigurationProvider..<span class="title">ctor</span>(<span class="params">FileConfigurationSource source</span>)</span></span><br><span class="line"><span class="function">   at Microsoft.Extensions.Configuration.Json.JsonConfigurationSource.<span class="title">Build</span>(<span class="params">IConfigurationBuilder builder</span>)</span></span><br><span class="line"><span class="function">   at Microsoft.Extensions.Configuration.ConfigurationBuilder.<span class="title">Build</span>()</span></span><br><span class="line"><span class="function">   at Microsoft.Extensions.Configuration.SystemsManagerExtensions.<span class="title">GetAwsOptions</span>(<span class="params">IConfigurationBuilder builder</span>)</span></span><br><span class="line"><span class="function">   at Microsoft.Extensions.Configuration.SystemsManagerExtensions.<span class="title">AddSystemsManager</span>(<span class="params">IConfigurationBuilder builder, Action`<span class="number">1</span> configureSource</span>)</span></span><br></pre></td></tr></table></figure><p>The other thing that had changed was that due to having to encrypt the clusters EBS volumes we had used this as an opportunity to upgrade the version of Linux the cluster was using.</p><p>After a little bit of Googling this appeared to be due to the reloadOnChange flag being set to true when adding our Json config files.  Since we are running this in a container and containers are immutable it seemed to be an easy fix, just set reloadOnChange to false. </p><p>When we deployed the updated version, we ended up with the same exception, from the call stack it appeared that .Net was ignoring the value of the flag. Very confusing 😕. </p><p>I ended up debugging into the Microsoft code to see what was going on and found that we were using Host.CreateDefaultBuilder adds the config files itself with reload on change set to true as you can see in the code snippet below.</p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">builder.ConfigureAppConfiguration((hostingContext, config) =&gt;</span><br><span class="line">&#123;</span><br><span class="line">    IHostEnvironment env = hostingContext.HostingEnvironment;</span><br><span class="line"> </span><br><span class="line">    <span class="built_in">bool</span> reloadOnChange = hostingContext.Configuration.GetValue(<span class="string">&quot;hostBuilder:reloadConfigOnChange&quot;</span>, defaultValue: <span class="literal">true</span>);</span><br><span class="line"> </span><br><span class="line">    config.AddJsonFile(<span class="string">&quot;appsettings.json&quot;</span>, optional: <span class="literal">true</span>, reloadOnChange: reloadOnChange)</span><br><span class="line">            .AddJsonFile(<span class="string">$&quot;appsettings.<span class="subst">&#123;env.EnvironmentName&#125;</span>.json&quot;</span>, optional: <span class="literal">true</span>, reloadOnChange: reloadOnChange);</span><br></pre></td></tr></table></figure><p><a href="https://github.com/dotnet/runtime/blob/v5.0.1/src/libraries/Microsoft.Extensions.Hosting/src/Host.cs#L76">Link to this code on MS GitHub </a></p><p>Microsoft was setting up the Json config files as well as our code, and theirs was defaulting to reloadOnChange. This call is pointless in our solution as we are then doing all this set up ourselves. If you read the rest of the CreateDefaultBuilder file there is stuff in there we don’t use and stuff we end up replacing, so why are we using it?</p><p>The fix was easy, change Host.CreateDefaultBuilder to new HostBuilder. Digging into the history of Host.CreateDefaultBuilder (thanks MS for putting it on GitHub), it turns out this function has worked the same way since at least .Net core 2.0. In .Net 5 they have added a flag so you can set reloadOnChange to false, but as all our applications do this type of setup themselves it is pointless to us.</p><p>The learnings from this are to check what sample code does, given that all the source for .Net core&#x2F;.Net 5 is one GitHub check what the MS calls are doing. From what found it appears that we have been doing our set up wrong for a while as we end up duplicating a lot of what is in Host.CreateDefaultBuilder. Going forward I’ll be using new HostBuilder, unless I’m doing a simple app that only needs what is in Host.CreateDefaultBuilder.</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;During a recent production deployment of one of our applications we had an issue where containers started rolling, this was very odd as t</summary>
      
    
    
    
    
    <category term="AWS" scheme="https://todothinkofname.net/tags/AWS/"/>
    
    <category term="asp.net core" scheme="https://todothinkofname.net/tags/asp-net-core/"/>
    
    <category term="ecs" scheme="https://todothinkofname.net/tags/ecs/"/>
    
  </entry>
  
  <entry>
    <title>Solution Architect Professional Recertification</title>
    <link href="https://todothinkofname.net/2020/06/26/Recertification/"/>
    <id>https://todothinkofname.net/2020/06/26/Recertification/</id>
    <published>2020-06-26T06:50:00.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>It’s been 3 years already and I had to resit my Architect professional exam.  This time I used the online option to do it from home which was an interesting experience. </p><p><a href="https://www.youracclaim.com/badges/4a701683-e370-4dfd-b3e8-918862bfa6d7/public_url">Anyway, I passed and am certified for another 3 years.</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;It’s been 3 years already and I had to resit my Architect professional exam.  This time I used the online option to do it from home which</summary>
      
    
    
    
    
    <category term="AWS" scheme="https://todothinkofname.net/tags/AWS/"/>
    
  </entry>
  
  <entry>
    <title>OpenTelemetry</title>
    <link href="https://todothinkofname.net/2020/04/21/OpenTelemetry/"/>
    <id>https://todothinkofname.net/2020/04/21/OpenTelemetry/</id>
    <published>2020-04-21T02:07:06.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="What-is-OpenTelemetry"><a href="#What-is-OpenTelemetry" class="headerlink" title="What is OpenTelemetry?"></a>What is OpenTelemetry?</h2><p>From the <a href="https://cloudblogs.microsoft.com/opensource/2019/05/23/announcing-opentelemetry-cncf-merged-opencensus-opentracing/">Microsoft blog</a></p><p><em>“OpenTelemetry is created as a merger of the OpenCensus and OpenTracing projects. This project aspires to make robust, portable telemetry a built-in feature of any software. It allows you to collect low-overhead telemetry from the entirety of a modern software stack.”</em></p><p>I originally saw mention of OpenTelemetry on the ASP.Net core blog and then this month Jimmy Bogard started twitting about a project he was playing with, some of which he has blogged and appears to be an on going series. This got me interested in having another look at it.</p><h2 id="What-does-it-offer-us"><a href="#What-does-it-offer-us" class="headerlink" title="What does it offer us"></a>What does it offer us</h2><p>In short OpenTelemery allows us a consistent way of adding end-to-end diagnostics and tracing to an application, extracting away the system we are using to visualise this information. Currently there is a Alpha library for .Net <a href="https://github.com/open-telemetry/opentelemetry-dotnet">https://github.com/open-telemetry/opentelemetry-dotnet</a> which should be moving to beta shortly.</p><p>I don’t have a full example, I’ll leave that up to Jimmy as he will do a much better job, but I have some highlights below.</p><p>To configure OprnTelemetry for NewRelic we would configure it like this</p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">services.AddOpenTelemetry((sp, builder) =&gt;</span><br><span class="line">    &#123;</span><br><span class="line">        builder</span><br><span class="line">          <span class="comment">//.SetSampler(Samplers.AlwaysSample)</span></span><br><span class="line">          .UseNewRelic(<span class="keyword">this</span>.Configuration)</span><br><span class="line">          .AddRequestCollector()</span><br><span class="line">          .AddDependencyCollector();</span><br><span class="line">     &#125;);</span><br></pre></td></tr></table></figure><p><a href="https://github.com/newrelic/newrelic-telemetry-sdk-dotnet">NewRelic have their own library</a> for OpenTelemetry.</p><p>AWS are starting to look at OpenTelemetry for XRay as well, but only Java so far :sad:. </p><h2 id="Wrap-up"><a href="#Wrap-up" class="headerlink" title="Wrap up"></a>Wrap up</h2><p>I feel this is something that is worth keeping an eye on. It seems to have good support from vendors and is supported by the <a href="https://opentelemetry.io/">Cloud Native Computing Foundation</a>.</p><p>If we had this when we switched from DataDog the migration would have been as simple as changing .UseDataDog to .UseNewRelic.</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;What-is-OpenTelemetry&quot;&gt;&lt;a href=&quot;#What-is-OpenTelemetry&quot; class=&quot;headerlink&quot; title=&quot;What is OpenTelemetry?&quot;&gt;&lt;/a&gt;What is OpenTelemetry?</summary>
      
    
    
    
    
    <category term="OpenTelemetry" scheme="https://todothinkofname.net/tags/OpenTelemetry/"/>
    
  </entry>
  
  <entry>
    <title>Git Hooks</title>
    <link href="https://todothinkofname.net/2019/03/15/Git-Hooks/"/>
    <id>https://todothinkofname.net/2019/03/15/Git-Hooks/</id>
    <published>2019-03-15T01:51:23.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>Recently I started having a poke around with <a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks">Git Hook</a>. The main reason for looking in to this is becuase I have a bad memory and I am always forgetting to run the unit tests before creating pushing to Github and creating a PR.  </p><p>It turned out to be really easy to set up. All I needed to do was place a <code>pre-push</code> file into the projects <code>.git/hooks</code> folder. </p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dotnet <span class="built_in">test</span> ./src/project.sln</span><br></pre></td></tr></table></figure><p>So now when a do a push from the shell </p><p><img src="/images/push.png"></p><p>I also use the git client built in to Visual Stuido. This also seems to respect the hooks although it doesn’t give feed back on progress.</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Recently I started having a poke around with &lt;a href=&quot;https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks&quot;&gt;Git Hook&lt;/a&gt;. The main re</summary>
      
    
    
    
    
    <category term="Git" scheme="https://todothinkofname.net/tags/Git/"/>
    
  </entry>
  
  <entry>
    <title>CloudFront and SSL</title>
    <link href="https://todothinkofname.net/2018/09/08/Cloudfront-and-SSL/"/>
    <id>https://todothinkofname.net/2018/09/08/Cloudfront-and-SSL/</id>
    <published>2018-09-08T01:53:25.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>With Chrome starting to flag sites that don’t support TLS I thought i was about time I set my blog up to be served over TLS.</p><p>Since this site is hosted in S3 it was pretty much a matter of following the AWS documentation.  The only issue I had was configuring Route53 where the documentation is a little lacking.  </p><p>In Route53 when you set up the Alias record you set the target to the DNS name of your CloudFront distribution. The appears to only be need is you already have your S3 bucket set up for static site hosting. </p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;With Chrome starting to flag sites that don’t support TLS I thought i was about time I set my blog up to be served over TLS.&lt;/p&gt;
&lt;p&gt;Since</summary>
      
    
    
    
    
    <category term="AWS, CloudFront" scheme="https://todothinkofname.net/tags/AWS-CloudFront/"/>
    
  </entry>
  
  <entry>
    <title>SSH on Windows 10</title>
    <link href="https://todothinkofname.net/2018/09/02/SSH-on-Windows-10/"/>
    <id>https://todothinkofname.net/2018/09/02/SSH-on-Windows-10/</id>
    <published>2018-09-02T01:33:13.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>As I’ve been doing my AWS training I’ve needed to SSH in Linux machines quite often for tutorials.  Every time the videos for these tutorials have said to use PUTTY when using Windows which I hate.</p><p>Windows 10 has had a bash shell for a while now, which I have been using for SSH and which works very well.  What some people may not be aware of is that Microsoft added a full native OpenSSH client to the Windows 10 2018 spring update.</p><p>To use it you need to enable the Windows feature. You do this bu going into settings and searching for features and selecting “Manage Optional Features”.<br><img src="/images/features.PNG" alt="Windows 10 Optional Features"><br>Click the + button at the top and find OpenSSH Client in the list and click install.  That’s it you now have a ssh client that you can run from Powershell or CMD.<br><img src="/images/ssh.png" alt="Windows 10 SSH"></p><p>The last thing you might need to do is if your private key is password protected and you want to add it to the ssh-agent.  </p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Get-Service</span> ssh<span class="literal">-agent</span></span><br><span class="line"></span><br><span class="line">Status   Name               DisplayName</span><br><span class="line"><span class="literal">------</span>   <span class="literal">----</span>               <span class="literal">-----------</span></span><br><span class="line">Stopped  ssh<span class="literal">-agent</span>          OpenSSH Authentication Agent</span><br><span class="line"></span><br><span class="line"><span class="built_in">Start-Service</span> ssh<span class="literal">-agent</span></span><br><span class="line"></span><br><span class="line">Status   Name               DisplayName</span><br><span class="line"><span class="literal">------</span>   <span class="literal">----</span>               <span class="literal">-----------</span></span><br><span class="line">Running  ssh<span class="literal">-agent</span>          OpenSSH Authentication Agent</span><br><span class="line"></span><br><span class="line">ssh<span class="literal">-add</span> id_rsa</span><br></pre></td></tr></table></figure><p>All done, you can now use OpenSSH for you Git client as well as logging into Linux machines.</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;As I’ve been doing my AWS training I’ve needed to SSH in Linux machines quite often for tutorials.  Every time the videos for these tutor</summary>
      
    
    
    
    
    <category term="ssh Windows10" scheme="https://todothinkofname.net/tags/ssh-Windows10/"/>
    
  </entry>
  
  <entry>
    <title>Exams</title>
    <link href="https://todothinkofname.net/2016/09/25/exams/"/>
    <id>https://todothinkofname.net/2016/09/25/exams/</id>
    <published>2016-09-25T05:44:40.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>I’ve passed my last AWS associate exam this week.  Next year in on to one of the professional exam.  Hopefully now I’ll have a bit more time for the blog.</p><p>The last part of my Alexa blog as been <a href="https://devblog.xero.com/talking-to-the-xero-api-part-3-8cf02e7b0174">posted</a>.</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;I’ve passed my last AWS associate exam this week.  Next year in on to one of the professional exam.  Hopefully now I’ll have a bit more t</summary>
      
    
    
    
    
    <category term="AWS, Alexa" scheme="https://todothinkofname.net/tags/AWS-Alexa/"/>
    
  </entry>
  
  <entry>
    <title>AWShine</title>
    <link href="https://todothinkofname.net/2016/07/04/AWShine/"/>
    <id>https://todothinkofname.net/2016/07/04/AWShine/</id>
    <published>2016-07-04T08:39:24.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>I just wanted to say a big thank you to AWS for the AWShine event they held in Auckland last week.  It was a lot of fun.</p><p>Thanks for the Echo I just have to figure out how to program it now.</p><p><img src="/images/AWShine.jpg"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;I just wanted to say a big thank you to AWS for the AWShine event they held in Auckland last week.  It was a lot of fun.&lt;/p&gt;
&lt;p&gt;Thanks fo</summary>
      
    
    
    
    
    <category term="AWS" scheme="https://todothinkofname.net/tags/AWS/"/>
    
  </entry>
  
  <entry>
    <title>Dapper With .Net Core</title>
    <link href="https://todothinkofname.net/2016/05/30/Dapper-with-Net-core/"/>
    <id>https://todothinkofname.net/2016/05/30/Dapper-with-Net-core/</id>
    <published>2016-05-30T02:07:06.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>I’ve been looking at converting one of our existing WebApi site to ASP.Net core.  One issue that I found is that we us Table Value Parameters (TVP) in our sql server stored procedures.</p><p>In .Net 4.6 Dapper uses DataTables and the .AsTableValuedParameter helper method.  DataTables don’t exist in .Net core which means that we have an issue.</p><p>What I found is that you can go back to what appears to be the original way that Dapper supported TVPs and create a class that implements IDaynamicParameters.</p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">EmailAddressesParameter</span> : <span class="title">SqlMapper.IDynamicParameters</span></span><br><span class="line">  &#123;</span><br><span class="line">      <span class="keyword">private</span> <span class="keyword">readonly</span> IEnumerable&lt;<span class="built_in">string</span>&gt; _emailAddresses;</span><br><span class="line"></span><br><span class="line">      <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;summary&gt;</span>Initializes a new instance of the</span></span><br><span class="line">      <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;see cref=&quot;T:System.Object&quot; /&gt;</span> class.<span class="doctag">&lt;/summary&gt;</span></span></span><br><span class="line">      <span class="function"><span class="keyword">public</span> <span class="title">EmailAddressesParameter</span>(<span class="params">IEnumerable&lt;<span class="built_in">string</span>&gt; emailAddresses</span>)</span></span><br><span class="line">      &#123;</span><br><span class="line">          _emailAddresses = emailAddresses;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;summary&gt;</span></span></span><br><span class="line">      <span class="comment"><span class="doctag">///</span> Add all the parameters needed to the command just before it executes</span></span><br><span class="line">      <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;/summary&gt;</span></span></span><br><span class="line">      <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;param name=&quot;command&quot;&gt;</span>The raw command prior to execution<span class="doctag">&lt;/param&gt;</span></span></span><br><span class="line">      <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;param name=&quot;identity&quot;&gt;</span>Information about the query<span class="doctag">&lt;/param&gt;</span></span></span><br><span class="line">      <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">AddParameters</span>(<span class="params">IDbCommand command, SqlMapper.Identity identity</span>)</span></span><br><span class="line">      &#123;</span><br><span class="line">          <span class="keyword">var</span> sqlCommand = (SqlCommand) command;</span><br><span class="line">          sqlCommand.CommandType = CommandType.StoredProcedure;</span><br><span class="line">          <span class="keyword">var</span> items = <span class="keyword">new</span> List&lt;SqlDataRecord&gt;();</span><br><span class="line"></span><br><span class="line">          <span class="keyword">foreach</span> (<span class="keyword">var</span> emailAddress <span class="keyword">in</span> _emailAddresses)</span><br><span class="line">          &#123;</span><br><span class="line">              <span class="keyword">var</span> rec = <span class="keyword">new</span> SqlDataRecord(<span class="keyword">new</span> SqlMetaData(<span class="string">&quot;EmailAddress&quot;</span>,</span><br><span class="line">                SqlDbType.NVarChar, <span class="number">100</span>));</span><br><span class="line">              rec.SetString(<span class="number">0</span>, emailAddress);</span><br><span class="line">              items.Add(rec);</span><br><span class="line">          &#125;</span><br><span class="line"></span><br><span class="line">          <span class="keyword">var</span> p = sqlCommand.Parameters.Add(<span class="string">&quot;@emailAddress&quot;</span>, SqlDbType.Structured);</span><br><span class="line">          p.Direction = ParameterDirection.Input;</span><br><span class="line">          p.TypeName = <span class="string">&quot;EmailTableType&quot;</span>;</span><br><span class="line">          p.Value = items;</span><br><span class="line">      &#125;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure><p>Then you call it like this.</p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">using</span> (<span class="keyword">var</span> connection = <span class="keyword">new</span> SqlConnection(connectionString))</span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">var</span> parameters = <span class="keyword">new</span> EmailAddressesParameter(<span class="keyword">new</span> List&lt;<span class="built_in">string</span>&gt;() &#123; <span class="string">&quot;test@test.com&quot;</span> &#125;);</span><br><span class="line">  connection.Execute(<span class="string">&quot;test&quot;</span>, parameters);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>It has a slight downside that you need to create a new class for each TVP you use.  I don’t think that is too big of a deal as it would be a one time set up.</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;I’ve been looking at converting one of our existing WebApi site to ASP.Net core.  One issue that I found is that we us Table Value Parame</summary>
      
    
    
    
    
    <category term="asp.net core" scheme="https://todothinkofname.net/tags/asp-net-core/"/>
    
    <category term="dapper" scheme="https://todothinkofname.net/tags/dapper/"/>
    
  </entry>
  
  <entry>
    <title>Odd Error Redirecting on Linux</title>
    <link href="https://todothinkofname.net/2016/05/11/Odd-error-redirecting-on-Linux-1/"/>
    <id>https://todothinkofname.net/2016/05/11/Odd-error-redirecting-on-Linux-1/</id>
    <published>2016-05-11T03:42:56.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>We have automatic tests that run over our website using <a href="http://docs.seleniumhq.org/">Selenium</a>.</p><p>For some reason these tests stated failing on from our build server where they where working locally.  The issue was where we had a post back from an external site, when the request hit our site it was getting a 404 error.  </p><p>So I started looking at what was different between our local machines and what the build server was using. On our local machines we run a Selenium hub locally, but the build server users a server which turned out to be running Linux.</p><p>Having found that I set up a Linux VM so I could see Chrome running. So watching the test what I saw was this<br><img src="/images/Error.jpg"><br>This was very odd as the route did exist and it worked fine when running on Windows.</p><p>Digging into the code one thing I did notice was that we weren’t defining the scheme on the URL when constructing the call back URL. I added the scheme to the url and it started working.</p><p>So it appears while Chrome on Windows was able to infer the scheme, Chrome on Linux needed it explicitly defined.</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;We have automatic tests that run over our website using &lt;a href=&quot;http://docs.seleniumhq.org/&quot;&gt;Selenium&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For some reason these </summary>
      
    
    
    
    
    <category term="ASP.NET" scheme="https://todothinkofname.net/tags/ASP-NET/"/>
    
    <category term="Linux" scheme="https://todothinkofname.net/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>WebApi - Binding to Header Values</title>
    <link href="https://todothinkofname.net/2016/05/08/WebApi-Binding-to-header-values/"/>
    <id>https://todothinkofname.net/2016/05/08/WebApi-Binding-to-header-values/</id>
    <published>2016-05-08T22:41:53.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>We have a WebApi project at work where we need to get a value from the header and use it as input to a query.</p><p>One way to do this is</p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> IActionResult <span class="title">DoSomething</span>()</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">var</span> headerValues = request.Headers.GetValues(<span class="string">&quot;MyHeader&quot;</span>);</span><br><span class="line">  <span class="keyword">var</span> header = headerValues.FirstOrDefault();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>YUCK.</p><p>I wasn’t very keen on this and starting think it must be possible to use WebApi’s model binding.  After a bit of searching I found <a href="https://blog.bennymichielsen.be/2013/11/17/modelbinding-with-headers-in-asp-net-webapi/trackback/">https://blog.bennymichielsen.be/2013/11/17/modelbinding-with-headers-in-asp-net-webapi/</a> which gave me most of<br>the details.  This left me with model binding working, but not quite in the way I wanted.</p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> IActionResult <span class="title">DoSomething</span>(<span class="params">[ValueProvider(<span class="keyword">typeof</span>(HeaderValue</span>))] <span class="built_in">int</span> custId)</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="comment">//Do something with custId</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Better, but not quite what I wanted.</p><p>In trying to fill in a few of the missing pieces I had a look at the WebApi code on GitHub and found that in one of their <a href="https://github.com/ASP-NET-MVC/aspnetwebstack/blob/4e40cdef9c8a8226685f95ef03b746bc8322aa92/test/System.Web.Http.Integration.Test/ModelBinding/ModelBindingController.cs#L271">Integration tests</a> Microsoft had pretty much exactly what I was after.</p><p>So between the two I was able to put together something I was happy with.</p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">HeaderValueProviderFactory</span> : <span class="title">ValueProviderFactory</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;summary&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span>     Gets the value provider.</span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;/summary&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;param name=&quot;actionContext&quot;&gt;</span>The action context.<span class="doctag">&lt;/param&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;returns&gt;</span><span class="doctag">&lt;/returns&gt;</span></span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">override</span> IValueProvider <span class="title">GetValueProvider</span>(<span class="params">HttpActionContext actionContext</span>)</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> HeaderValueProvider(actionContext.Request);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;summary&gt;</span></span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> Returns the tenant id from the request header.</span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> http://blog.bennymichielsen.be/2013/11/17/modelbinding-with-headers-in-asp-net-webapi/</span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> also some ideas from the ASP.NET unit tests</span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> https://github.com/ASP-NET-MVC/aspnetwebstack/blob/4e40cdef9c8a8226685f95ef03b746bc8322aa92/test/System.Web.Http.Integration.Test/ModelBinding/ModelBindingController.cs#L271</span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;/summary&gt;</span></span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">HeaderValueProvider</span> : <span class="title">IValueProvider</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">readonly</span> HttpRequestMessage _requestMessage;</span><br><span class="line"></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;summary&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> Initializes a new instance of the <span class="doctag">&lt;see cref=&quot;HeaderValueProvider&quot;/&gt;</span> class.</span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;/summary&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;param name=&quot;requestMessage&quot;&gt;</span>The request message.<span class="doctag">&lt;/param&gt;</span></span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">HeaderValueProvider</span>(<span class="params">HttpRequestMessage requestMessage</span>)</span></span><br><span class="line">    &#123;</span><br><span class="line">        _requestMessage = requestMessage;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;summary&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> Determines whether the specified prefix contains prefix.</span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;/summary&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;param name=&quot;prefix&quot;&gt;</span>The prefix.<span class="doctag">&lt;/param&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;returns&gt;</span><span class="doctag">&lt;/returns&gt;</span></span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="built_in">bool</span> <span class="title">ContainsPrefix</span>(<span class="params"><span class="built_in">string</span> prefix</span>)</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> _requestMessage.Headers.Contains(prefix);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;summary&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> Gets the value.</span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;/summary&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;param name=&quot;key&quot;&gt;</span>The key.<span class="doctag">&lt;/param&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;returns&gt;</span><span class="doctag">&lt;/returns&gt;</span></span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ValueProviderResult <span class="title">GetValue</span>(<span class="params"><span class="built_in">string</span> key</span>)</span></span><br><span class="line">    &#123;</span><br><span class="line">        IEnumerable&lt;<span class="built_in">string</span>&gt; headerValue;</span><br><span class="line">        ValueProviderResult result = <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">if</span> (_requestMessage.Headers.TryGetValues(key, <span class="keyword">out</span> headerValue))</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">var</span> header = headerValue <span class="keyword">as</span> IList&lt;<span class="built_in">string</span>&gt; ?? headerValue.ToList();</span><br><span class="line">            <span class="keyword">if</span> (header.Any())</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="keyword">var</span> <span class="keyword">value</span> = header.First();</span><br><span class="line">                result = <span class="keyword">new</span> ValueProviderResult(<span class="keyword">value</span>, <span class="keyword">value</span>, CultureInfo.InvariantCulture);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">[<span class="meta">AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)</span>]</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">FromHeaderAttribute</span> : <span class="title">ModelBinderAttribute</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;summary&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> Gets the value providers that will be fed to the model binder.</span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;/summary&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;returns&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> A collection of <span class="doctag">&lt;see cref=&quot;T:System.Web.Http.ValueProviders.ValueProviderFactory&quot;/&gt;</span> instances.</span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;/returns&gt;</span></span></span><br><span class="line">    <span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;param name=&quot;configuration&quot;&gt;</span>The <span class="doctag">&lt;see cref=&quot;T:System.Web.Http.HttpConfiguration&quot;/&gt;</span> configuration object.<span class="doctag">&lt;/param&gt;</span></span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="title">IEnumerable</span>&lt;<span class="title">ValueProviderFactory</span>&gt; <span class="title">GetValueProviderFactories</span>(<span class="params">HttpConfiguration configuration</span>)</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">base</span>.GetValueProviderFactories(configuration).OfType&lt;HeaderValueProviderFactory&gt;();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title">WebApiConfig</span></span><br><span class="line"> &#123;</span><br><span class="line">     <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">Register</span>(<span class="params">HttpConfiguration config</span>)</span></span><br><span class="line">     &#123;</span><br><span class="line">         <span class="comment">// Web API configuration and services</span></span><br><span class="line">         config.Services.Add(<span class="keyword">typeof</span>(ValueProviderFactory), <span class="keyword">new</span> HeaderValueProviderFactory());</span><br><span class="line">     &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>So finally I can just do</p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> IActionResult <span class="title">DoSomething</span>(<span class="params">[FromHeader(Name=<span class="string">&quot;CustId&quot;</span></span>)] <span class="built_in">int</span> custId)</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="comment">// Do something with custId</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Much nicer.</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;We have a WebApi project at work where we need to get a value from the header and use it as input to a query.&lt;/p&gt;
&lt;p&gt;One way to do this i</summary>
      
    
    
    
    
    <category term=".Net" scheme="https://todothinkofname.net/tags/Net/"/>
    
    <category term="C#" scheme="https://todothinkofname.net/tags/C/"/>
    
    <category term="WebApi" scheme="https://todothinkofname.net/tags/WebApi/"/>
    
  </entry>
  
  <entry>
    <title>Moving Blog</title>
    <link href="https://todothinkofname.net/2016/04/25/Getting-started/"/>
    <id>https://todothinkofname.net/2016/04/25/Getting-started/</id>
    <published>2016-04-25T05:48:16.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>Since I’m doing AWS certification and need to get some more experiance with AWS I thought it would be a good idea to move my blog.  </p><p>So I’ve moved it to <a href="https://hexo.io/">Hexo</a> because I wanted a static site generator that wasn’t written in Ruby and would run on Windows. Hexo is pretty good, but I’ve some some of the plug ins need Python 2 and then need to try an compile C code which works about as bladly as it does for Ruby.</p><p>I event tried it under the new Windows 10 bash support, but I seems that node isn’t node, but is nodejs.  I need to do some more research on that.</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Since I’m doing AWS certification and need to get some more experiance with AWS I thought it would be a good idea to move my blog.  &lt;/p&gt;
</summary>
      
    
    
    
    
    <category term="AWS" scheme="https://todothinkofname.net/tags/AWS/"/>
    
  </entry>
  
  <entry>
    <title>Asp.Net User Secrets</title>
    <link href="https://todothinkofname.net/2015/07/12/Asp.Net%20user%20secrets/"/>
    <id>https://todothinkofname.net/2015/07/12/Asp.Net%20user%20secrets/</id>
    <published>2015-07-12T22:05:00.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>So I’ve been playing around with Asp.Net 5 beta 5 trying to figure out how to use some of the new configuration stuff.  Especially the user secrets stuff.  </p><p>The idea of user secrets is that you need to have some settings on you dev machine which you don’t want in source control.  Things like passwords etc.  </p><p>I’ve found the documentation some what lacking so hopefully this overview will help.  </p><p>Firstly you need to install the user-secret command. The installation instructions aren’t too bad and can be found here <a href="https://github.com/aspnet/Home/wiki/DNX-Secret-Configuration#global-tool">DNX-Secret-Configuration</a>.  </p><p>To add the user secrets  </p><p>Once I had that installed I added the userSecrestsId to my project.json, but that didn’t seem to be picked up.  </p><pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;"><span style="color: #b4b4b4;">{</span>      <span style="color: #d7ba7d;">"webroot"</span><span style="color: #b4b4b4;">:</span> <span style="color: #d69d85;">"wwwroot"</span><span style="color: #b4b4b4;">,</span>      <span style="color: #d7ba7d;">"userSecretsId"</span><span style="color: #b4b4b4;">:</span> <span style="color: #d69d85;">"aspnet5-4c570577-d4ba-491c-a56c-3f267e3d5211"</span><span style="color: #b4b4b4;">,</span>      <span style="color: #d7ba7d;">"version"</span><span style="color: #b4b4b4;">:</span> <span style="color: #d69d85;">"1.0.0-*"</span><span style="color: #b4b4b4;">,</span></pre><p>I found that I need to add this to the startup.js when I loaded the user secrets.  </p><pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;"><span style="color: #569cd6;">public</span> <span style="color: #569cd6;">class</span> <span style="color: #4ec9b0;">Startup</span>      {          <span style="color: #569cd6;">public</span> Startup(IHostingEnvironment env)          {              <span style="color: #569cd6;">var</span> builder <span style="color: #b4b4b4;">=</span> <span style="color: #569cd6;">new</span> ConfigurationBuilder();              <span style="color: #569cd6;">if</span> (env<span style="color: #b4b4b4;">.</span>IsDevelopment())              {                  builder<span style="color: #b4b4b4;">.</span>AddUserSecrets(<span style="color: #d69d85;">"aspnet5-4c570577-d4ba-491c-a56c-3f267e3d5211"</span>);              }              <span style="color: #569cd6;">else</span>              {                  builder<span style="color: #b4b4b4;">.</span>AddEnvironmentVariables();              }              Configuration <span style="color: #b4b4b4;">=</span> builder<span style="color: #b4b4b4;">.</span>Build();          }</pre><p>The next problem was figuring out how to inject these values into the controller.  What I found is you need to AddOptions in the ConfigureServices method and they Configure the class you want the values put in.  </p><pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;"><span style="color: #569cd6;">public</span> <span style="color: #569cd6;">void</span> ConfigureServices(IServiceCollection services)         {             services<span style="color: #b4b4b4;">.</span>AddMvc();             services<span style="color: #b4b4b4;">.</span>AddOptions();             services<span style="color: #b4b4b4;">.</span>Configure<span style="color: #b4b4b4;"></span>AwsOptions<span style="color: #b4b4b4;">></span>(Configuration);</pre><p>My AwsOptions class just has two string fields with the name of the secret properties I want to use.  </p><pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;"><span style="color: #569cd6;">namespace</span> <span style="color: #b4b4b4;"></span>Config  {      <span style="color: #569cd6;">public</span> <span style="color: #569cd6;">class</span> <span style="color: #4ec9b0;">AwsOptions</span>      {          <span style="color: #569cd6;">public</span> <span style="color: #569cd6;">string</span> awsAccessKey { <span style="color: #569cd6;">get</span>; <span style="color: #569cd6;">set</span>; }          <span style="color: #569cd6;">public</span> <span style="color: #569cd6;">string</span> awsSecret { <span style="color: #569cd6;">get</span>; <span style="color: #569cd6;">set</span>; }              }  }</pre><p>The ASP.NET configuration system will look for values in the Configuration object that match these name and load them into that class.  Then to get them in the controller you do the following  </p><pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;">[Route(<span style="color: #d69d85;">"api/[controller]"</span>)]  <span style="color: #569cd6;">public</span> <span style="color: #569cd6;">class</span> <span style="color: #4ec9b0;">AController</span> : Controller  {      <span style="color: #569cd6;">private</span> <span style="color: #569cd6;">readonly</span> IOptions<span style="color: #b4b4b4;"></span>AwsOptions<span style="color: #b4b4b4;">></span> _awsOptions;      <span style="color: #569cd6;">private</span> <span style="color: #569cd6;">readonly</span> ILogger<span style="color: #b4b4b4;"></span>SeverController<span style="color: #b4b4b4;">></span> _logger;      <span style="color: #569cd6;">public</span> AController(IOptions<span style="color: #b4b4b4;"></span>AwsOptions<span style="color: #b4b4b4;">></span> awsOptions, ILogger<span style="color: #b4b4b4;"></span>AController<span style="color: #b4b4b4;">></span> logger)      {          _awsOptions <span style="color: #b4b4b4;">=</span> awsOptions;          _logger <span style="color: #b4b4b4;">=</span> logger;      }      <span style="color: #57a64a;">// POST api/values</span>      [HttpPost]      <span style="color: #569cd6;">public</span> <span style="color: #569cd6;">async</span> <span style="color: #4ec9b0;">Task</span><span style="color: #b4b4b4;"></span>IActionResult<span style="color: #b4b4b4;">></span> Post(<span style="color: #4ec9b0;">Guid</span> Id)      {          AmazonSimpleNotificationServiceClient snsclient <span style="color: #b4b4b4;">=</span>  <span style="color: #569cd6;">new</span> AmazonSimpleNotificationServiceClient(_awsOptions<span style="color: #b4b4b4;">.</span>Options<span style="color: #b4b4b4;">.</span>awsAccessKey,                   _awsOptions<span style="color: #b4b4b4;">.</span>Options<span style="color: #b4b4b4;">.</span>awsSecret, RegionEndpoint<span style="color: #b4b4b4;">.</span>USWest2);</pre><p>That’s it.  Then you will get your user secret values injected into you class.  </p><p>Full Startup.cs (because I hate it when the snippets miss something I need)  </p><pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;"><span style="color: #569cd6;">using</span> Microsoft<span style="color: #b4b4b4;">.</span>AspNet<span style="color: #b4b4b4;">.</span>Builder;  <span style="color: #569cd6;">using</span> Microsoft<span style="color: #b4b4b4;">.</span>AspNet<span style="color: #b4b4b4;">.</span>Hosting;  <span style="color: #569cd6;">using</span> Microsoft<span style="color: #b4b4b4;">.</span>Framework<span style="color: #b4b4b4;">.</span>Configuration;  <span style="color: #569cd6;">using</span> Microsoft<span style="color: #b4b4b4;">.</span>Framework<span style="color: #b4b4b4;">.</span>DependencyInjection;  <span style="color: #569cd6;">using</span> Microsoft<span style="color: #b4b4b4;">.</span>Framework<span style="color: #b4b4b4;">.</span>Logging;  <span style="color: #569cd6;">using</span> Severing<span style="color: #b4b4b4;">.</span>Service<span style="color: #b4b4b4;">.</span>Config;  <span style="color: #569cd6;">namespace</span> Service  {      <span style="color: #569cd6;">public</span> <span style="color: #569cd6;">class</span> <span style="color: #4ec9b0;">Startup</span>      {          <span style="color: #569cd6;">public</span> Startup(IHostingEnvironment env)          {              <span style="color: #569cd6;">var</span> builder <span style="color: #b4b4b4;">=</span> <span style="color: #569cd6;">new</span> ConfigurationBuilder();              <span style="color: #569cd6;">if</span> (env<span style="color: #b4b4b4;">.</span>IsDevelopment())              {                  builder<span style="color: #b4b4b4;">.</span>AddUserSecrets(<span style="color: #d69d85;">"aspnet5-4c570577-d4ba-491c-a56c-3f267e3d5211"</span>);              }              <span style="color: #569cd6;">else</span>              {                  builder<span style="color: #b4b4b4;">.</span>AddEnvironmentVariables();              }              Configuration <span style="color: #b4b4b4;">=</span> builder<span style="color: #b4b4b4;">.</span>Build();          }          <span style="color: #569cd6;">public</span> IConfiguration Configuration { <span style="color: #569cd6;">get</span>; <span style="color: #569cd6;">set</span>; }          <span style="color: #57a64a;">// This method gets called by a runtime.</span>          <span style="color: #57a64a;">// Use this method to add services to the container</span>          <span style="color: #569cd6;">public</span> <span style="color: #569cd6;">void</span> ConfigureServices(IServiceCollection services)          {              services<span style="color: #b4b4b4;">.</span>AddMvc();              services<span style="color: #b4b4b4;">.</span>AddOptions();              services<span style="color: #b4b4b4;">.</span>Configure<span style="color: #b4b4b4;"></span>AwsOptions<span style="color: #b4b4b4;">></span>(Configuration);              services<span style="color: #b4b4b4;">.</span>AddLogging();              <span style="color: #57a64a;">// Uncomment the following line to add Web API services which makes it easier to port Web API 2 controllers.</span>              <span style="color: #57a64a;">// You will also need to add the Microsoft.AspNet.Mvc.WebApiCompatShim package to the 'dependencies' section of project.json.</span>              <span style="color: #57a64a;">// services.AddWebApiConventions();</span>          }          <span style="color: #57a64a;">// Configure is called after ConfigureServices is called.</span>          <span style="color: #569cd6;">public</span> <span style="color: #569cd6;">void</span> Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)          {              loggerFactory<span style="color: #b4b4b4;">.</span>AddConsole();              <span style="color: #57a64a;">// Configure the HTTP request pipeline.</span>              app<span style="color: #b4b4b4;">.</span>UseStaticFiles();              <span style="color: #57a64a;">// Add MVC to the request pipeline.</span>              app<span style="color: #b4b4b4;">.</span>UseMvc();              <span style="color: #57a64a;">// Add the following route for porting Web API 2 controllers.</span>              <span style="color: #57a64a;">// routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");</span>          }      }  }</pre>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;So I’ve been playing around with Asp.Net 5 beta 5 trying to figure out how to use some of the new configuration stuff.  Especially the us</summary>
      
    
    
    
    
    <category term="ASP.NET" scheme="https://todothinkofname.net/tags/ASP-NET/"/>
    
    <category term="beta5" scheme="https://todothinkofname.net/tags/beta5/"/>
    
  </entry>
  
  <entry>
    <title>Fix for NServiceBus Testing.</title>
    <link href="https://todothinkofname.net/2013/05/04/Fix%20for%20NServiceBus%20testing/"/>
    <id>https://todothinkofname.net/2013/05/04/Fix%20for%20NServiceBus%20testing/</id>
    <published>2013-05-04T09:09:00.000Z</published>
    <updated>2023-02-19T01:46:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>Looks like the issue I had with NSB testing may not have been the Unobtrusive messages.</p><p>What I’ve ended up having to do is this.</p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">MessageConventionExtensions.IsMessageTypeAction =</span><br><span class="line">  t =&gt; t.Namespace != <span class="literal">null</span> &amp;&amp; t.Namespace.EndsWith(“Messages”) &amp;&amp; !t.Namespace.StartsWith(“NServiceBus”);</span><br><span class="line">Test.Initialize();</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Looks like the issue I had with NSB testing may not have been the Unobtrusive messages.&lt;/p&gt;
&lt;p&gt;What I’ve ended up having to do is this.&lt;/</summary>
      
    
    
    
    
    <category term=".Net" scheme="https://todothinkofname.net/tags/Net/"/>
    
    <category term="NServiceBus" scheme="https://todothinkofname.net/tags/NServiceBus/"/>
    
  </entry>
  
</feed>
