<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Michael Field</title>
    <description>The latest articles on DEV Community by Michael Field (@kaijuking).</description>
    <link>https://dev.to/kaijuking</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F484854%2F8ba82c74-d191-41cb-bddd-25dc8a314150.jpeg</url>
      <title>DEV Community: Michael Field</title>
      <link>https://dev.to/kaijuking</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kaijuking"/>
    <language>en</language>
    <item>
      <title>#CloudGuruChallenge – Cloud Resume on AWS</title>
      <dc:creator>Michael Field</dc:creator>
      <pubDate>Tue, 11 May 2021 02:32:39 +0000</pubDate>
      <link>https://dev.to/kaijuking/cloudguruchallenge-cloud-resume-on-aws-wip-4hen</link>
      <guid>https://dev.to/kaijuking/cloudguruchallenge-cloud-resume-on-aws-wip-4hen</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Summary&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This post is about the &lt;a href="https://cloudresumechallenge.dev/"&gt;Cloud Resume&lt;/a&gt; challenge posted by &lt;a href="https://www.linkedin.com/in/forrestbrazeal/"&gt;Forrest Brazeal&lt;/a&gt; from "A Cloud Guru". #CloudGuruChallenge&lt;/p&gt;

&lt;p&gt;The challenge was to create a static website for your "Cloud Resume". As I journeyed through the cloud I wound up registering and creating four static websites since, as the saying goes, practice makes perfect. I wasn't worried about the extra cost associated with the three other domains as I plan to use them for other personal projects and/or sandboxing. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Finished Project&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mfieldcloudresumechallenge.com/"&gt;MField Cloud Resume&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Other test sites&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://asinglepicture.com/"&gt;A Single Picture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.justasinglepicture.com/"&gt;Just A Single Picture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://linksthatareuseful.com/"&gt;Links That Are Useful&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now onto the details of the project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3o6Mb2IGbQhix0dZLO/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3o6Mb2IGbQhix0dZLO/giphy.gif" alt="Marge's Resume"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Tools&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I used &lt;a href="https://code.visualstudio.com/"&gt;VSCode&lt;/a&gt; for my IDE and I'm loving it more and more each time I use it. Check it out! It's free!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Requirements&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I organized the requirements into three parts:&lt;/p&gt;

&lt;h3&gt;
  
  
  Front-end Components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Include the AWS Cloud Practitioner certificate (&lt;em&gt;WIP&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Be built with HTML, CSS and stored in an S3 bucket&lt;/li&gt;
&lt;li&gt;Use Route 53 to host the domain and configure DNS&lt;/li&gt;
&lt;li&gt;Use HTTPS for security via CloudFront&lt;/li&gt;
&lt;li&gt;Use Javascript to send a request to the backend to get the visitor count&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Back-end Components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Store the visitor count in DynamoDB&lt;/li&gt;
&lt;li&gt;An API Gateway endpoint which invokes a Lambda Function&lt;/li&gt;
&lt;li&gt;A Lambda function invoked which can access the database to retrieve/update the visitor count as well as send a response back to the front-end&lt;/li&gt;
&lt;li&gt;Infrastructure As Code (IAC) using the SAM CLI to create, build and deploy the template.yaml file needed to generate the resources in AWS&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GitHub CI/CD
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Two private Github repos one for each component&lt;/li&gt;
&lt;li&gt;Github actions invoked whenever new changes are merged

&lt;ul&gt;
&lt;li&gt;Front-end: need to invalidate the CloudFront cache&lt;/li&gt;
&lt;li&gt;Back-end: run python tests, build and deploy SAM 'template.yaml' file&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Front-end Components&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/xT5LMTZqXSxIOVagGk/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/xT5LMTZqXSxIOVagGk/giphy.gif" alt="Resume Needs Work"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  HTML &amp;amp; CSS
&lt;/h3&gt;

&lt;p&gt;I used a free, open sourced &lt;a href="https://github.com/StartBootstrap/startbootstrap-bare"&gt;starter bootstrap template&lt;/a&gt; and modified the content as needed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;index.html: personal and resume related background info&lt;/li&gt;
&lt;li&gt;projects.html: highlights other AWS projects &amp;amp; Cloud Challenges&lt;/li&gt;
&lt;li&gt;404.html: custom error page returned by CloudFront distribution whenever user navigates to a non-existent page&lt;/li&gt;
&lt;li&gt;default.js: contains the Javascript which requests the user count&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Javascript
&lt;/h4&gt;

&lt;p&gt;I attempted two ways to send a request to the Visitor Count API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch"&gt;Fetch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3schools.com/xml/xml_http.asp"&gt;XMLHttpRequest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although both methods worked I eventually went with XMLHttpRequest since it was easier to handle non-200 status codes as Fetch doesn't reject even on an HTTP error status. &lt;/p&gt;

&lt;p&gt;When testing the site locally I used a VSCode plugin called &lt;a href="https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer"&gt;Live Server&lt;/a&gt; which launches and loads your site in a local server. It was during this part of testing that I noticed my visitor count kept incrementing each time I refreshed and/or navigated back to the main index.html page. &lt;/p&gt;

&lt;p&gt;To help prevent this I decided to use the browser's Session Storage which is checked when the page loads.&lt;/p&gt;

&lt;p&gt;If the Session Storage item doesn't exist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send a request to the API endpoint to update and return the updated Visitor Count. The count value is then parsed from the response, stored in the Session Storage and displayed on the page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the Session Storage item does exist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieve the current value from the Session Storage and display the value on the page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Per &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage"&gt;MSDN&lt;/a&gt; documentation the Session Storage persists as long as the browser window is open. Once the user closes the browser the session is ended and the object is cleared.&lt;/p&gt;

&lt;h4&gt;
  
  
  AWS Resources
&lt;/h4&gt;

&lt;h5&gt;
  
  
  S3 Bucket
&lt;/h5&gt;

&lt;p&gt;AWS documentation found &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/website-hosting-custom-domain-walkthrough.html"&gt;here&lt;/a&gt; was my main source of information when setting up and configuring the S3 bucket. I found it very interesting how the "Access" level of the bucket changed throughout the entire project. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After creating the bucket

&lt;ul&gt;
&lt;li&gt;Access = Bucket and objects not public&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;After disabling the "Block all public access" setting

&lt;ul&gt;
&lt;li&gt;Access = Objects can be public&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;After editing the bucket policy

&lt;ul&gt;
&lt;li&gt;Access = Public&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;After creating and configuring CloudFront

&lt;ul&gt;
&lt;li&gt;Access = Objects can be public&lt;/li&gt;
&lt;li&gt;Details = &lt;em&gt;The bucket is not public but anyone with appropriate permissions can grant public access to objects.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  AWS Certificate Manager
&lt;/h5&gt;

&lt;p&gt;For the most part things went smoothly. However, there were some hiccups along the way.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For one of my test sites I figured I'd try creating a site with all the resources in the US-West region. When configuring the CloudFront distribution I was surprised to see the cert was not listed. Attempting to manually enter the cert failed but luckily the AWS error message displayed contained the answer as to why. When using CloudFront the certificate must be requested/imported in the US East region as is stated &lt;a href="https://docs.aws.amazon.com/acm/latest/userguide/acm-regions.html"&gt;here&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;Remember to click the "Create record in Route 53" button. Otherwise one could spend a while wondering why the request was taking so long. (true story! lol)&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  CloudFront
&lt;/h5&gt;

&lt;p&gt;Configuring a CloudFront distribution was (and still is) a rather daunting task considering all the available settings and options.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;General

&lt;ul&gt;
&lt;li&gt;Make sure to fill in the CNAME(s) properly. A few times I quickly skipped over or forgot this part and wondered why I wasn't able to view the site.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Origin Access Identity

&lt;ul&gt;
&lt;li&gt;Found creating a new identity worked best instead of using an existing identity.&lt;/li&gt;
&lt;li&gt;Select the "Yes, Update Bucket Policy" option. Doing so will automatically update the S3 bucket's policy which is how I noticed the bucket's access changed from "Public" to "Objects can be public". Otherwise you will have to manually update the bucket policy to grant the distribution access.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Custom Error Pages

&lt;ul&gt;
&lt;li&gt;When navigating to a non-existent page the response returned by CloudFront is a very user unfriendly '403 Access Denied' page. To help mitigate this I created a custom error response which returns the 404.html page in the S3 bucket.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Back-end Components&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3orieZsDE1JMM0k9RC/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3orieZsDE1JMM0k9RC/giphy.gif" alt="Lisa Work's On Resume"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Infrastructure As Code
&lt;/h3&gt;

&lt;p&gt;Initial setup was rather simple. To start I used the "Hello World Example" template which one can initialize through the SAM CLI. In the command line run the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 1: type in &lt;em&gt;sam init&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Step 2: Select "AWS Quick Start Templates"&lt;/li&gt;
&lt;li&gt;Step 3: Select "Zip (artifact is a zip uploaded to S3)"&lt;/li&gt;
&lt;li&gt;Step 4: Select your runtime of choice (ex: Python3.8)&lt;/li&gt;
&lt;li&gt;Step 5: Give your sam-app a name&lt;/li&gt;
&lt;li&gt;Step 6: Select template #1 (Hello World Example)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Following the above steps will auto-generate a template which one can then modify to suit your needs. For this project, I modified the following three pieces.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;template.yaml file&lt;/li&gt;
&lt;li&gt;Lambda Function&lt;/li&gt;
&lt;li&gt;python tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The template.yaml file consists of a serverless lambda function configured with events which generates an &lt;a href="https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api"&gt;implicit API&lt;/a&gt;. Modifying the template the final version consisted of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DynamoDB to store the visitor count&lt;/li&gt;
&lt;li&gt;Lambda Function with policy allowing access to

&lt;ul&gt;
&lt;li&gt;DynamoDB&lt;/li&gt;
&lt;li&gt;Parameter Store to retrieve the database name&lt;/li&gt;
&lt;li&gt;API Events to request the data from the backend&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Lambda Function has two "API Events":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Count

&lt;ul&gt;
&lt;li&gt;This path will retrieve, update and return the new visitor count to the frontend.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Health

&lt;ul&gt;
&lt;li&gt;I wanted the CI/CD workflow to fail and not even get to the SAM build/deploy portion if the API itself was down. To accomplish this I wrote a test which asserts the health response's status. If returned response code is not the expected value than the test fails which in turn should cause the CI/CD workflow to stop.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also used &lt;a href="https://learning.postman.com/docs/writing-scripts/script-references/test-examples/#testing-response-body"&gt;Postman&lt;/a&gt; to locally verify the endpoints. Postman is an absolutely awesome tool for testing APIs and I highly recommend it to anyone!&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yL6q-qRC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qbr88q2sak37qtdjxjdv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yL6q-qRC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qbr88q2sak37qtdjxjdv.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;GitHub CI/CD&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3orieMNuGBoS4aq4h2/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3orieMNuGBoS4aq4h2/giphy.gif" alt="Marge At Work"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The final portion of the project was to create a CI/CD pipeline using Github workflow actions. I was nervous at first since I had never used this feature before but I was able to put together a workflow for both the front-end and back-end code. The initial step was to add a workflow to the private repository. This can be done by going to the "Actions" tab of the repository and creating the suggested "Simple Workflow". &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KZptrMhU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7elbskvh1bluq553oc05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KZptrMhU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7elbskvh1bluq553oc05.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From there it was a matter of using other resources (i.e. Google) as well as trial/error to finetune the workflow. Part of the process was using an AWS user with only the permissions necessary for the job at hand. To accomplish this I created a new Group with a custom policy consisting of only the necessary permissions needed. Afterwards I created and assigned a new User to that Group.&lt;/p&gt;

&lt;p&gt;Back-End&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bDa0wYjW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9qak7297fs9xn8729l69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bDa0wYjW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9qak7297fs9xn8729l69.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Front-End&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OA1jw-9O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qz65wwq53yfm0mx8lr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OA1jw-9O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qz65wwq53yfm0mx8lr2.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Closing Thoughts&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/rOaQLY67fj6sE/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/rOaQLY67fj6sE/giphy.gif" alt="Upload Resume"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This challenge is a really great starting point for anyone who is interested in learning what the cloud is and the resources AWS provides. It's a highly recommended stepping stone for anyone who wants to start learning by doing. And once you start you'll get bitten by the 'cloud bug' and want to learn and do more. And what better way to showcase such knowledge than building and deploying your resume utilizing the technologies inside the (AWS) cloud itself.&lt;/p&gt;

&lt;p&gt;Where to go from here? Well, as of this writing I am scheduled to take the AWS Cloud Practitioners exam in early June 2021 and will use the bulk of my time in preparation for the exam. Other areas of interest and projects include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the AWS &lt;a href="https://aws.amazon.com/cdk/"&gt;Cloud Development Kit&lt;/a&gt; to redo my &lt;a href="https://github.com/kaijuking/japanese-word-of-the-day"&gt;Twitter Bot&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Hosting a &lt;a href="https://aws.amazon.com/getting-started/hands-on/build-react-app-amplify-graphql/"&gt;REACT application&lt;/a&gt; on AWS&lt;/li&gt;
&lt;li&gt;the #100DaysOfCode challenge&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you again Forrest! This was a lot of fun! And thank you to everyone who took the time to read this post. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Update - June 12, 2021]&lt;/strong&gt;&lt;br&gt;
I took and passed the AWS Cloud Practitioner certification exam on June 11th! Click &lt;a href="https://www.credly.com/badges/9b17d979-5d64-4e06-8aae-3e49fcce804e/public_url"&gt;here&lt;/a&gt; to view my certificate. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>#CloudGuruChallenge – Event-Driven Python on AWS</title>
      <dc:creator>Michael Field</dc:creator>
      <pubDate>Thu, 08 Oct 2020 05:02:51 +0000</pubDate>
      <link>https://dev.to/kaijuking/cloudguruchallenge-event-driven-python-on-aws-3gnp</link>
      <guid>https://dev.to/kaijuking/cloudguruchallenge-event-driven-python-on-aws-3gnp</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Summary&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Back in September 2020 &lt;a href="https://www.linkedin.com/in/forrestbrazeal/"&gt;Forrest Brazeal&lt;/a&gt; from Cloud Guru posted a new #CloudGuruChallenge which was to build an event driven ETL (Extract, Transform, Load) application.&lt;/p&gt;

&lt;p&gt;Challenge Details can be found &lt;a href="https://acloudguru.com/blog/engineering/cloudguruchallenge-python-aws-etl"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Background&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Before going into the details of the #CloudGuruChallenge, I would like to mention that this was only my second time at attempting to create an application using AWS. At the time the new challenge was announced I had just started a two week stay-cation where my main goal was to create a &lt;a href="https://twitter.com/maikuonline"&gt;"Japanese Word of the Day"&lt;/a&gt; Twitter bot using Python. &lt;/p&gt;

&lt;p&gt;I had a very basic POC created which worked locally on my machine but I wanted to move it to the cloud. Doing so would provide me with an opportunity to learn something new, get more practice using Python as well as not having to leave the application running on my local machine. However, moving the app to the cloud also presented some new challenges.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What services should I use?&lt;/li&gt;
&lt;li&gt;Should I run the app on an EC2 instance? &lt;/li&gt;
&lt;li&gt;How would I store and update the data?&lt;/li&gt;
&lt;li&gt;How should I store sensitive data like the auth-keys/secrets?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3o6MbbwX2g2GA4MUus/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3o6MbbwX2g2GA4MUus/giphy.gif" alt="Homer Doesn't Understand"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In all the application included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lambda Function #1: posts a new word to Twitter account&lt;/li&gt;
&lt;li&gt;Lambda Function #2: adds new words to the database &lt;/li&gt;
&lt;li&gt;CloudWatch Event #1: invokes Lambda Function #1 once a day&lt;/li&gt;
&lt;li&gt;CloudWatch Event #2: invokes Lambda Function #2 when a JSON file is uploaded to S3&lt;/li&gt;
&lt;li&gt;S3 Bucket: holds a JSON file consisting of new Japanese words&lt;/li&gt;
&lt;li&gt;DynamoDB: stores a list of Japanese words which Lambda Function #1 queries when posting a new word to Twitter&lt;/li&gt;
&lt;li&gt;AWS Systems Manager Parameter Store to hold the auth-keys/secrets&lt;/li&gt;
&lt;li&gt;AWS SAM CLI for building and deploying the app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted to mention this first because it gave me the confidence to believe that I could actually complete the new challenge. &lt;/p&gt;

&lt;p&gt;Repository for this project can be found &lt;a href="https://github.com/kaijuking/japanese-word-of-the-day"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Cloud Guru Challenge – Details&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;The challenge was to create a Python compute job which would (once a day) extract a set of Covid19 data and display the information on a dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;AWS Resources&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;All resources (Lambda, Events, S3, DynamoDB, AWS Glue, SNS) were created via the template.yaml file which sounded easy at first but was actually very difficult for me to fully understand. Just when I thought I got it right (and with &lt;em&gt;sam build&lt;/em&gt; giving the green light) something would go wrong when attempting to deploy the app. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/d3QGYTziFiDL2/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/d3QGYTziFiDL2/giphy.gif" alt="Yoinks, and Away!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sometimes the issue had to do with improper syntax while others times I wasn't referencing the correct name or resource. Overall it was really cool and exciting being able to spin up AWS resources without having to use the console.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Don't forget to set &lt;em&gt;PublicAccessBlockConfiguration&lt;/em&gt; to TRUE to prevent public access to your S3 resources&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/awsdocs/aws-lambda-developer-guide/tree/master/sample-apps/blank-python"&gt;aws lambda developer guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-publicaccessblockconfiguration.html"&gt;AWS::S3::Bucket PublicAccessBlockConfiguration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Data Extraction/Filtering/Validation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In another first for me I decided to use Python Pandas as the means of extracting, filtering and transforming the raw csv data. I've heard about Python Pandas before but never used it myself nor did I have any real insight into how powerful the module is.&lt;/p&gt;

&lt;p&gt;I used Pandas to extract the raw data from the csv files as well and performed some preliminary validation. I checked to see if the raw data included the expected column names as well the expected datatype (&lt;em&gt;isnull()&lt;/em&gt;, &lt;em&gt;map(type).all() == str&lt;/em&gt;, etc). My thinking was that the app should stop (and not proceed) if the raw data itself didn't contain the expected data. &lt;/p&gt;

&lt;p&gt;My biggest concern about using the Panda Module was the shear size of the module itself as it was the bulk of the application's size. AWS provides Lambda layers and I attempted to try and use that to decrease the size/deploy time but wasn't able to figure it out. Taking application size (as well as any changes made by either &lt;a href="https://aws.amazon.com/blogs/compute/upcoming-changes-to-the-python-sdk-in-aws-lambda/"&gt;AWS&lt;/a&gt; or Python) I'm thinking it might be good to create one's own Lambda Layer library of modules. My thinking being if there are any breaking changes/updates (AWS SDK, the module or Python) the application should still be able to run using the layer.&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://realpython.com/pandas-python-explore-dataset/"&gt;Using Pandas and Python to Explore Your Dataset&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pandas.pydata.org/docs/user_guide/index.html"&gt;Pandas User Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Data Transformation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The final data transformation logic is contained in a separate Python module (&lt;em&gt;transformdata.py&lt;/em&gt;) where the two sets data are merged into one 'final' dataset.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Uploading The Data&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Because I had "some" experience with using DynamoDB with my Twitter-bot I thought it was going to be a piece of cake using the same database resource for this challenge. However, I should have investigated AWS QuickSight more because if I had I would have learned that QuickSight doesn't yet support DynamoDB. With that said my application basically has two databases: DynamoDB and S3. &lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;DynamoDB&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;If the DynamoDB table has 0 items than the whole final dataset is uploaded. Otherwise I query the database (with date sorted descending) and return only one record (which should be the last most recent date). I then use Pandas to filter the final dataset by that date so that only items with a date greater than the filtered date are uploaded to the DB. This is to avoid having to uploaded everything each day in the database.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;S3&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Since I use S3 to feed the QuickSight dashboard, I simply just upload the entire dataset to S3 (csv file). This also avoids having to worry about any older dates having updates to any of the counts (cases, deaths, recovered). &lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/uhho/a1490ae2abd112b556dcd539750aa151"&gt;Uploading CSV to S3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Notification&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The notification I sent aren't the most user friendly nor prettiest to look at but it does notify the user of how many items were added to the database.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bIZ5ZkJG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2cm15dy6can8fln6crne.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bIZ5ZkJG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2cm15dy6can8fln6crne.PNG" alt="AWS SNS Email Notification"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Tests&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I have six tests (each test containing several scenarios) which are used to verify the 'raw' data and the transformed data. Making sure the expected outcome occurs. &lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://realpython.com/python-testing/"&gt;Getting Started With Testing in Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/unittest.html"&gt;unittest — Unit testing framework&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Dashboard&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When I found out QuickSight doesn't support DynamoDB I had to quickly create an S3 resource. Once that was done I was able to connect QuickSight to the S3 dataset and put together a chart showing the number of cases vs recovered vs deaths over time. I have to say (despite the name) QuickSight wasn't very quick for me to catch on and use. The user interface didn't seem very intuitive but I say that with a grain of salt since this was my first experience using any sort of Business Intelligence (BI) service. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H_XqUglZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zn0rlf3eoyvgawj3ctmy.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H_XqUglZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zn0rlf3eoyvgawj3ctmy.PNG" alt="Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Repository&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Code can be found &lt;a href="https://github.com/kaijuking/cgc-eventdriven-etl"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Looking Back&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;First and foremost I want to thank Forrest and everyone at CloudGuru for creating these challenges as it was (without a doubt) an amazing learning adventure. I'd also want to thank my current job for 1) paying for a 3 day AWS training camp back in December 2019 and 2) for giving us access to the resources on Cloud Guru itself. &lt;/p&gt;

&lt;p&gt;In my current job position the extent of my direct interaction with AWS itself is via the console and mostly for troubleshooting. To be able to actually create resources and deploy an application using those resources is an amazing feeling. I can't stress enough how amazing a learning opportunity these se #CloudGuruChallenges are.  &lt;/p&gt;

&lt;p&gt;Moving forward I want to continue looking/persuing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lambda layers&lt;/li&gt;
&lt;li&gt;CI/CD&lt;/li&gt;
&lt;li&gt;Further usage and insight into AWS QuickSight&lt;/li&gt;
&lt;li&gt;More usage of Python Pandas and Unit Tests&lt;/li&gt;
&lt;li&gt;Complete the previous Cloud Resume challenge&lt;/li&gt;
&lt;li&gt;Study for the AWS Certified Cloud Practitioner exam&lt;/li&gt;
&lt;li&gt;Planning better before jumping into code&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
