<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>aws &#8211; Software, Fitness, and Gaming &#8211; Jesse Warden</title>
	<atom:link href="https://jessewarden.com/tag/aws/feed" rel="self" type="application/rss+xml" />
	<link>https://jessewarden.com</link>
	<description>Software &#124; Fitness &#124; Gaming</description>
	<lastBuildDate>Tue, 07 Apr 2020 04:21:21 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://jessewarden.com/wp-content/uploads/2016/08/cropped-Lambda2-32x32.png</url>
	<title>aws &#8211; Software, Fitness, and Gaming &#8211; Jesse Warden</title>
	<link>https://jessewarden.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Handling Noop Infrastructure in AWS Step Functions</title>
		<link>https://jessewarden.com/2020/04/handling-noop-infrastructure-in-aws-step-functions.html</link>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Tue, 07 Apr 2020 04:21:21 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[functionalprogramming]]></category>
		<category><![CDATA[statemachine]]></category>
		<category><![CDATA[states]]></category>
		<category><![CDATA[stepfunction]]></category>
		<guid isPermaLink="false">https://jessewarden.com/?p=5921</guid>

					<description><![CDATA[Spent a month on this and I think I figured out how to get JSON to &#8220;roll over&#8221; a Step Function step that is a noop (no operation: function that doesn&#8217;t return a value), like say AWS Batch. Noop&#8217;s (no operation) are steps that basically are full of side effects, but really don&#8217;t have a [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Spent a month on this and I think I figured out how to get JSON to &#8220;roll over&#8221; a <a href="https://aws.amazon.com/step-functions/">Step Function</a> step that is a noop (no operation: function that doesn&#8217;t return a value), like say <a href="https://aws.amazon.com/batch/">AWS Batch</a>. Noop&#8217;s (no operation) are steps that basically are full of side effects, but really don&#8217;t have a useful return value beyond &#8220;SUCCESS&#8221;.</p>



<span id="more-5921"></span>



<p>If you code Batch in <a href="https://golang.org/">Go</a> for example, the main method has it right there in the return value: void. Meaning… there <em>is</em> no return value.</p>



<p>How, then, do you use something like a noop in your mostly Functional Programming style Step Function that assumes you&#8217;re composing infrastructure like you&#8217;d compose functions? Basically tap. If you&#8217;re not familiar, tap is a quick way to debug pure function chains.</p>



<p>If you&#8217;ve ever heard of the identity function, it basically gives you back what you give it, like this in Python:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">def identity(oh_yeah):
  <span class="hljs-keyword">return</span> oh_yeah</code></span></pre>


<p>Or this in JavaScript:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> identity = <span class="hljs-function"><span class="hljs-params">ohYeah</span> =&gt;</span>
  ohYeah</code></span></pre>


<p>That seems like a ridiculous function, no doubt. But watch what happens when you combine it with composed functions, say, parsing some JSON.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">def parse(str):
  <span class="hljs-keyword">return</span> json_parse(str) \
  &gt;&gt; parse_people \
  &gt;&gt; filter_humans \
  &gt;&gt; format_names</code></span></pre>


<p>Parse composes 4 functions together. If they&#8217;re pure, how do you &#8220;see&#8221; inside that pipeline? You &#8220;tap&#8221; into it. We can take our identity function, and convert to a tap function like this:</p>


<pre class="wp-block-code"><span><code class="hljs language-php">def tap(oh_yeah):
  <span class="hljs-keyword">print</span>(<span class="hljs-string">"oh_yeah:"</span>, oh_yeah)
  <span class="hljs-keyword">return</span> oh_yeah</code></span></pre>


<p>Then we can &#8220;tap into&#8221; the pipeline.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">def parse(str):
  <span class="hljs-keyword">return</span> json_parse(str) \
  &gt;&gt; tap \
  &gt;&gt; parse_people \
  &gt;&gt; tap \
  &gt;&gt; filter_humans \
  &gt;&gt; tap \
  &gt;&gt; format_names</code></span></pre>


<p>Sick, ya? Now the normal way to do that in Step Functions is via a <a href="https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-pass-state.html">Pass state</a>:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-string">"Tap"</span>: {
  <span class="hljs-string">"Type"</span>: <span class="hljs-string">"Pass"</span>,
  <span class="hljs-string">"Next"</span>: <span class="hljs-string">"NextStep"</span>
}</code></span></pre>


<p>You can then see the output in the Step Function console, or tweak the inputs/outputs if you wish.</p>



<p>… but that&#8217;s for Lambdas, Step Functions, SQS, and SNS steps that not only return a result like a pure function, but do so using your JSON. In JavaScript, that&#8217;s pretty easy to merge properties:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> addYoSelf = <span class="hljs-function"><span class="hljs-params">json</span> =&gt;</span>
  ({ …json, <span class="hljs-attr">name</span>: <span class="hljs-string">"Jesse was here"</span> })</code></span></pre>


<p>Batch, and even Step Functions, don&#8217;t always work like this. You typically have to define <a href="https://docs.aws.amazon.com/step-functions/latest/dg/input-output-inputpath-params.html">Parameters</a> manually depending upon the input… meaning you lose your JSON tree. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f622.png" alt="😢" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>… UNLESS it&#8217;s just 1 branch. You can create siblings that are collected in a single spot using the <a href="https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-parallel-state.html">Parallel task</a>.</p>



<p>If you think <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all">Promise.all</a> like in JavaScript or <a href="https://docs.python.org/3/library/asyncio-task.html#asyncio.gather">gather</a> in Python, multiple results, but a single, Array filled result. This allows you to keep context at least in 1 spot using a Pass, and you don&#8217;t care about the rest.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">a = stuff
identity = <span class="hljs-function"><span class="hljs-params">stuff</span> =&gt;</span> stuff
addSelf = <span class="hljs-function"><span class="hljs-params">stuff</span> =&gt;</span> ({… stuff, <span class="hljs-attr">name</span>: <span class="hljs-string">'Jesse'</span>})
destroy = <span class="hljs-function"><span class="hljs-params">stuff</span> =&gt;</span> <span class="hljs-literal">undefined</span>
end = <span class="hljs-function"><span class="hljs-params">a</span> =&gt;</span> <span class="hljs-built_in">Promise</span>.all(&#91;identity(a), addSelf(a), destroy(a)])</code></span></pre>


<p>Notice how <code>end</code> will result in an Array like:<br><code>[stuff, stuff + name Jesse, undefined]</code></p>



<p>Undefined is often what we get with noops that return no value. BUT, we need the first part to continue our Step Function with &#8220;context&#8221;. Using a Parallel + Pass, you can keep that context.</p>



<p>Until Batch gets the .waitForTaskToken feature (I mean… ECS has it…), you can wrap her in a Parallel to keep context. Just watch those catches….</p>



<p>tl;dr; JSON use Parallel and in next state go:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-string">"OutputPath"</span>: <span class="hljs-string">"$&#91;0]"</span></code></span></pre>


<p>BTW, I know you can use <code>ResultPath</code> and just attach to your existing JSON, but AWS Batch is HUGE, and we&#8217;re already getting super close to our JSON size limit with our immense Array size I refuse to read from S3. You could just export and then rip off from a Pass state, but you&#8217;ll get a size exception before that happens sadly. Twice now I&#8217;ve got an exception when it completes the Batch because the JSON is too large, and using this technique has worked every time. </p>



<figure class="wp-block-gallery columns-1 is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><img fetchpriority="high" decoding="async" width="372" height="317" src="https://jessewarden.com/wp-content/uploads/2020/04/stepfunctions_graph-8.png" alt="" data-id="5922" data-full-url="https://jessewarden.com/wp-content/uploads/2020/04/stepfunctions_graph-8.png" data-link="https://jessewarden.com/?attachment_id=5922" class="wp-image-5922" srcset="https://jessewarden.com/wp-content/uploads/2020/04/stepfunctions_graph-8.png 372w, https://jessewarden.com/wp-content/uploads/2020/04/stepfunctions_graph-8-300x256.png 300w" sizes="(max-width: 372px) 100vw, 372px" /></figure></li></ul></figure>



<p>And Step Function JSON for above (supply your own Lambda):</p>


<pre class="wp-block-code"><span><code class="hljs language-json">{
  <span class="hljs-attr">"Comment"</span>: <span class="hljs-string">"A Hello World example of the Amazon States Language using Pass states"</span>,
  <span class="hljs-attr">"StartAt"</span>: <span class="hljs-string">"Both"</span>,
  <span class="hljs-attr">"States"</span>: {
    <span class="hljs-attr">"Both"</span>: {
      <span class="hljs-attr">"Type"</span>: <span class="hljs-string">"Parallel"</span>,
      <span class="hljs-attr">"Next"</span>: <span class="hljs-string">"Keep JSON"</span>,
      <span class="hljs-attr">"Branches"</span>: &#91;
        {
          <span class="hljs-attr">"StartAt"</span>: <span class="hljs-string">"Good Function Returns Value"</span>,
          <span class="hljs-attr">"States"</span>: {
            <span class="hljs-attr">"Good Function Returns Value"</span>: {
              <span class="hljs-attr">"Type"</span>: <span class="hljs-string">"Task"</span>,
              <span class="hljs-attr">"Resource"</span>: <span class="hljs-string">"arn:aws:lambda:us-east-1:0000000:function:jesse-identity"</span>,
              <span class="hljs-attr">"Parameters"</span>: {
                <span class="hljs-attr">"uno"</span>: <span class="hljs-string">"yup"</span>
              },
              <span class="hljs-attr">"ResultPath"</span>: <span class="hljs-string">"$.datLambdaResult"</span>,
              <span class="hljs-attr">"End"</span>: <span class="hljs-literal">true</span>
            }
          }
        },
        {
          <span class="hljs-attr">"StartAt"</span>: <span class="hljs-string">"Bad Noop"</span>,
          <span class="hljs-attr">"States"</span>: {
            <span class="hljs-attr">"Bad Noop"</span>: {
              <span class="hljs-attr">"Type"</span>: <span class="hljs-string">"Pass"</span>,
              <span class="hljs-attr">"Result"</span>: <span class="hljs-string">"World"</span>,
              <span class="hljs-attr">"End"</span>: <span class="hljs-literal">true</span>
            }
          }
        }
      ]
    },
    <span class="hljs-attr">"Keep JSON"</span>: {
      <span class="hljs-attr">"Type"</span>: <span class="hljs-string">"Pass"</span>,
      <span class="hljs-attr">"OutputPath"</span>: <span class="hljs-string">"$&#91;0]"</span>,
      <span class="hljs-attr">"End"</span>: <span class="hljs-literal">true</span>
    }
  }
}</code></span></pre>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>AWS Adventures: Part 3 – Post Mortem on Lambdas</title>
		<link>https://jessewarden.com/2017/09/aws-adventures-part-3-post-mortem-on-lambdas.html</link>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Thu, 28 Sep 2017 00:26:28 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[lambda]]></category>
		<category><![CDATA[serverless]]></category>
		<guid isPermaLink="false">http://jessewarden.com/?p=5359</guid>

					<description><![CDATA[Introduction Friends have asked that I report a from the trenches update on my thoughts on Lambdas. I fell in love about a year ago, so how do I feel now? I&#8217;ll cover the pro&#8217;s and con&#8217;s I faced, what I learned, and what I still don&#8217;t know. Why If you read my previous article [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Introduction</h1>
<p>Friends have asked that I report a from the trenches update on my thoughts on Lambdas. I fell in love about a year ago, so how do I feel now? I&#8217;ll cover the pro&#8217;s and con&#8217;s I faced, what I learned, and what I still don&#8217;t know.<br />
<span id="more-5359"></span></p>
<h1>Why</h1>
<p>If you read my previous article on <a href="http://jessewarden.com/2016/12/aws-adventures-part-1-lambda.html">what Lambdas are</a>, and <a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html">how you build an automation workflow</a> around them, you&#8217;ll see why I like them. In short, a front end developer with a bit of back-end Node experience can use continuous deployment for working REST services (or non) quickly, without worry of maintenance, or sudden spikes in traffic. I&#8217;m a coder, and with the <a href="https://aws.amazon.com/sdk-for-node-js/">AWS Node</a> and <a href="https://aws.amazon.com/sdk-for-python/">Python SDK</a> , I can code my way onto the cloud vs. learning Unix, various weirdness with Terraform/Chef/Ansible/Docker, etc.</p>
<p>I have Amazon manage my infrastructure so I can focus on coding. I love it.</p>
<h1>Different Environments</h1>
<p>If you utilize multiple AWS accounts and/or environments, the gotchas are basically your permissions. Specifically, IAM roles and what permissions those IAM roles have. If you follow the whole dev/qa/staging/prod etc. life cycle of testing your code in each <a href="https://www.martinfowler.com/articles/continuousIntegration.html#TestInACloneOfTheProductionEnvironment">environment</a> and then &#8220;moving&#8221; to a higher environment once the code passes all testing, you&#8217;ll find you do the same thing here. In my experience, you&#8217;re just testing two things: Can my Lambda use it&#8217;s permissions the same (log to CloudWatch, access a particular S3 bucket, etc) as well as ensuring connectivity that you could of fat fingered somewhere (i.e. the subnet/security group in the Terraform that&#8217;s creating your Lambda isn&#8217;t correct for the prod environment)? Beyond that, everything seems to operate the same between environments which I loved.</p>
<p><strong>Lesson</strong>: As long as you avoid <a href="http://www.continuitysoftware.com/blog/what-is-configuration-drift/">configuration drift</a>, you&#8217;re fine.</p>
<h1>No API Gateway?</h1>
<p>Lambdas are built for burst traffic or the occasional code run for simple services. However, it does NOT require an API Gateway. Meaning, you do not need a URL to have your code run. It truly is a &#8220;function&#8221;, or a bunch of code. How that code is run doesn&#8217;t have to be a URL being put in the web browser.</p>
<p>AWS is flexible. Lambdas are actually functions, not actual &#8220;API&#8217;s&#8221;. Meaning, anything can trigger them; they ARE functions. Files put on an S3 bucket (hard drive), some log messages in CloudWatch that match a string, and even periodic cron jobs managed by AWS. I can personally attest that during the S3 outage last year, when it came back up, not 1 of my messages over a 2 hour period was lost in my CloudWatch cro</p>
<p>More important, though, is that Lambdas can invoke other Lambdas.</p>
<p><strong>Lesson</strong>: Even with AWS, you can code yourself out of any negative situation. :: flexes bicep :: Take a look the triggers that AWS provides for Lambdas. You truly can react to a variety of events.</p>
<h1>Lambda&#8217;s Calling Lambda&#8217;s</h1>
<p>Lambda&#8217;s can invoke other Lambda functions through <a href="https://boto3.readthedocs.io/en/latest/reference/services/lambda.html#Lambda.Client.invoke">lambda.invoke.</a> Given the fact that each Lambda (Python or JavaScript) with a reasonable amount of code runs less than 100 to 200 ms is awesome&#8230; and doesn&#8217;t cost me much since I&#8217;m not running a high TPS in my personal projects, this is great.</p>
<p>Another subtle benefit is that you can call them in either a request / response for a more REST type of feel, or a fire and forget for longer running processes. While I haven&#8217;t been able to have the need yet, I loved playing with the <a href="https://aws.amazon.com/step-functions/">step functions</a> for when you have a bunch of microservices you&#8217;re trying to coordinate in a concurrent fashion.</p>
<h1>Errors and Logging</h1>
<p>Be aware that some connection errors aren&#8217;t verbose. This may be for security reasons. 99% of my &#8220;Lambda can&#8217;t connect to some thing&#8221; all had to do with a misconfigured security group, subnet, or IAM permission. That&#8217;s good to know since those things can be easily automated using Terraform or things like the SDK.</p>
<p>For logging, while Lambdas typically log to CloudWatch by default, make sure you log to a single log stream so you can utilize the console or SDK to more easily find logs in a time window. Searching various log streams with dates in the titles over time to find a particular log is harder if it&#8217;s not in a the same stream name.</p>
<h1>Time Limit</h1>
<p>Years ago, Lambdas were limited to 1 minute. Then they got 5 minutes. 5 minutes is still not enough once you have so much power at your finger tips, heh.</p>
<p>If you run into scenarios where 5 minutes isn&#8217;t enough, you have 2 options:</p>
<ol>
<li>Use <a href="https://aws.amazon.com/step-functions/">step functions</a>. This can be challenging for some developers because it inverses the responsibility of those doing the work to poll for jobs vs. you being responsible to tell them. This helps solve concurrency issues, too.</li>
<li>Use an audit log + <a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html">CloudWatch cron job</a>. Either use a NoSQL database like <a href="https://aws.amazon.com/dynamodb/">Dynamo</a> or an S3 bucket folder. Your Lambda&#8217;s will do their work, then audit that they &#8220;started and stopped&#8221; with a UUID. This could be a timestamped data entry in Dynamo, or a file in S3 bucket. You then have that long running process make an entry with the same UUID/correlation ID in the same audit log (Dynamo or S3). Finally, you have a CloudWatch cron job launch a Lambda every minute or so to check on the status. When the Lambda finds a stopped job audit entry that matches a start, it can mark the job as successful, error&#8217;d, or timed out based on your criteria. This CloudWatch cron jobs are beast, yes, they can be trusted.</li>
</ol>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1>Deployment</h1>
<p>Deployment is huge contention amongst many developers. I&#8217;m a huge proponent of automating everything with the AWS SDK. Others like to use Terrform/Chef/Ansible, etc. Others like to upload ZIP files through the console.</p>
<p>Whatever method you do, I still encourage the use of existing integration testing solutions. AWS&#8217;s update process is super easy; you&#8217;re literally uploading code to the Lambda directly or an S3 bucket, and &#8220;poof&#8221;, you&#8217;re Lambda is updated. You can use the environment &amp; versioning if you wish. I personally didn&#8217;t like that, though, and instead liked using a <a href="https://martinfowler.com/bliki/BlueGreenDeployment.html">green/blue deployment</a> model where you have 2 Lambdas with a blue/green suffix in the name. When you upload new code, you simply switch the trigger as the last step once all your integration tests have been run. If you screw up, no big deal, it&#8217;s near instant to switch it back without uploading new code.</p>
<p>Things like ping and health checks are still extremely important, as are dry runs. Ping&#8217;s are simply a way of ensuring your Lambda function is there. If it&#8217;s API Gateway, that&#8217;s a URL you can hit to ensure it works. If it&#8217;s an S3 bucket trigger, you can drop a particular filename in a particular place, and your Lambda can respond either there or in CloudWatch. For health checks, this is the most important; it ensures your Lambda can talk to all the required services it needs and report back. This goes hand in hand with a dry run to ensure it can talk to those things, but doesn&#8217;t affect them; like making accidental database entries. Instead, it&#8217;s just ensuring your connectivity (i.e. IAM role permissions, subnet/security groups, VPC&#8217;s) are all correct.</p>
<p>&nbsp;</p>
<h1>Where Do We Go From Here?</h1>
<p>A guy reached out to me on Slack asking for help in Python. He&#8217;s never coded in his life, about my age (38), and manages databases that are recently moved from an on-prem situation to his AWS. He wanted to basically have an alarm (an AWS log event) trigger a Lambda, and if it&#8217;s cause was the database was running out of hard drive, to allocate 50 megs more. I gave him a crash course in Python and what I had learned of AWS and Lambdas, and he was up and running in about a month in prod with a 30 line Python Lambda.</p>
<p>That&#8217;s so awesome.</p>
<p>The people using AWS Batch and other short lived EC2&#8217;s for minutes to seconds worth of work are moving some of that to Lambdas for price reasons. Various Lambdas are in the background, facilitating various logging, monitoring, or reactionary/reactive roles to help functionality in Ops or for developers. It&#8217;s become &#8220;just another tool in the toolbox&#8221;, not some new, shiny thing to not be trusted by the cynics.</p>
<p>We&#8217;re still at the beginning of serverless. It is growing, and more and more people from a variety of skillets want to use them. That&#8217;s telling. If you&#8217;re not doing a lot of server-side development and just frontend websites, I encourage you to take a look at hosting your files on S3 and simply putting CloudWatch in front of it. AWS has a good wizard for this.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>AWS Adventures: Part 2 &#8211; Infrastructure As Code, Deploying a Microservice</title>
		<link>https://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html</link>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Sun, 15 Jan 2017 20:04:00 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[infrastructureascode]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[microservice]]></category>
		<category><![CDATA[monolith]]></category>
		<category><![CDATA[serverless]]></category>
		<category><![CDATA[testing]]></category>
		<guid isPermaLink="false">http://jessewarden.com/?p=5272</guid>

					<description><![CDATA[Introduction &#160; In the old days, you&#8217;d write code and allow another team called Operations (or OPs for short) to deploy it to various servers for testing, and eventually production. Quality Assurance teams would be testing your code from a few days to a few weeks ago on another server. Developer tooling, infrastructure as a service, and [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Introduction</h1>
<p>&nbsp;</p>
<p>In the old days, you&#8217;d write code and allow another team called Operations (or OPs for short) to deploy it to various servers for testing, and eventually production. Quality Assurance teams would be testing your code from a few days to a few weeks ago on another server.</p>
<p>Developer tooling, infrastructure as a service, and shorter development cycles have changed all that. The Amazon practice of &#8220;you build it, you own it&#8221; has started to filter out to other companies as an adopted practice. Teams are now expected to build, deploy, and maintain their own software.</p>
<p>Today, I wanted to cover what I&#8217;ve learned about automated deployments around AWS. You&#8217;ll learn why you don&#8217;t need <a href="https://www.ansible.com/">Ansible</a>, <a href="https://www.chef.io/chef/">Chef</a>, or even <a href="https://serverless.com/">Serverless</a>, and instead can use AWS API&#8217;s to do everything you need.</p>
<p><span id="more-5272"></span></p>
<h1>Code</h1>
<p>The <a href="https://github.com/JesterXL/build-destroy-test-lambda">source code</a> for this article is on Github.</p>
<h1>Contents</h1>
<ul>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#Infrastructure As Code">Infrastructure As Code</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#infrastructureasanapi">Infrastructure As An API</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#Destroy, Build, and Test Your Lambda">Destroy, Build, and Test Your Lambda</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#step0">Step 0: Authenticate</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#step1">Step 1: Code Setup</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#step2">Step 2: Mad Creds</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#step3">Step 3: TDD</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#step4">Step 4: List Lambda Functions</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#step5">Step 5: Create Lambda Function</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#step6">Step 6: Delete Your Lambda Function</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#step7">Step 7: Making Testable Code by Testing It</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#step8">Step 8: Build a Command-Line Tool</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#step9">Step 9: Multiple Environments &amp; Green Blue Deployment</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#step10">Step 10: Integration Test</a></li>
<li><a href="http://jessewarden.com/2017/01/aws-adventures-part-2-infrastructure-as-code-deploying-a-microservice.html#Conclusions">Conclusions</a></li>
</ul>
<p><a name="Infrastructure As Code"></a></p>
<h1>Infrastructure As Code</h1>
<h2>Servers As Pets</h2>
<p>In the old days, you treated servers as a part of the family. You named them, constantly monitored their health, and were extremely careful when updating code or applying security patches to them.</p>
<p>As time went on, hardware got cheaper, and <a href="http://martinfowler.com/bliki/BlueGreenDeployment.html">green blue deployments</a> came about. You still had physical servers at your place of work or nearby, but you had 2 instead of 1 production boxes that you switched between.</p>
<h2>Disposable Infrastructure</h2>
<p>The cloud being cheap changed all that. Eventually servers became so cheap and easy to make, you just destroyed and created new ones at the first sign of trouble.</p>
<h2>Infrastructure == Code</h2>
<p>The Infrastructure As Code movement, in short, is that all your servers and API&#8217;s and builds&#8230; are code. Not JSON, not YAML, not even XML (lol, wtf). If you want to update a server, deploy new code, or update a library version, you simply change the code and check into version control.</p>
<p>As a coder, the reasons I like this are:</p>
<ol>
<li>I&#8217;m a coder, I write code, and that makes it something I can more easily understand.</li>
<li>Source code is put into version control. Our releases are the same thing as our code versioning.</li>
<li>Version control has a record of all changes.</li>
<li>Team can peer review server/deployment changes increasing quality.</li>
<li>I can unit &amp; integration test my infrastructure code more easily because why? It&#8217;s code.</li>
</ol>
<p><a name="infrastructureasanapi"></a></p>
<h1>Infrastructure as an API</h1>
<p>You can build and destroy a lot of things using the AWS console, the web site you use to access your AWS account. However, <a href="http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/index.html">everything on AWS is an API</a>. While Lambdas are only JavaScript, Java, C#, and Python, you have more language choices, both official and non, to manage your AWS infrastructure such as <a href="https://aws.amazon.com/cli/">Shell</a> and <a href="https://hackage.haskell.org/package/aws">Haskell</a>. We automate these processes using code around these API&#8217;s AWS gives us.</p>
<p>As a JavaScript Developer, it&#8217;s perfect for me because my local <a href="https://nodejs.org/en/">Node</a> development environment is in JavaScript, my front-end <a href="https://angular.io/">Angular</a> is written in JavaScript, my <a href="http://restify.com/">REST API&#8217;s</a> are written in JavaScript, and my infrastructure deployment code is now written in JavaScript. Some of the <a href="https://jenkins.io/">Jenkins</a> job creation/deletion/staring is in JavaScript. Daddy has Thor&#8217;s hammer Mjölnir, some FullStack gauntlets of power, and everything in software is suddenly an orcish nail.</p>
<h2>Immutable Infrastructure</h2>
<p>When disposable infrastructure came into fashion, there was this concept of destroy and build. Rather than debug and nurse a particular server back to health, it was faster and more predictable to just destroy it and build a new one. As this process matured, it eventually became known as &#8220;immutable infrastructure&#8221;.</p>
<p>Just like how nowadays you try to avoid mutable state in your code, you treat your servers and API&#8217;s the same way. Since they are now a result of your code creating it, this is easier.</p>
<h2>Mutable State Lives On</h2>
<p>However, there are some statefull things you can&#8217;t really remove. URL&#8217;s for one thing. While API Gateway will give a brand new, unique URL each time you create a REST API, the URL to access your website doesn&#8217;t change. Mine is <a href="http://jessewarden.com">jessewarden.com</a>. If I were to destroy my website&#8217;s server and code to update it to the latest code on a new server, I&#8217;d still want to use the same URL.</p>
<p>In programming, we use constants for these types of things, and that&#8217;s no different here. For statefull things that do not change, or perhaps are updated later, you&#8217;ll create variables for these.</p>
<h2>Don&#8217;t Update. Instead Destroy, Then Create a New One</h2>
<p>Everything else, assume it&#8217;s immutable. If you update your Lambda code in Gitub, don&#8217;t <a href="http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#updateFunctionCode-property">update it</a> in AWS manually. Destroy and then create a new one with the latest code which takes seconds.</p>
<p>Treat your infrastructure like you would your state in <a href="http://redux.js.org/">Redux</a>:</p>
<pre><code>const newLambda = Object.assign({}, currentLambda, {updated: latestGitCommit});</code></pre>
<p><a name="Destroy, Build, and Test Your Lambda"></a></p>
<h1>Destroy, Build, and Test Your Lambda</h1>
<p>While larger applications are made up of many API&#8217;s, databases, storages, and front ends, we&#8217;ll pick a small piece that should be able to be built &amp; deployed independently. Let&#8217;s destroy, build, and test our newly built Lambda. Afterwards we&#8217;ll update some code in our Lambda to show you how you update over time.</p>
<p>Before we start, you should know that AWS Lambda has <a href="http://docs.aws.amazon.com/lambda/latest/dg/versioning-aliases.html">a nice alias and versioning functionality</a>. I <strong>don&#8217;t</strong> use any of it and I <strong>don&#8217;t</strong> consider it useful. Same with <a href="http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-deploy-api.html">API Gateway stage deployments</a>. Once you start automating things and synching with your <a href="https://www.atlassian.com/git/tutorials/comparing-workflows/">Git Feature Branch or Gitflow workflow</a>, the Lambdas, API Gateways, and Buckets you create are then result of your code versioning. I&#8217;m only 3 months in so perhaps I&#8217;ll change my mind next year.</p>
<p>Versions are custom names such as &#8220;v1.0.0&#8221;, while &#8220;$LATEST&#8221; which you can&#8217;t delete is basically equivalent to Git&#8217;s &#8220;master&#8221;. They can be treated like Git tags. Aliases are names such as &#8220;dev&#8221;, &#8220;qa&#8221;, and &#8220;prod&#8221;. They don&#8217;t have to be environment based, but it helps because you can say &#8220;dev is pointing to $LATEST&#8221; and &#8220;qa is pointing to git tag 1.2.7&#8221;.</p>
<p>Also note, none of this has any rollback functionality. If you screw up, that should be considered OK. The whole point of using code to destroy and build is so you can have confidence that &#8220;rolling back&#8221; is simply switching to a stable Git tag and rebuilding your stack from scratch which takes seconds to minutes.</p>
<p>Easier said then done. For 2 weeks my API Gateway destroy functions were destroying the first api gateway it found that matched a substring. Whoops. #WithGreatPowerComesGreatResponsibility</p>
<h2>Crash Course Into AWS Terminology</h2>
<p>If you already know these, skip to Step 0.</p>
<p><strong>AWS</strong>: Amazon Web Services. Amazon provides hard drives in the cloud, virtual servers, and all kinds of other amazon tools to build applications in the cloud.</p>
<p><strong>AWS Console</strong>: The website you use to access your AWS account and build, destroy, and configure your various AWS services.</p>
<p><strong>Lambda</strong>: A function that Amazon hosts and runs for you. Hot serverless action.</p>
<p><strong>Environment</strong>: Arbitrary name given to a &#8220;different server&#8221;. Typically &#8220;dev&#8221;, &#8220;qa&#8221;, &#8220;staging&#8221; and &#8220;prod&#8221;. Ensures code can be moved between servers and not break.</p>
<p><strong>Region</strong>: AWS hosts data centers in physical locations throughout the world. Each has a name such as &#8220;us-east-1&#8221; for my neck of the woods and &#8220;ap-southeast-2&#8221; for Sydney, Australia. You can have the same code and files run on those regions to be faster for your users.</p>
<p><strong>API Gateway</strong>: Create URL&#8217;s that are typically used for REST API&#8217;s, but you can create them for mocks for simpler integration testing, or simple proxies to existing REST API&#8217;s.</p>
<p><strong>ARN</strong>: Amazon Resource Names. Everything in AWS has a unique ARN. They&#8217;re like URL&#8217;s for websites. They look intimidating at first, but creating them yourself becomes pretty trivial once you learn the format.<br />
<a name="step0"></a></p>
<h1>Step 0: Authenticate</h1>
<p>Good news about Step 0 is you only have to do this crap once.</p>
<p>Although we&#8217;ll be using Node for this tutorial, you&#8217;ll need your credentials to authenticate with your AWS account (if you don&#8217;t have one, <a href="https://aws.amazon.com/">go sign up</a>, button on the top right). For security reasons, you should <a href="http://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html">create an IAM user</a> that doesn&#8217;t have access to all the things. However, to keep this tutorial simple, we&#8217;ll use a core credentials.</p>
<p>In the AWS console, click your name, choose security credentials. Choose Access Keys, then click the &#8220;Create New Access Key&#8221; button.</p>
<p><img decoding="async" class="alignnone size-full wp-image-5274" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-11.12.56-AM.png" alt="" width="1075" height="435" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-11.12.56-AM.png 1075w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-11.12.56-AM-300x121.png 300w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-11.12.56-AM-768x311.png 768w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-11.12.56-AM-1024x414.png 1024w" sizes="(max-width: 1075px) 100vw, 1075px" /></p>
<p>In the popup, click the tincy blue arrow link to &#8220;Show Access Key&#8221;.</p>
<p><img decoding="async" class="alignnone size-full wp-image-5275" src="http://jessewarden.com/wp-content/uploads/2016/12/Group.png" alt="" width="762" height="298" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Group.png 762w, https://jessewarden.com/wp-content/uploads/2016/12/Group-300x117.png 300w" sizes="(max-width: 762px) 100vw, 762px" /></p>
<p>Create a new JSON file called &#8220;credentials.json&#8221; on your computer and paste in the following code. If you&#8217;re using source control, ensure you git ignore the credentials.json file so it&#8217;s not checked into source control, yet can still remain in your code project.</p>
<pre><code>{
    "accessKeyId": "your key here", 
    "secretAccessKey": "your secret access key here", 
    "region": "us-east-1"
}</code></pre>
<p><a name="step1"></a></p>
<h1>Step 1: Code Setup</h1>
<p>Make a folder, open your terminal, cd to the directory, run <code>npm init</code> and hit enter until it stops asking you questions, and finally <code>run npm install aws-sdk --save</code>. I&#8217;m using Node v7.3.0, but you can use whatever. Use <a href="https://github.com/creationix/nvm">nvm</a> to switch to different versions at will.</p>
<p>Create a new JavaScript file called &#8220;index.js&#8221; and put in the following code. This is our basic lambda function that just returns a hello world message.</p>
<pre><code>exports.handler = (event, context, callback) =&gt;
{
    const response = {
        statusCode: '200',
        body: JSON.stringify({result: true, data: 'Hello from Lambda'}),
        headers: {
            'Content-Type': 'application/json',
        },
    }
    callback(null, response);
};</code></pre>
<p><a name="step2"></a></p>
<h1>Step 2: Mad Creds</h1>
<p>Create a new JavaScript file called &#8220;build.js&#8221;, and put in the following code.</p>
<pre><code>const log    = console.log;
const AWS    = require('aws-sdk');
AWS.config.loadFromPath('./credentials.json');</code></pre>
<p>That 3rd statement is synchronous and must appear before you instantiate any other AWS objects/classes, else you&#8217;ll get weird authentication errors.<br />
<a name="step3"></a></p>
<h1>Step 3: TDD</h1>
<p>Note the below are unit tests, not integration tests. Integration tests are tricky not to cause leaky state, so we&#8217;ll start with unit tests first. We&#8217;ll be using <a href="https://mochajs.org/">Mocha</a> and <a href="http://chaijs.com/">Chai</a>, but if you are a <a href="https://medium.com/javascript-scene/why-i-use-tape-instead-of-mocha-so-should-you-6aa105d8eaf4#.7351qclw4">Tape</a> or <a href="https://jasmine.github.io/">Jasmine</a> fan, feel free to use those instead. Run <code>npm install mocha chai lodash --save</code>. Open your package.json, and change the scripts section to look like this:</p>
<pre><code>"scripts": {
  "test": "mocha build.test.js"
},</code></pre>
<p>Create a new file called &#8220;build.test.js&#8221;, and put in the following code:</p>
<pre><code>const expect = require("chai").expect;
const should = require('chai').should();
const _ = require('lodash');
const {
    listFunctions
} = require('./build');</code></pre>
<p>Chai has various assertions, &#8220;should&#8221; reads better than &#8220;expect&#8221;, and we&#8217;ll be using <a href="https://lodash.com/docs/4.17.3">Lodash</a> for creating our own predicates. To avoid using <a href="http://sinonjs.org/">Sinon</a>, we&#8217;ll be making our functions as <a href="https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-pure-function-d1c076bec976#.ua47saviu">pure</a> as possible. To do that, we&#8217;ll need a simple mock for the AWS Lambda client:</p>
<pre><code>const mockLamba = {
    listFunctions: (params, cb) =&gt; cb(undefined, {"Functions": []})
};</code></pre>
<p>Our first test is to read a list of functions:</p>
<pre><code>describe('#listFunctions', ()=&gt;
{
    it('should give a list of functions', (done)=&gt;
    {
        listFunctions(mockLamba, (err, data)=&gt;
        {
            _.isArray(data.Functions).should.be.true;
            done();
        });
    });
});</code></pre>
<p>To run them, in your terminal type <code>npm test</code> and hit enter. You should get an error like &#8220;ReferenceError: listFunctions is not defined&#8221;.<br />
<a name="step4"></a></p>
<h1>Step 4: List Lambda Functions</h1>
<p>Let&#8217;s define it:</p>
<pre><code>
const listFunctions = (lambda, callback)=&gt;
{
    var params = {
        MaxItems: 50
    };
    lambda.listFunctions(params, (err, data)=&gt;
    {
        if(err)
        {
            log("lambda::listFunctions error:", err);
            return callback(err);
        }
        callback(undefined, data);
    });
};</code></pre>
<p>The <code>listFunctions</code> will list all the Lambda functions you have in your account. Here&#8217;s my personal play one:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5276" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-3.11.05-PM.png" alt="" width="1900" height="838" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-3.11.05-PM.png 1900w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-3.11.05-PM-300x132.png 300w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-3.11.05-PM-768x339.png 768w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-3.11.05-PM-1024x452.png 1024w" sizes="auto, (max-width: 1900px) 100vw, 1900px" /></p>
<p>Now re-run your test and she should be Corbin Dallas green.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5277" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-3.14.56-PM.png" alt="" width="532" height="182" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-3.14.56-PM.png 532w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-3.14.56-PM-300x103.png 300w" sizes="auto, (max-width: 532px) 100vw, 532px" /></p>
<p>Now let&#8217;s manually integration test to verify we can use the API in an authenticated way and our code works. Modify your <code>listFunctions</code> so we can see the goodies that come back via a logging of the data:</p>
<pre><code>lambda.listFunctions(params, (err, data)=&gt;
    {
        if(err)
        {
            log("lambda::listFunctions error:", err);
            return callback(err);
        }
        log("lambda::listFunctions, data:", data);
        callback(undefined, data);
    });</code></pre>
<p>Run <code>node index.js</code> and you should see some JSON in your Terminal.</p>
<p>Let&#8217;s add 1 more test for a negative scenario in case we don&#8217;t have permissions, bad credentials, etc.</p>
<pre><code>const mockBadLambda = {
    listFunctions: (params, cb) =&gt; cb(new Error('boom'))
};
// ...
it('should blow up if something goes wrong', (done)=&gt;
{
    listFunctions(mockBadLambda, (err, data)=&gt;
    {
        err.should.exist;
        done();
    });
});</code></pre>
<p>Re-run and you should have 2 passing tests.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5278" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-10.36.05-PM.png" alt="" width="638" height="196" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-10.36.05-PM.png 638w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-30-at-10.36.05-PM-300x92.png 300w" sizes="auto, (max-width: 638px) 100vw, 638px" /><br />
<a name="step5"></a></p>
<h1>Step 5: Create Lambda Function</h1>
<p>Lambda functions require (Jesse Warden&#8217;s way) 4 things:</p>
<ol>
<li>A name prefix. You&#8217;ll often have at least 2 different functions to test development vs. production servers. So &#8220;myapp-dev&#8221; vs. &#8220;myapp-prod&#8221;. The &#8220;myapp&#8221; is your prefix.</li>
<li>An alias. While AWS is implying they&#8217;d like you to use dev, qa, and prod, we&#8217;ll just use one called &#8220;defaultalias&#8221;. Sometimes this is referred to as a qualifier.</li>
<li>A function name. It&#8217;s what you see in the left column of the aws console.</li>
<li>The code, heh! I put mine in a zip file called &#8220;deploy.zip&#8221;. For now we&#8217;ll zip up our index.js file into a zip first. It&#8217;s easier to do this with shell, but THE HAMMER IS JS AND EVERYTHING IS A NAIL.</li>
<li>A role.</li>
</ol>
<h3>Note On Roles (Feel free to skip)</h3>
<p><a href="http://jessewarden.com/2016/12/aws-adventures-part-1-lambda.html">My last article</a> talked about creating a custom role, but we can use the default one Amazon provides called &#8220;lambda_basic_execution&#8221;. I&#8217;ll hardcode it for this tutorial. Note the number in it is your AWS account number. Given in a production environment this would something your team or a OPS/Cloud/Security team would create, we&#8217;ll create a variable for it vs. getting it dynamically. Roles are complicated and are the #1 thing to break your code next to security things (VPC, subnets, security groups).</p>
<p>Let&#8217;s now create a lambda function. In your build.test.js, first import it:</p>
<pre><code>const {
    listFunctions,
    createFunction
} = require('./build');
</code></pre>
<p>Then add a new method to our Lambda mock:</p>
<pre><code>createFunction: (params, cb) =&gt; cb(undefined, {"FunctionArn": 'default'})</code></pre>
<p>When you create a new Lambda function, it&#8217;ll return a big ole JSON object mirroring mostly your parameters. The FunctionArn is the unique ID/URL of our function, so if we get this, we know she&#8217;s legit and it worked. We&#8217;ll add a new predicate to test for this String as well as a new test:</p>
<pre><code>const legitString = (o) =&gt; _.isString(o) &amp;&amp; o.length &gt; 0;
const mockFS = {
 readFileSync: (filename)=&gt; new Buffer('')
};

describe('#createFunction', ()=&gt;
{
    it('should give us a positive response', (done)=&gt;
    {
        createFunction(mockLamba, mockFS, (err, data)=&gt;
        {
            legitString(data.FunctionArn).should.be.true;
            done();
        });
    });
});</code></pre>
<p>Running it should fail:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5281" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-31-at-10.46.54-AM.png" alt="" width="784" height="436" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-31-at-10.46.54-AM.png 784w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-31-at-10.46.54-AM-300x167.png 300w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-31-at-10.46.54-AM-768x427.png 768w" sizes="auto, (max-width: 784px) 100vw, 784px" /></p>
<p>Let&#8217;s make it pass. This&#8217;ll require a bit more variables setup first. Add your createFunction to the build.js:</p>
<pre><code>const createFunction = (lambda, fs, callback)=&gt;
{
    var params = {
        Code: {
            ZipFile: fs.readFileSync('deploy.zip')
        },
        FunctionName: FUNCTION_NAME,
        Handler: 'index.handler',
        Role: ROLE,
        Runtime: 'nodejs4.3'
    };
    lambda.createFunction(params, (err, data)=&gt;
    {
        if(err)
        {
            // console.log("err:", err);
            return callback(err);
        }
        // log("data:", data);
        callback(undefined, data);
    });
};</code></pre>
<p>And ensure you&#8217;ve exported the function below:</p>
<pre><code>module.exports = {
    listFunctions,
    createFunction
};</code></pre>
<p>No re-run <code>npm test</code> and it should pass:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5282" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-31-at-10.51.47-AM.png" alt="" width="652" height="298" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-31-at-10.51.47-AM.png 652w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-31-at-10.51.47-AM-300x137.png 300w" sizes="auto, (max-width: 652px) 100vw, 652px" /></p>
<p>Let&#8217;s add a negative test scenario in case the createFunction fails. Add a createFunction to the mockBadLambda:</p>
<pre><code>createFunction: (params, cb) =&gt; cb(new Error('boom'))</code></pre>
<p>Then add the negative test for it:</p>
<pre><code>it('should blow up if something goes wrong', (done)=&gt;
{
    createFunction(mockBadLambda, mockFS, (err, data)=&gt;
    {
        err.should.exist;
        done();
    });
});</code></pre>
<p>Your tests run now should show:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5283" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-31-at-11.03.42-AM.png" alt="" width="654" height="310" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-31-at-11.03.42-AM.png 654w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-31-at-11.03.42-AM-300x142.png 300w" sizes="auto, (max-width: 654px) 100vw, 654px" /></p>
<h3>Make and Destroy Deploy ZIP</h3>
<p><strong>Note Shell vs. JavaScript</strong>: While you can use a pure JavaScript solution using <a href="https://www.npmjs.com/package/archiver">archiver</a> (ensure you use forceZip64 in the constructor), now that PC&#8217;s have shell baked in, it&#8217;s easier to read, less code to write, and more predictable.</p>
<p>When you create a Lambda function, you need to upload code in the same call. Typically our code is more than just 1 <code>index.js</code> file, it&#8217;s many libraries in <code>node_modules</code>, configure files, etc. For file size reasons and ease of portability, we zip it all up into 1 smaller file. If you look at our <code>createFunction</code> you&#8217;ll see she reads it into a Node Buffer.</p>
<p>To create it and delete it ourself, we just need to add 2 new script commands to our <code>package.json</code>:</p>
<pre><code>"makezip": "zip deploy.zip index.js",
"deletezip": "rm -f deploy.zip"</code></pre>
<p>Test yourself by running <code>npm run deletezip</code> and <code>npm run makezip</code>.</p>
<h3>Give createFunction a Spin</h3>
<p>Let&#8217;s give her a go. Open up index.js, and at the very bottom, just go ahead and hardcode:</p>
<pre><code>createFunction(lambda, fs);</code></pre>
<p>You should now be able to log into the AWS Console and see your new Lambda function in the list:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5293" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-01-at-4.17.26-PM.png" alt="" width="2076" height="444" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-01-at-4.17.26-PM.png 2076w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-01-at-4.17.26-PM-300x64.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-01-at-4.17.26-PM-768x164.png 768w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-01-at-4.17.26-PM-1024x219.png 1024w" sizes="auto, (max-width: 2076px) 100vw, 2076px" /></p>
<p>Wunderbar! Now, delete your hardcoded createFunction from index.js.<br />
<a name="step6"></a></p>
<h1>Step 6: Delete Your Lambda Function</h1>
<p>Your function is created. If you want to update code in it, you could simple make a new zip file and call <a href="http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#updateFunctionCode-property">updateFunctionCode</a>. However, to make things truly immutable and atomic, meaning each individual aspect of our Lambda we can test and update individually, we&#8217;ll just delete the whole thing.</p>
<p>Remember, we&#8217;re not treating our server like a nice camera. Instead, we purchase a disposable one at the local drugstore/apothecary, and if it breaks, we get a new one instead of waisting time debugging a $9.25 single use electronic. This is important for deploying specific versions of code. If you deploy a git tag called &#8220;2.1.6&#8221;, but you later update code, you&#8217;ve negated the whole point of using a specific git tag since it&#8217;s not really 2.1.6, but your own version. If something goes wrong, you know for sure (mostly) that&#8217;s that version of the code and not your modification.</p>
<p>In build.test.js, import the non-existent deleteFunction:</p>
<pre><code>const {
	listFunctions,
	createFunction,
	deleteFunction
} = require('./build');</code></pre>
<p>Add a mock method to our mockLambda:</p>
<pre><code>deleteFunction: (params, cb) =&gt; cb(undefined, {})</code></pre>
<p>And a mock method to our mockBadLambda:</p>
<pre><code>deleteFunction: (params, cb) =&gt; cb(new Error('boom'))</code></pre>
<p>And finally our 2 tests:</p>
<pre><code>describe('#deleteFunction', ()=&gt;
{
	it('should delete our lambda if there', (done)=&gt;
	{
		deleteFunction(mockLamba, (err)=&gt;
		{
			_.isUndefined(err).should.be.true;
			done();
		});
	});
	it('should not delete our lambda if it', (done)=&gt;
	{
		deleteFunction(mockBadLambda, (err)=&gt;
		{
			err.should.exist;
			done();
		});
	});
});</code></pre>
<p>If our Lambda works, we get no error. The call gives you an empty Object back which is worthless, so we just bank on &#8220;no error is working code&#8221;. Let&#8217;s write the implementation. In build.js, put in the following code above your module.exports:</p>
<pre><code>const deleteFunction = (lambda, callback)=&gt;
{
    var params = {
        FunctionName: FUNCTION_NAME
    };
    lambda.deleteFunction(params, (err, data)=&gt;
    {
        if(err)
        {
            // log("lambda::deleteFunction, error:", err);
            return callback(err);
        }
        // log("lambda::deleteFunction, data:", data);
        callback(undefined, data);
    });
};</code></pre>
<p>And then add to your module.exports:</p>
<pre><code>module.exports = {
    listFunctions,
    createFunction,
    deleteFunction
};</code></pre>
<p>Cool, now re-run npm test:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5294" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-01-at-4.51.18-PM.png" alt="" width="648" height="432" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-01-at-4.51.18-PM.png 648w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-01-at-4.51.18-PM-300x200.png 300w" sizes="auto, (max-width: 648px) 100vw, 648px" /></p>
<p>Let&#8217;s give her a spin. Hardcode <code>deleteFunction(lambda, ()=&gt;{});</code> at the very bottom, run <code>node build.js</code>, then log into the AWS Console for Lambda, and you should no longer see &#8216;datMicro&#8217; (or whatever you called it) in the left list.<br />
<a name="step7"></a></p>
<h1>Step 7: Making Testable Code by Testing It</h1>
<p>There are a few more steps to go in making our Lambda fully functional with the API Gateway. However, we can at this point test her out in the AWS Console. That means we can test her out in JavaScript, too. Let&#8217;s take a look at the original Lambda function code:</p>
<pre><code>exports.handler = (event, context, callback) =&gt;
{
    const response = {
        statusCode: '200',
        body: JSON.stringify({result: true, data: 'Hello from Lambda'}),
        headers: {
            'Content-Type': 'application/json',
        }
    }
    callback(null, response);
};</code></pre>
<p>A few problems with this handler. First, it&#8217;s not testable because it doesn&#8217;t return anything. Second, it doesn&#8217;t really take any inputs of note. Let&#8217;s do a few things. We&#8217;ll add some unit tests, a function that always returns true, and a random number function.</p>
<h2>Always True</h2>
<p>Create an index.test.js file, and add this code as a starting template:</p>
<pre><code>const expect = require("chai").expect;
const should = require('chai').should();
const _ = require('lodash');
const {
	alwaysTrue
} = require('./index');

describe('#index', ()=&gt;
{
    describe('#alwaysTrue', ()=&gt;
    {
        it('is always true', ()=&gt;
        {
            alwaysTrue().should.be.true;
        });
    });
});
</code></pre>
<p>Modify your package.json to point to this test for now:</p>
<pre><code>"scripts": {
    "test": "mocha index.test.js",
    ...
},</code></pre>
<p>Now run npm test. Hopefully you get something along the lines of:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5295" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-02-at-10.28.32-AM.png" alt="" width="319" height="171" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-02-at-10.28.32-AM.png 319w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-02-at-10.28.32-AM-300x161.png 300w" sizes="auto, (max-width: 319px) 100vw, 319px" /></p>
<p>To make it pass, create the predicate:</p>
<pre><code>const alwaysTrue = ()=&gt; true;</code></pre>
<p>Then export at the very bottom:</p>
<pre><code>module.exports = {
    alwaysTrue
};</code></pre>
<p>Re-run your npm test, and it should be green:</p>
<pre><code>module.exports = {
    alwaysTrue
};</code></pre>
<p><a href="http://softwareengineering.stackexchange.com/questions/202908/how-do-functional-languages-handle-random-numbers">Testing random numbers is hard</a>. For now, we&#8217;ll just verify the number is within the range we specified. In index.test.js import the new, non-existent, function:</p>
<pre><code>const {
	alwaysTrue,
    getRandomNumberFromRange
} = require('./index');</code></pre>
<p>And a basic test, as we&#8217;re not handling bounds or typing checks for now:</p>
<pre><code>describe('#getRandomNumberFromRange', ()=&gt;
{
    it('should give a number within an expected range', ()=&gt;
    {
        const START = 1;
        const END = 10;
        const result = getRandomNumberFromRange(START, END);
        _.inRange(result, START, END).should.be.true;
    });
});</code></pre>
<p>Re-run your tests and it should fail (or perhaps not even compile).</p>
<p>Now implement the function in index.js:</p>
<pre><code>const getRandomNumberFromRange = (start, end)=&gt;
{
	const range = end - start;
	let result = Math.random() * range;
	result += start;
	return Math.round(result);
};</code></pre>
<p>And export her at the bottom:</p>
<pre><code>module.exports = {
    alwaysTrue,
    getRandomNumberFromRange
};</code></pre>
<p>Re-run your tests and she should be green:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5296" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-02-at-11.21.20-AM.png" alt="" width="375" height="127" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-02-at-11.21.20-AM.png 375w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-02-at-11.21.20-AM-300x102.png 300w" sizes="auto, (max-width: 375px) 100vw, 375px" /></p>
<p>Lastly, let&#8217;s rework our main Lambda function to always return a value, respond to a test, and become its own function as we&#8217;ll manually add it to the module.exports in a bit. In index.test.js, import the handler:</p>
<pre><code>const {
	alwaysTrue,
    getRandomNumberFromRange,
    handler
} = require('./index');</code></pre>
<p>And write the first test that expects it to return a response. Since we aren&#8217;t a typed language, we&#8217;ll create a loose one via a couple predicates to determine if it&#8217;s &#8220;response like&#8221;.</p>
<pre><code>const responseLike = (o)=&gt; _.isObjectLike(o) &amp;&amp; _.has(o, 'statusCode') &amp;&amp; _.has(o, 'body');</code></pre>
<p>And the test:</p>
<pre><code>describe('#handler', ()=&gt;
{
    it('returns a response with basic inputs', ()=&gt;
    {
        const result = handler({}, {}, ()=&gt;{});
        responseLike(result).should.be.true;
    });
});</code></pre>
<p>For now the response is always an <a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes">HTTP 200</a>. We can add different ones later. Re-run your tests and she should fail:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5297" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-02-at-11.51.48-AM.png" alt="" width="412" height="245" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-02-at-11.51.48-AM.png 412w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-02-at-11.51.48-AM-300x178.png 300w" sizes="auto, (max-width: 412px) 100vw, 412px" /></p>
<p>Now let&#8217;s modify the function signature of our handler from:</p>
<pre><code>exports.handler = (event, context, callback) =&gt;</code></pre>
<p>to:</p>
<pre><code>const handler = (event, context, callback) =&gt;</code></pre>
<p>Move her above the module.exports and then add her to the exports. Final Lambda should look like this:</p>
<pre><code>const alwaysTrue = ()=&gt; true;
const getRandomNumberFromRange = (start, end)=&gt;
{
	const range = end - start;
	let result = Math.random() * range;
	result += start;
	return Math.round(result);
};

const handler = (event, context, callback) =&gt;
{
    const response = {
        statusCode: '200',
        body: JSON.stringify({result: true, data: 'Hello from Lambda'}),
        headers: {
            'Content-Type': 'application/json',
        }
    }
    callback(null, response);
};

module.exports = {
    alwaysTrue,
    getRandomNumberFromRange,
    handler
};</code></pre>
<p>Our Lambda will return random numbers in the response based on the range you give it. We&#8217;ll have to create some predicates to ensure we actually get numbers, they are within range, and then return error messages appropriately. Our response in our handler will start to be different based on if someone passes in good numbers, bad numbers, bad data, or if it&#8217;s just a test. So, we&#8217;ll need to make him dynamic. Finally, we&#8217;ll add a flag in the event to make integration testing easier.</p>
<p>First, the litany of predicates for input checking. You&#8217;ll need 2 helper functions to make this easier. Create a new JavaScript file called predicates.js, and put this code into it:</p>
<pre><code>const _ = require('lodash');

const validator = (errorCode, method)=&gt;
{
	const valid = function(args)
	{
		return method.apply(method, arguments);
	};
	valid.errorCode = errorCode;
	return valid;
}

const checker = ()=&gt;
{
	const validators = _.toArray(arguments);
	return (something)=&gt;
	{
		return _.reduce(validators, (errors, checkerFunction)=&gt;
		{
			if(checkerFunction(something))
			{
				return errors;
			}
			else
			{
				return _.chain(errors).push(checkerFunction.errorCode).value();
			}
		}, [])
	};
};

module.exports = {
	validator,
	checker
};</code></pre>
<p>Now, let&#8217;s test the new, (soon to be) parameter checked handler in a few situations. At the top of index.test.js, import the handler function:</p>
<pre><code>const {
	alwaysTrue,
    getRandomNumberFromRange,
    handler
} = require('./index');</code></pre>
<p>Let&#8217;s add a new, more brutal negative test where we pass nothing:</p>
<pre><code>it('passing nothing is ok', ()=&gt;
{
    const result = handler();
    responseLike(result).should.be.true;
});</code></pre>
<p>Let&#8217;s look at the responses and ensure we&#8217;re failing because of bad parameters, specifically, a malformed event. One test for a good event, one for a missing end, and one for our echo statement. Since the response is encoded JSON, we create a predicate to parse it out and check the result:</p>
<pre><code>const responseSucceeded = (o)=&gt;
{
    try
    {
        const body = JSON.parse(o.body);
        return body.result === true;
    }
    catch(err)
    {
        return false;
    }
};
// ...
it('succeeds if event has a start and end', ()=&gt;
{
    const response = handler({start: 1, end: 10}, {}, ()=&gt;{});
    responseSucceeded(response).should.be.true;
});
it('fails if event only has start', ()=&gt;
{
    const response = handler({start: 1}, {}, ()=&gt;{});
    responseSucceeded(response).should.be.false;
});
it('succeeds if event only has echo to true', ()=&gt;
{
    const response = handler({echo: true}, {}, ()=&gt;{});
    responseSucceeded(response).should.be.true;
});</code></pre>
<p>None of those will pass. Let&#8217;s make &#8217;em pass. Open index.js, and put in the predicates first. Import her up at the top:</p>
<pre><code>// Note: the below only works in newer Node, 
// not the 4.x version AWS uses
// const { validator, checker } = require('./predicates');
const predicates = require('./predicates');
const validator = predicates.validator;
const checker = predicates.checker;</code></pre>
<p>Then below put your predicate helpers:</p>
<pre><code>// predicate helpers
const eventHasStartAndEnd = (o) =&gt; _.has(o, 'start') &amp;&amp; _.has(o, 'end');
const eventHasTestEcho    = (o) =&gt; _.get(o, 'echo', false);
const isLegitNumber       = (o) =&gt; _.isNumber(o) &amp;&amp; _.isNaN(o) === false</code></pre>
<p>These check the event for both a start and end property, or an echo. Lodash _.isNumber counts NaN as a number, even though NaN stands for &#8220;Not a Number&#8221; and is a Number per the ECMAStandard because &#8220;design by committee&#8221;. I wrangle the insanity by writing my own predicate that&#8230; you know&#8230; makes sense: isLegitNumber.</p>
<p>We&#8217;ll use them to build our argument predicates:</p>
<pre><code>// argument predicates
const legitEvent = (o)=&gt; 
    _.some([
            eventHasStartAndEnd, 
            eventHasTestEcho
        ],
        (predicate) =&gt; predicate(o)
    );
const legitStart = (o) =&gt; isLegitNumber(_.get(o, 'start'));
const legitEnd   = (o) =&gt; isLegitNumber(_.get(o, 'end'));</code></pre>
<p>Now we have a lot of functions to verify if our event is acceptable. However, if it&#8217;s not acceptable, we don&#8217;t know why. Worse, users of your Lambda, both you in 2 weeks when you forgot your code, and other API consumers, won&#8217;t have any clue what they did either without cracking open the CloudWatch logs + your code and attempting to debug it.</p>
<p>We&#8217;ll take this a step further by using those validator and checker functions we imported above. Second, the validators:</p>
<pre><code>// validators
const validObject = validator('Not an Object.', _.isObjectLike);
const validEvent  = validator('Invalid event, missing key properties.', legitEvent);
const validStart  = validator('start is not a valid number.', legitStart);
const validEnd    = validator('end is not a valid number.', legitEnd);</code></pre>
<p>These functions are normal, they just take advantage of JavaScript and just about everything being a dynamic Object. That first parameter, the string error message, you can store on the function, so if it returns false, you know WHY it returned false. The checkers will accumulate those errors using a <a href="http://jessewarden.com/2016/08/beginners-guide-to-functional-programming-part-1.html#reduce">reduce function</a>. Third, the checkers:</p>
<pre><code>// checkers
const checkEvent       = checker(validObject, validEvent);
const checkStartAndEnd = checker(validStart, validEnd);</code></pre>
<p>2 more predicates and we&#8217;re done. All Lambdas are required to have at least 1 response to not blow up. However, you and I know code either works or it doesn&#8217;t. There is middle ground, sure, but for simple stuff, it&#8217;s black and white. We&#8217;ll break those out into 2 predicates for creating our HTTP responses of errors:</p>
<pre><code>const getErrorResponse = (errors)=&gt;
{
    return {
        statusCode: '500',
        body: JSON.stringify({result: false, error: errors.join('\n')}),
        headers: {
            'Content-Type': 'application/json',
        }
    };
};</code></pre>
<p>And success:</p>
<pre><code>const getResponse = (data)=&gt;
{
    return {
        statusCode: '200',
        body: JSON.stringify({result: true, data}),
        headers: {
            'Content-Type': 'application/json',
        }
    }
};</code></pre>
<p>Armed with our predicates, we can have a flexible handler, and if something blows up, we will know why. Let&#8217;s break her down into 5 steps:</p>
<pre><code>const handler = (event, context, callback) =&gt;
{
    if(_.isNil(callback) === true)
    {
        return getErrorResponse(['No callback was passed to the handler.']);
    }
    ...</code></pre>
<p>We&#8217;re ok with no event and context, but no callback!? That&#8217;s crazy talk. Here&#8217;s your t3h boom.</p>
<pre><code>const errors = checkEvent(event);
if(errors.length &gt; 0)
{
    callback(new Error(errors.join('\n')));
    return getErrorResponse(errors);
}</code></pre>
<p>If our event isn&#8217;t legit (either and echo, or having start and end numbers), we send the array of errors we get back to whoever triggered us in an error callback. Instead of &#8220;I didn&#8217;t work&#8221;, they&#8217;ll have a fighting chance of knowing why since we sent them the validation messaging.</p>
<p><b>Quick Security Note</b></p>
<p>I should point out AWS walks the line of being secure and not giving you verbose errors while sometimes giving you what they can without compromising security to help you debug as a developer. You&#8217;ll note that my checkers tend to be verbose in the hope they&#8217;ll help whoever made a mistake. However, as things scale, you must be careful not to expose public information, or reveal too much about what you DON&#8217;T validate. I&#8217;m not a security guy, I don&#8217;t have the answers beyond lots of peer review of code, automated quality checks, and automated security scanning. You&#8217;ll note the obvious of not throwing stack traces back to the client. You can see those in CloudWatch if you wish.</p>
<pre><code>if(event.echo === true)
{
    const echoResponse = getResponse('pong');
    callback(undefined, echoResponse);
    return echoResponse;
}</code></pre>
<p>That&#8217;s for our future integration tests. It&#8217;s easier if our remote code is aware she&#8217;ll be pinged to see if she&#8217;s alive and well. We test for it to ensure it doesn&#8217;t negatively affect others. You can see the work that went into validating it as well as ensuring it played nice with others, yet still supported the ability to be tested without actually doing real work that could lead to leaky state.</p>
<pre><code>const startEndErrors = checkStartAndEnd(event);
if(startEndErrors.length &gt; 0)
{
    callback(new Error(startEndErrors.join('\n')));
    return getErrorResponse(startEndErrors);
}</code></pre>
<p>Finally, we check to ensure if we&#8217;re going to do the random number generation, we have what we need from the event to do so, else, blow up and explain why. The real work is the end of the function:</p>
<pre><code>const start        = _.get(event, 'start');
    const end          = _.get(event, 'end');
    const randomNumber = getRandomNumberFromRange(start, end);
    const response     = getResponse(randomNumber);
    callback(undefined, randomNumber);
    return response;
};</code></pre>
<p>Now re-running your tests should result in them all passing:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5300" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-7.00.31-PM.png" alt="" width="380" height="213" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-7.00.31-PM.png 380w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-7.00.31-PM-300x168.png 300w" sizes="auto, (max-width: 380px) 100vw, 380px" /></p>
<h2>Manual Test</h2>
<p>One last manual test you can do as well is simply run her in the node REPL. In the Terminal, type &#8220;node&#8221; and hit enter.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5301" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.04.14-PM.png" alt="" width="454" height="54" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.04.14-PM.png 454w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.04.14-PM-300x36.png 300w" sizes="auto, (max-width: 454px) 100vw, 454px" /></p>
<p>Then import your index module by typing <code>lambda = require('./index')</code> and hitting enter:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5302" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.05.52-PM.png" alt="" width="468" height="106" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.05.52-PM.png 468w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.05.52-PM-300x68.png 300w" sizes="auto, (max-width: 468px) 100vw, 468px" /></p>
<p>You&#8217;ll see our 3 functions we exposed. AWS only cares about your handler, so let&#8217;s manually test ours with some bogus data. Type <code>lambda.handler()</code> and hit enter, and you should see a 500 response:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5303" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.07.23-PM.png" alt="" width="540" height="74" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.07.23-PM.png 540w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.07.23-PM-300x41.png 300w" sizes="auto, (max-width: 540px) 100vw, 540px" /></p>
<p>Now let&#8217;s mirror our unit test by using, and give it some good inputs via <code>handler({echo: true}, {}, ()=&gt;{});</code> to get a basic 200 response:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5304" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.09.29-PM.png" alt="" width="370" height="81" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.09.29-PM.png 370w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.09.29-PM-300x66.png 300w" sizes="auto, (max-width: 370px) 100vw, 370px" /></p>
<p>You can Control + C twice to get out of Node.</p>
<p>Skills. Unit tests work, and a manual test works. Now you can be assured if you upload to AWS and she breaks, it&#8217;s them not you. Yes, your problem, but thankfully your self-esteem shall remain intact. Remember, part of programming is deflecting blame to others, backing it up with fancy terms like &#8220;I have lots of TDD code coverage&#8221;, then fixing &#8220;their&#8221; problem and looking like a hero.</p>
<h2>Deploy Testable Code to AWS To Test There</h2>
<p>Speaking of AWS, let&#8217;s redeploy and test our more testable code up on AWS. This&#8217;ll be a common task you do again and again by testing code locally, then re-deploying to test it on AWS. We&#8217;ll suffer through it for a bit so we appreciate the automating of it later.</p>
<p>For now, let&#8217;s adjust your makezip script in package.json to add our new files. We have to add predicates.js and our libraries which are in node_modules:</p>
<pre><code>"makezip": "zip -r -X deploy.zip index.js predicates.js node_modules",</code></pre>
<p>We&#8217;ll hardcode our build script for now to destroy our stack first, then recreate it with whatever deploy.zip it finds locally. Open up build.js, and at the bottom, let&#8217;s chain together our deleteFunction &amp; createFunction:</p>
<pre><code>deleteFunction(lambda, (err, data)=&gt;{
    log("deleteFunction");
    log("err:", err);
    log("data:", data);
    createFunction(lambda, fs, (err, data)=&gt;
    {
        log("createFunction");
        log("err:", err);
        log("data:", data);
    });
});</code></pre>
<p>You may get an error the first time since no function may be up there to delete and that&#8217;s ok. We&#8217;re creating &amp; fixing one thing at a time. For now, it&#8217;s good enough if she creates your zip file and uploads it to your newly created Lambda function. We&#8217;re not differentiating between dependencies and development dependencies in node_modules, so your deploy.zip will be quite large, and may take more time to upload now that she&#8217;s not just under 1kb of text.</p>
<p>Run npm run deletezip, then npm run makezip, then node build&#8230; or just:</p>
<pre><code>npm run deletezip &amp;&amp; npm run makezip &amp;&amp; node build</code></pre>
<p>Log into your AWS Console and under Services choose Lambda. You should see your function in the list (they&#8217;re often sorted by newest up top). Notice she&#8217;s 4+ megs, t3h lulz. #myFLAFilesWereBigRaR #backInTheDay</p>
<p>Click it, and let&#8217;s test it. You&#8217;ll see a big blue button at the top called &#8220;Test&#8221;. Click it. It should blow up with our custom blow up message:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5305" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.36.40-PM.png" alt="" width="805" height="266" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.36.40-PM.png 805w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.36.40-PM-300x99.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-8.36.40-PM-768x254.png 768w" sizes="auto, (max-width: 805px) 100vw, 805px" /></p>
<p>Hot, let&#8217;s see if she correctly responds to our manual integration test. Click &#8220;Actions&#8221; and &#8220;Configure Test Event&#8221;. Here, you can basically make up your own event JSON to test your Lambda and it&#8217;ll run on AWS infrastructure. Ours is pretty simple, echo true. When done click Save and Test.<img loading="lazy" decoding="async" class="alignnone size-full wp-image-5306" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-9.23.12-PM.png" alt="" width="837" height="805" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-9.23.12-PM.png 837w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-9.23.12-PM-300x289.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-9.23.12-PM-768x739.png 768w" sizes="auto, (max-width: 837px) 100vw, 837px" /></p>
<p>Now be careful; sometimes this window has a glitch where it&#8217;ll save &#8220;echo&#8221;: &#8220;true&#8221; instead of &#8220;echo&#8221;: true. The &#8220;true&#8221; String is not the same as the true Boolean that we want. All goes well, you&#8217;ll see:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5308" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-9.22.37-PM.png" alt="" width="394" height="195" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-9.22.37-PM.png 394w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-9.22.37-PM-300x148.png 300w" sizes="auto, (max-width: 394px) 100vw, 394px" /></p>
<p>DAT PONG! Last manual test, let&#8217;s generate a random number. Again click Actions and Configure Test Event, and replace the fixture with:</p>
<pre><code>{
  "start": 1,
  "end": 10
}</code></pre>
<p>Save and Test&#8230;</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5309" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-10-at-9.27.07-PM.png" alt="" width="45" height="61" /></p>
<p>I got a 5, what&#8217;d you get?<br />
<a name="step8"></a></p>
<h1>Step 8: Build a Command-line Tool</h1>
<p>To make our build.js more flexible, we&#8217;ll have to create our first command-line program in Node. There are a few command-line parsing libraries out there, but we&#8217;ll just create our own predicates so you learn how to do it yourself, this&#8217;ll be commonplace in creating command-line tools for yourself, and we won&#8217;t have <a href="https://twitter.com/jesterxl/status/819370700792352769">weird test errors</a> (hence the image).</p>
<p>Open build.js, and delete our buildFunction &amp; creatFunction calls at the very bottom. We&#8217;re removing that hardcoded; instead of constantly modifying build.js, we&#8217;ll make it do what we want when we run it. Next, open up package.json, and let&#8217;s include both our tests now vs. switching between index or the build.</p>
<pre><code>"scripts": {
    "test": "mocha *.test.js",</code></pre>
<p>If you&#8217;ve never used globs before, that&#8217;s what the star is. It says &#8220;anything that has a .test.js suffix in the filename&#8221;. We have 2 tests, so if you run npm test now, you&#8217;ll get:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5312" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-11-at-8.17.30-PM.png" alt="" width="778" height="768" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-11-at-8.17.30-PM.png 778w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-11-at-8.17.30-PM-300x296.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-11-at-8.17.30-PM-768x758.png 768w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-11-at-8.17.30-PM-100x100.png 100w" sizes="auto, (max-width: 778px) 100vw, 778px" /></p>
<p>Green is gorrrrrrrgeous.</p>
<p>Let&#8217;s create a stub since this&#8217;ll be a constant create, add, test fail, test succeed workflow. Open build.js, and add:</p>
<pre><code>const getProgram = (argsv)=&gt;
{

};</code></pre>
<p>Then at the bottom export him:</p>
<pre><code>module.exports = {
    ...
    getProgram
};</code></pre>
<p>In build.test.js, import our getProgram function:</p>
<pre><code>const {
	...
	getProgram
} = require('./build');</code></pre>
<p>We&#8217;re going to give this function our command line parameters and expect him to interpret what we meant.</p>
<pre><code>describe.only('#getProgram', ()=&gt;
{
	it('should not build with no parameters', ()=&gt;
	{
		const program = getProgram();
		expect(program.action).to.equal(ACTION_NOTHING);
	});
});</code></pre>
<p>Now re-run npm test, and she&#8217;ll fail properly:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5313" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-11-at-8.23.03-PM.png" alt="" width="816" height="350" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-11-at-8.23.03-PM.png 816w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-11-at-8.23.03-PM-300x129.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-11-at-8.23.03-PM-768x329.png 768w" sizes="auto, (max-width: 816px) 100vw, 816px" /></p>
<p>&nbsp;</p>
<p>To make it pass, we just need to return a no-op (meaning, no operation, don&#8217;t do anything).</p>
<pre><code>const getProgram = (argsv)=&gt;
{
    if(_.isArray(argsv) === false)
    {
        return {action: 'nothing'};
    }
    
};</code></pre>
<p>Re-run tests and it should pass:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5317" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-10.56.41-AM.png" alt="" width="628" height="194" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-10.56.41-AM.png 628w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-10.56.41-AM-300x93.png 300w" sizes="auto, (max-width: 628px) 100vw, 628px" /></p>
<p>There are the 3 things our program should do: nothing, build, and destroy.</p>
<pre><code>const ACTION_NOTHING = 'nothing';
const ACTION_BUILD   = 'build';
const ACTION_DESTROY = 'destroy';</code></pre>
<p>And export &#8217;em out at the bottom of build.js:</p>
<pre><code>module.exports = {
    ...
    ACTION_BUILD,
    ACTION_DESTROY,
    ACTION_NOTHING
};</code></pre>
<p>To know which one, we&#8217;ll have to parse <code>process.argsv</code>, an array that holds all the arguments passed when starting a Node program.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5318" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-11.02.36-AM.png" alt="" width="1262" height="204" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-11.02.36-AM.png 1262w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-11.02.36-AM-300x48.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-11.02.36-AM-768x124.png 768w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-11.02.36-AM-1024x166.png 1024w" sizes="auto, (max-width: 1262px) 100vw, 1262px" /></p>
<p>The first, the location to the Node binary running it, and second, the build that&#8217;s being run, we don&#8217;t care about. Everything AFTER is fair game&#8230; or there could be dragons there; command-line programs are easy to fat finger (mis-type) so our Array could have some cray text in it.</p>
<p>We&#8217;ll strip out those first 2 items, and create some predicates that search for their items. The following predicates will get an Array, and see if -b or &#8211;build is in there.</p>
<pre><code>const hasBigBuild   = (array) =&gt; _.includes(array, '--build');
const hasSmallBuild = (array) =&gt; _.includes(array, '-b');
const hasBuild      = (array) =&gt; hasBigBuild(array) || hasSmallBuild(array);</code></pre>
<p>And these for destroy:</p>
<pre><code>const hasBigDestroy   = (array) =&gt; _.includes(array, '--destroy');
const hasSmallDestroy = (array) =&gt; _.includes(array, '-d');
const hasDestroy      = (array) =&gt; hasBigDestroy(array) || hasSmallDestroy(array);</code></pre>
<p>If you have both, we&#8217;ll make the assumption now that you want to destroy your stack first, then build a fresh new one. This is a pretty common practice we&#8217;ll be doing, so we&#8217;ll bake in this assumption now vs. coding error logic for telling the developer they provided competing instructions. So let&#8217;s add that instruction to avoid ambiguity, and the predicate to test for it.</p>
<pre><code>const ACTION_DESTROY_AND_BUILD = 'destroy and build';
...
const hasDestroyAndBuild = (array) =&gt; hasBuild(array) &amp;&amp; hasDestroy(array);
...
module.exports = {
    ...
    ACTION_DESTROY_AND_BUILD
};</code></pre>
<p>Let&#8217;s create a new test detecting our build instructions. In build.test.js, import the action up top:</p>
<pre><code>const {
	...
	ACTION_BUILD
} = require('./build');</code></pre>
<p>Then the test:</p>
<pre><code>it('should build if we tell it to do so', ()=&gt;
{
	const parameters = [
		'node is rad',
		'testing bro',
		'--build'
	];
	const program = getProgram(parameters);
	expect(program.action).to.equal(ACTION_BUILD);
});</code></pre>
<p>Run your test and she should boom:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5319" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-11.15.34-AM.png" alt="" width="850" height="382" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-11.15.34-AM.png 850w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-11.15.34-AM-300x135.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-11.15.34-AM-768x345.png 768w" sizes="auto, (max-width: 850px) 100vw, 850px" /></p>
<p>Add this to the bottom of the getProgram function:</p>
<pre><code>if(hasBuild(argsv) === true)
{
    return {action: ACTION_BUILD};
}</code></pre>
<p>Now re-run your tests:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5322" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-2.59.30-PM.png" alt="" width="606" height="208" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-2.59.30-PM.png 606w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-2.59.30-PM-300x103.png 300w" sizes="auto, (max-width: 606px) 100vw, 606px" /></p>
<p>&#8230; and the destroy test in build.test.js, import destroy action:</p>
<pre><code>const {
	...
	ACTION_DESTROY
} = require('./build');</code></pre>
<p>And the test:</p>
<pre><code>it('should destroy if we tell it to do so', ()=&gt;
{
	const parameters = [
		'node is rad',
		'testing bro',
		'--destroy'
	];
	const program = getProgram(parameters);
	expect(program.action).to.equal(ACTION_DESTROY);
});</code></pre>
<p>Running it should show the failure:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5323" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-3.14.35-PM.png" alt="" width="862" height="410" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-3.14.35-PM.png 862w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-3.14.35-PM-300x143.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-3.14.35-PM-768x365.png 768w" sizes="auto, (max-width: 862px) 100vw, 862px" /></p>
<p>To make it pass, we need to check for a destroy below (or above) the build:</p>
<pre><code>if(hasDestroy(argsv) === true)
{
    return {action: ACTION_DESTROY};
}</code></pre>
<p>And re-running the tests should show passing:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5324" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-3.20.23-PM.png" alt="" width="636" height="232" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-3.20.23-PM.png 636w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-14-at-3.20.23-PM-300x109.png 300w" sizes="auto, (max-width: 636px) 100vw, 636px" /></p>
<p>Finally, let&#8217;s test for both. Import the action:</p>
<pre><code>const {
	...
	ACTION_DESTROY_AND_BUILD
} = require('./build');</code></pre>
<p>and copy paste the test:</p>
<pre><code>it('should destroy and build', ()=&gt;
{
	const parameters = [
		'node is rad',
		'testing bro',
		'--destroy',
		'--build'
	];
	const program = getProgram(parameters);
	expect(program.action).to.equal(ACTION_DESTROY_AND_BUILD);
});</code></pre>
<p>To make it pass, let&#8217;s add the final piece to our build.js:</p>
<pre><code>const getProgram = (argsv)=&gt;
{
    if(_.isArray(argsv) === false)
    {
        return {action: ACTION_NOTHING};
    }

    if(hasDestroyAndBuild(argsv) === true)
    {
        return {action: ACTION_DESTROY_AND_BUILD};
    }

    if(hasBuild(argsv) === true)
    {
        return {action: ACTION_BUILD};
    }

    if(hasDestroy(argsv) === true)
    {
        return {action: ACTION_DESTROY};
    }

    return {action: ACTION_NOTHING};
};</code></pre>
<p>Re-run your tests:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5326" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-9.20.40-AM.png" alt="" width="628" height="262" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-9.20.40-AM.png 628w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-9.20.40-AM-300x125.png 300w" sizes="auto, (max-width: 628px) 100vw, 628px" /></p>
<p>Now that we can parse command-line parameters, let&#8217;s write the code that will perform those actions. No tests for this function, just copy pasta this into build.js:</p>
<pre><code>const performActionIfPassed = (callback)=&gt;
{
    const program = getProgram(process.argv);
    if(program.action === ACTION_BUILD)
    {
        createFunction(lambda, fs, callback);
    }
    else if(program.action === ACTION_DESTROY)
    {
        deleteFunction(lambda, callback);
    }
    else if(program.action === ACTION_DESTROY_AND_BUILD)
    {
        deleteFunction(lambda, (err, data)=&gt;
        {
            createFunction(lambda, fs, callback);
        });
    }
};</code></pre>
<p>Then at the bottom, we&#8217;ll use a snippet to identify if we&#8217;re running through <code>node build.js</code> then run our build code; if not, our build.js is being required, so do nothing.</p>
<pre><code>if(require.main === module)
{
    performActionIfPassed((err, data)=&gt;
    {
        log("Done.");  
    });
}</code></pre>
<p>Let&#8217;s take her for a spin. Open up your Terminal, cd to the code directory, and run <code>node build --build --destroy</code>. If you left your logging uncommented, she may just sit there for a bit as it uploads the zip file (remember, she&#8217;s big currently). Also, deleteFunction may throw an error if the function isn&#8217;t created, and that&#8217;s ok.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5327" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.09.28-AM.png" alt="" width="2198" height="416" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.09.28-AM.png 2198w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.09.28-AM-300x57.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.09.28-AM-768x145.png 768w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.09.28-AM-1024x194.png 1024w" sizes="auto, (max-width: 2198px) 100vw, 2198px" /></p>
<p>My deleteFunction through an error, but that&#8217;s ok, the create worked. Now that we have a function, let&#8217;s try just a destroy via <code>node build --destroy</code>:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5328" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.10.50-AM.png" alt="" width="1124" height="116" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.10.50-AM.png 1124w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.10.50-AM-300x31.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.10.50-AM-768x79.png 768w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.10.50-AM-1024x106.png 1024w" sizes="auto, (max-width: 1124px) 100vw, 1124px" /></p>
<p>And looking at our Lambda function list again:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5329" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.11.28-AM.png" alt="" width="2194" height="504" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.11.28-AM.png 2194w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.11.28-AM-300x69.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.11.28-AM-768x176.png 768w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.11.28-AM-1024x235.png 1024w" sizes="auto, (max-width: 2194px) 100vw, 2194px" /></p>
<p>Yay! Lastly, let&#8217;s just do a single build via <code>node build --build</code>:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5330" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.13.06-AM.png" alt="" width="2204" height="586" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.13.06-AM.png 2204w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.13.06-AM-300x80.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.13.06-AM-768x204.png 768w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.13.06-AM-1024x272.png 1024w" sizes="auto, (max-width: 2204px) 100vw, 2204px" /></p>
<p>Last step in this adventure is to make this all 1 command. Open your package.json, and let&#8217;s add a new script:</p>
<pre><code>"scripts": {
    ...
    "deploy": "npm run deletezip &amp;&amp; npm run makezip &amp;&amp; node build --destroy --build"
  },</code></pre>
<p>Now, anytime you change code and want to re-test it, simply run <code>npm run deploy</code>.<br />
<a name="step9"></a></p>
<h1>Step 9: Multiple Environments &amp; Green Blue Deployment</h1>
<h2>Background on Environments</h2>
<p>We use multiple environments for a lot of reasons. Here are the 2 most important:</p>
<ol>
<li>Your code can continue serving customers while you work on it.</li>
<li>Your code often breaks when it moves to a new environment. You create at least 3 so there is no penalty of breaking production when you move your code from a dev to qa. Once you&#8217;ve practiced this a couple times, you can make the hopefully more confident move from qa to prod.</li>
</ol>
<p>Environments are a higher level term, but usually mean a different server with a different URL or IP address. Even servers that are the exact same hardware, OS, versions, and software still can have code break. Some issues you know about, others are part of the discovery process of moving environments.</p>
<p>There is no standard. The most typical is dev for &#8220;developers to play with code&#8221;. QA for &#8220;quality assurance people to test the most solid code&#8221;. Staging as the last environment change check before prod. Prod is production.</p>
<p>Some teams use more. Some use less.</p>
<p>While there is a strong push towards immutable infrastructure, prod still remains special. In immature software organizations, prod is often the only thing users see. There is a trick to ensure prod remains working when you push new code to it called <a href="https://martinfowler.com/bliki/BlueGreenDeployment.html">green / blue deployment</a>. You create 2 virtual servers on prod. They are identical with one difference: one has a name of green, and one of blue. Users are using a URL to see the green server. You move code to blue. Once you validate blue is working, you switch the URL to point to blue. This is really fast. Sometimes. This is also really easy to undo if something goes wrong. Sometimes.</p>
<h2>Environments for Lambdas?</h2>
<p>Given that Lambdas are &#8220;always up&#8221;, yet you&#8217;re only charged for when they actually run, do you really care about environments? What about green / blue deployment?</p>
<p>Sadly, yes.</p>
<h3>Security</h3>
<p>you&#8217;ll still potentially have different security in place for each environment. In AWS&#8217; case, this is VPC (virtual private cloud), subnets, and security groups (things that determine what you can do, what ports are open, etc).</p>
<h3>Dev&#8217;s Use Dev</h3>
<p>You&#8217;ll have users and other developers in the case of microservices, actively depending upon certain environments to be accessible and behave a certain way.</p>
<h3>Dev&#8217;s Use QA for their QA</h3>
<p>Microservices additionally are often a chain in a larger application, many they intentionally don&#8217;t know about. As such, other teams may use your QA service in their QA environment to mirror how you&#8217;re developing software.</p>
<h3>No Downtime</h3>
<p>Updating a Lambda, while super quick (seconds if just updating the function code without publishing a new version), you&#8217;ll still experience downtime if someone&#8217;s hitting that server.</p>
<h3>Rollback Window</h3>
<p>If you update a Lambda and break the code, you increase that break window until your rollback to old code is finished. Lambda versions can potentially help here. (I don&#8217;t use them)</p>
<h2>Green / Blue with Lambdas</h2>
<p>Finally, the easiest way to update production Lambdas is still green/blue. Users can actively be using them, or they can be being used in an activate AWS Step Function process, and you can ensure you don&#8217;t cause them downtime. The muddy ground here is &#8220;What is the URL?&#8221;</p>
<p>For example, not all Lambdas are triggered by an API Gateway URL. While you can change the Lambda function an API Gateway is aimed at by just changing the ARN, things get a tincy bit more complicated with S3 bucket, SNS, and CloudWatch notifications. For example, at the time of this writing S3 buckets only allow 1 bucket notification, per bucket. You can remove that notification and add it back, but if you&#8217;re dealing with extremely low latency systems, you can miss Object:put events to the bucket while your infrastructure code is running. There are remedial steps here, no doubt, just recognize that green / blue still is a useful deployment pattern to minimize downtime, regardless of environment.</p>
<p>For use, we&#8217;ll use the name, such as &#8220;myLambda-green&#8221; and &#8220;myLambda-blue&#8221;. The S3 bucket policy, or API Gateway URL, or whatever, points to that named Lambda.</p>
<h2>Where Does Environment Go?</h2>
<p>Two places. There are 2 people who care about the environment: You, and the Lambda. You put it as part of the Lambda name so can easily scan the function list in the Lambda console, debug in CloudWatch easier, and the Lambda itself can help log. You&#8217;ll end up with many lambdas in a list that have the name &#8220;myLambda-dev-green&#8221;, &#8220;myLambda-dev-blue&#8221;, &#8220;myLambda-qa-green&#8221;, etc.</p>
<p>The Lambda consumes what environment it&#8217;s in from environment variables which can be encrypted if you wish. This ensures your code has no state, and just adopts whatever is there, regardless of it&#8217;s name. Given many enterprises have separate AWS accounts for both different parts of the organization, and production environments, you can help minimize the pain by making your code stateless and configurable by the environment variables.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5332" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.42.59-AM.png" alt="" width="2218" height="900" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.42.59-AM.png 2218w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.42.59-AM-300x122.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.42.59-AM-768x312.png 768w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-11.42.59-AM-1024x416.png 1024w" sizes="auto, (max-width: 2218px) 100vw, 2218px" /></p>
<h2>Regions</h2>
<p>Regions get a bit more complicated, but the short version is you just follow the same pattern of explicitly naming them and use environment variables. Many AWS function require a region parameter, so avoid typing &#8216;us-east-1&#8217; directly into your code.</p>
<h2>So&#8230; what do I do again?</h2>
<p>Same Lambda, just different name for it to differentiate between dev, qa, and prod as well as green and blue. Your createFunction just has a different string. For example, &#8220;myLambda-green&#8221; and &#8220;myLambda-blue&#8221;. If you use environments, you can put those in the name too: &#8220;myLambda-qa-green&#8221; and &#8220;myLambda-qa-blue&#8221;.</p>
<p>In our code above, we&#8217;ve defined dev without a color, but you could simple add more strings:</p>
<pre><code>const DEFAULT_ENVIRONMENT = 'dev';
const COLOR               = 'green';
const FUNCTION_NAME       = NAME_PREFIX + '-' + DEFAULT_ENVIRONMENT + '-' + COLOR;</code></pre>
<p>Then run <code>node build --build</code> fro each color and environment.</p>
<h2>Wait, Why Not Aliases and Versions?</h2>
<p>Lambda Alises (dev, qa, and prod, green, blue, staging, live), and the Versions they point to (1, $LATEST, Git tag v2.3.7) are great. They allow for potentially easier management of environments and code versions to be managed in a centralized place if you use the AWS Console heavily. However, configuration and environment variables are global and can only be modified in $LATEST version.</p>
<p>Given I work in a high security environment where I test multiple configurations, and unlike S3 buckets, we currently do not have a cost in creating multiple Lambdas, it&#8217;s more flexible for the workflow my team has.<br />
<a name="step10"></a></p>
<h1>Step 10: Integration Test</h1>
<p>We unit tested her locally. We manually tested her locally. We manually tested her remotely. In Step 7 we added an echo to more easily test if our Lambda is working without having it do actual work. Let&#8217;s automate all that.</p>
<p>Our first integration test invokes the Lambda function. It&#8217;s almost exactly the same thing as clicking the Test button, except Node is doing it instead of your finger. Create a new file called index.integrationtest.js and copy pasta this code into it:</p>
<pre><code>const AWS      = require('aws-sdk');
AWS.config.loadFromPath('./credentials.json');
const lambda   = new AWS.Lambda();
const log = console.log;

const expect = require("chai").expect;
const should = require('chai').should();
const {
    handler
} = require('./index');


describe('#index integration', function()
{
    this.timeout(10 * 1000);

    describe('#echo', ()=&gt;
    {
        it('responds to an echo', (done)=&gt;
        {
            var params = {
                FunctionName: "datDJMicrodev", 
                Payload: JSON.stringify({echo: true})
            };
            lambda.invoke(params, (err, data)=&gt;
            {
                log("err:", err);
                log("data:", data);
                done(err);
            });
        });
    });
});</code></pre>
<p>This will send the <code>echo</code> to our Lambda, and she&#8217;ll send the <code>pong</code> back. Run it by <code>mocha index.integrationtest.js</code> and she should report a true:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5333" src="http://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-2.42.46-PM.png" alt="" width="1868" height="306" srcset="https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-2.42.46-PM.png 1868w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-2.42.46-PM-300x49.png 300w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-2.42.46-PM-768x126.png 768w, https://jessewarden.com/wp-content/uploads/2017/01/Screen-Shot-2017-01-15-at-2.42.46-PM-1024x168.png 1024w" sizes="auto, (max-width: 1868px) 100vw, 1868px" /><br />
<a name="Conclusions"></a></p>
<h1>Conclusions</h1>
<p>Creating a microservice for AWS Lambda is easy and straightforward. We&#8217;ve built one here in this article. Typically, though, you build many of them. Even if you&#8217;re building a monolith application, and your one microservice is pretty large, all the deployment problems still exist. As you&#8217;ve hopefully seen, AWS API&#8217;s give you powerful tools to put both the deployment and testing of those deployments in your hands.</p>
<p>As a developer, you can now write the microservice, tooling, testing, and deployment all in the same language in the same code repository. This code that handles your infrastructure follows the same peer review and unit/integrating testing best practices. Your infrastructure is now testable, high quality code controlled by you, the developer. While we&#8217;ve created multiple Lambdas that represent their environment and version, AWS provides powerful tools to handle Lambda Aliases and Versions, both in code and in the AWS console.</p>
<p>Frameworks like Serverless help you manage multiple services, have a nice way to test locally, and help you if you&#8217;re not familiar with AWS. YAML isn&#8217;t code, however. Writing your service, and infrastructure, in the same language helps you adopts the same testing and debugging practices for it.</p>
<h1>Code (again in case you missed it)</h1>
<p>The <a href="https://github.com/JesterXL/build-destroy-test-lambda">source code</a> for this article is on Github.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>AWS Adventures: Part 1 &#8211; Lambda</title>
		<link>https://jessewarden.com/2016/12/aws-adventures-part-1-lambda.html</link>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Wed, 28 Dec 2016 22:46:00 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[apigateway]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[infrastructure]]></category>
		<category><![CDATA[lambda]]></category>
		<category><![CDATA[microservices]]></category>
		<category><![CDATA[s3]]></category>
		<category><![CDATA[servers]]></category>
		<guid isPermaLink="false">http://jessewarden.com/?p=5254</guid>

					<description><![CDATA[Introduction At the beginning of October, I started a new project to help my team move a 12 year old application to the cloud. I knew next to nothing about Amazon, or their infrastructure offerings called AWS. In the past 3 months I&#8217;ve learned a ton. Today I wanted to share what I&#8217;ve learned about [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Introduction</h1>
<p>At the beginning of October, I started a new project to help my team move a 12 year old application to the cloud. I knew next to nothing about Amazon, or their infrastructure offerings called AWS. In the past 3 months I&#8217;ve learned a ton. Today I wanted to share what I&#8217;ve learned about Lambdas: Functions you run in AWS.</p>
<p>Also known as serverless architecture.<br />
<span id="more-5254"></span></p>
<h1>What is AWS?</h1>
<p>AWS is short for Amazon Web Services. Amazon provides you a bunch of different services that help you build software, almost all of which they host.</p>
<h1>What Are Lambdas?</h1>
<p>Lambdas are one of their offerings that have been out over a year. The selling points of Lambdas are Amazon sets up and maintains the server for you, and you&#8217;re only charged for how long your code actually runs. You upload code and it just works.</p>
<h1>Why Not Use an EC2 Instead?</h1>
<p>An EC2 is Amazon&#8217;s virtual machine servers. You have to build and maintain them yourself. You pay to keep them running even when they aren&#8217;t handling any traffic. You have to rebuild them when new AMI&#8217;s (virtual machine templates) come out from Amazon. Things get really challenging when you scale dynamically for spikes in traffic.</p>
<h2></h2>
<h1>Why Not Docker?</h1>
<p>While <a href="https://www.docker.com/">Docker</a> makes some of the above less painful, especially when testing in Jenkins or testing on other developers machines, you still have all the same issues. You build the docker image and manage them through a container service like DockerSwarm or <a href="https://www.consul.io/">Consul</a>. The images themselves have to be managed by someone in DockYard.</p>
<h1>Why Lambdas</h1>
<h2>I&#8217;m A Front-End Developer</h2>
<p>If I want to run my JavaScript in the cloud, I don&#8217;t care about the OS, what&#8217;s installed on it, and all the details about keeping it running and refreshed with security updates. Amazon does and handles all that for you.</p>
<p>Lamba&#8217;s are just code, you don&#8217;t have to maintain the server or infrastructure, you only pay for what you use, and they automatically scale based on traffic.</p>
<p>If you&#8217;re a front-end developer like me who just wants to write code, and you&#8217;re keen on building <a href="http://samnewman.io/patterns/architectural/bff/">a back-end API for the front end</a>, they&#8217;re perfect.</p>
<h2>Lambdas Are Reactive and Event Driven</h2>
<p>One additional feature of Lambdas is their built in events. They are &#8220;reactive&#8221; by default. It&#8217;s assumed Lambdas are triggered by other AWS things. Things in this case being API Gateway for REST API&#8217;s such as GET and POST, S3 when you drop files on it, SNS for a basic message bus, or even JSON written into logs through CloudWatch. There also are the building blocks for distributed architecture in Step Functions.</p>
<h2>Simpler Continuous Deployment</h2>
<p>Trying to get monoliths, big applications where all the code is bundled together, deployed to production is hard. Getting this done often is even harder. One of the benefits microservices give you is easier deployment. You can deploy &#8220;one thing&#8221; without having to worry about the &#8220;other things&#8221;.</p>
<p>Anyone who&#8217;s had back-end developers deploy new API&#8217;s, or you deploying new front end code knows that&#8217;s a loaded statement. Unless you&#8217;ve done some integration and functional testing or you&#8217;ve deployed the code to a QA or staging environment which mimics production, you don&#8217;t &#8220;know&#8221; the code works.</p>
<p>If you define clear API&#8217;s upfront, keep the microservices truly simple in their functionality, this process becomes much simpler, and eases CI down the line.</p>
<h1>Are Lambdas Microservices?</h1>
<p>They can be <a href="http://www.martinfowler.com/articles/microservices.html">microservices</a>, but no, not by default. They are just a function. Microservices typically are accessed by a REST API. If you trigger them by an API Gateway (a restful URL provided by Amazon), then yes, they become microservices.</p>
<h1>Build A Microservice</h1>
<p>If you want to build a RESTful microservice with Lambda&#8217;s, you first have to have an AWS account. Assuming you have that, login and access the console (the AWS web interface).</p>
<h2>Step 1: Build A HelloWorld Lambda</h2>
<p>Click the &#8220;Services&#8221; button/menu, and select/search for &#8220;Lambda&#8221;, then click &#8220;Create a Lambda Function&#8221;.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5257" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-4.56.30-PM.png" alt="" width="1310" height="456" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-4.56.30-PM.png 1310w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-4.56.30-PM-300x104.png 300w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-4.56.30-PM-768x267.png 768w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-4.56.30-PM-1024x356.png 1024w" sizes="auto, (max-width: 1310px) 100vw, 1310px" /></p>
<p>In Runtime select &#8220;Node&#8221;; version doesn&#8217;t matter, just ensure not Edge for now. For template, click on &#8220;Blank Function&#8221;.</p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-5258 size-full" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-4.57.26-PM-e1482962313250.png" width="310" height="342" /></p>
<h2>Step 2: Choose A Trigger</h2>
<p>Click the empty box and choose &#8220;API Gateway&#8221;. Make up an API Name, choose &#8220;api&#8221; for deployment stage, and choose &#8220;Open&#8221; for security. Click &#8220;Next&#8221;.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5259" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-4.59.06-PM.png" alt="" width="1850" height="596" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-4.59.06-PM.png 1850w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-4.59.06-PM-300x97.png 300w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-4.59.06-PM-768x247.png 768w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-4.59.06-PM-1024x330.png 1024w" sizes="auto, (max-width: 1850px) 100vw, 1850px" /></p>
<h2>Step 3: Configure</h2>
<p>Pick a camel case (ex: likeThisMan) name. Scroll down to Role, and choose &#8220;Create a new role from template(s)&#8221;. Create a basic camel case role name such as &#8220;myCustomTemplateRole&#8221;. Scroll to the bottom and click &#8220;Next&#8221;, then on the next screen scroll to the bottom and click &#8220;Create function&#8221;.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5260" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.01.24-PM.png" alt="" width="1824" height="666" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.01.24-PM.png 1824w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.01.24-PM-300x110.png 300w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.01.24-PM-768x280.png 768w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.01.24-PM-1024x374.png 1024w" sizes="auto, (max-width: 1824px) 100vw, 1824px" /></p>
<p>You&#8217;re done!</p>
<p>Note it usually dumps you on the Trigger tab (what causes your Lambda function to run). In our case, it should show the URL for our API Gateway. Copy this to your clipboard or a notepad/textedit for later use.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5261" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.02.29-PM.png" alt="" width="2464" height="802" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.02.29-PM.png 2464w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.02.29-PM-300x98.png 300w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.02.29-PM-768x250.png 768w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.02.29-PM-1024x333.png 1024w" sizes="auto, (max-width: 2464px) 100vw, 2464px" /></p>
<p>It generates a basic function for you. You can see it by clicking the Code tab:</p>
<pre><code>exports.handler = (event, context, callback) => {
    callback(null, 'Hello from Lambda');
};</code></pre>
<p>&nbsp;</p>
<h1>Test &amp; Iterate On Your Microservice</h1>
<h2>Step 4: Test</h2>
<p>Click the blue &#8220;Test&#8221; button. In the new popup, the sample event template should be &#8220;Hello World&#8221;. Click &#8220;Save and Test&#8221;, and you should see &#8220;Hello from Lambda&#8221; below the execution result. Great, your Lambda function runs.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5262" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.04.29-PM-e1482962708312.png" alt="" width="363" height="141" /></p>
<h2>Step 5: Test Your API Gateway</h2>
<p>If you copy and paste your API Gateway URL in the browser, it should say &#8220;internal server error&#8221;. This is because that Lambda creation wizard you ran created a new REST API for you, but returns a JavaScript string. By default, you need to use JSON. Let&#8217;s modify your Lambda code to do that.</p>
<pre><code>exports.handler = (event, context, callback) =&gt; {
    
    const response = {
        statusCode: '200',
        body: JSON.stringify('Hello from Lambda'),
        headers: {
            'Content-Type': 'application/json',
        },
    }
    callback(null, response);
};</code></pre>
<p>Now re-open the API Gateway URL in your browser, and you should see your &#8220;Hello from Lambda&#8221; message.</p>
<h1>Debug Your Microservice</h1>
<h2>Step 6: Custom Logging</h2>
<p>The event and context parameters allow you to pass dynamic information to your Lambda, and let you know how your Lambda was invoked. Add 2 log statements to show the event and context variables:</p>
<pre><code>exports.handler = (event, context, callback) =&gt; {
    console.log("event:", event);
    console.log("context:", context);</code></pre>
<p>Now click &#8220;Save and Test&#8221;. The log output at the bottom right should show your 2 log messages. The event is probably the custom Hello World default test data of key1, value1, etc.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5263" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.05.52-PM.png" alt="" width="1616" height="624" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.05.52-PM.png 1616w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.05.52-PM-300x116.png 300w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.05.52-PM-768x297.png 768w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.05.52-PM-1024x395.png 1024w" sizes="auto, (max-width: 1616px) 100vw, 1616px" /></p>
<p>Think of &#8220;event&#8221; as parameters your Lambda can choose to parse and use to dynamically act on. The context gives your Lambda information about itself while running (log group name, how long your lambda function has to run, etc). Let&#8217;s see how the event can differ.</p>
<h2>Step 7: CloudWatch Logs</h2>
<p>Click the &#8220;Monitoring&#8221; tab, and to the far right you should see &#8220;View logs in CloudWatch&#8221;. Click it.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5264" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.06.40-PM.png" alt="" width="2434" height="358" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.06.40-PM.png 2434w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.06.40-PM-300x44.png 300w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.06.40-PM-768x113.png 768w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.06.40-PM-1024x151.png 1024w" sizes="auto, (max-width: 2434px) 100vw, 2434px" /></p>
<p>Hopefully you should see at least 1 log, but probably more.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5265" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.07.13-PM.png" alt="" width="1840" height="474" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.07.13-PM.png 1840w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.07.13-PM-300x77.png 300w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.07.13-PM-768x198.png 768w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.07.13-PM-1024x264.png 1024w" sizes="auto, (max-width: 1840px) 100vw, 1840px" /></p>
<p>They are sorted by most recent, so click on the top one. These should match what&#8217;s in your log output when you tested it.</p>
<p>Click the back button, select all the log streams by clicking the box to their left, and click &#8220;Delete Log Stream&#8221; then &#8220;Yes Delete&#8221;.</p>
<p>Reopen the API Gateway URL, then go back to your CloudWatch logs and click the little refresh button (the spinning circle arrows) on the top right. It should have just 1 log which you just caused by re-running your API Gateway URL. Click it, and you&#8217;ll notice the data is much different.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5266" src="http://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.15.00-PM.png" alt="" width="2428" height="828" srcset="https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.15.00-PM.png 2428w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.15.00-PM-300x102.png 300w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.15.00-PM-768x262.png 768w, https://jessewarden.com/wp-content/uploads/2016/12/Screen-Shot-2016-12-28-at-5.15.00-PM-1024x349.png 1024w" sizes="auto, (max-width: 2428px) 100vw, 2428px" /></p>
<p>CloudWatch is pretty good at parsing arbitrary strings and JSON. Click the event area in the list, and it should expand it to show you the full JSON. Notice API Gateway sends us a lot of parameters.</p>
<h1>What Languages Can I Use?</h1>
<p>You can write your Lambdas in JavaScript, Python, Java, and C#. You can also use your normal libraries. The tutorial above edits the code inline in the AWS console, but a future tutorial shows you how you can automate your code.</p>
<h1>What Else Can Lambdas Do?</h1>
<p>Amazon&#8217;s documentation gives you <a href="http://docs.aws.amazon.com/lambda/latest/dg/invoking-lambda-function.html#intro-core-components-event-sources">a list of events</a> that can trigger your lambda. However, some real world use cases I&#8217;ve used are:</p>
<h2>REST API&#8217;s</h2>
<p>API Gateway for basic REST Services instead of using Node + <a href="http://restify.com/">Restify</a> + Docker + DockerSwarm (You can still use Node + Restify, heh)</p>
<h2>Backend For Front End</h2>
<p>Database guy had 1 Lambda for his <a href="https://aws.amazon.com/dynamodb/">DynamoDB</a> access. My Lambda was an API for my front-end, and took his JSON and formatted it the way I needed it (my microservice<a href="http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#invoke-property"> invoked</a> his microservice).</p>
<h2>Unexpected Spikes In Traffic == No Worries</h2>
<p>Trying to sell a client on how Lambda&#8217;s scaled better, and were cheaper than a dozen WebSphere instances in a row. We wired up <a href="http://gatling.io/#/">Gatling</a> to blast it with hundreds of thousands of users over 2 minutes. Amazon was like, &#8220;That&#8217;ll be $10 please.&#8221; lol! #awesome (This as opposed to the Terminator 2 nuke scene that typically resulted in a spike of traffic with the servers melting).</p>
<h2>Content Mangement Updating Servers</h2>
<p>Dropping updated content from a Content Management System on S3 (a hard drive in the cloud). Then, updating content on some EC2 instances behind an ELB. Using the SDK to <a href="http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/EC2.html#describeInstances-property">describe instances</a> (what servers do I have, and of those, are they running or not), you can then snag their IP addresses. Our EC2&#8217;s were in a different security group, so we put a lambda in the same group, gave it a URL from API Gateway, then had Lambda A call Lambda B with the IP addresses to call &amp; updated content to give them.</p>
<h1>Conclusions</h1>
<p>As you can see, Lambdas provide a wonderful way to build microservices for both your application, and your infrastructure. You can start with a <a href="http://martinfowler.com/bliki/MonolithFirst.html">monolith first</a> and make your Lambda&#8217;s 1 function turn into a ton, or build a bunch of little ones that may or may not know about each other, but all have a well defined API contract.</p>
<p>Not worrying about servers has freed up me and others to no longer worry about infrastructure, and instead write code.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
