<?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>Forem: Leszek Ucinski</title>
    <description>The latest articles on Forem by Leszek Ucinski (@cloudedthings).</description>
    <link>https://forem.com/cloudedthings</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%2F731026%2Faa737ac8-aa33-4d86-9140-d12cea390e1f.jpeg</url>
      <title>Forem: Leszek Ucinski</title>
      <link>https://forem.com/cloudedthings</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/cloudedthings"/>
    <language>en</language>
    <item>
      <title>Finding Your Fit: Crafting Diverse Development Environments on AWS Lightsail</title>
      <dc:creator>Leszek Ucinski</dc:creator>
      <pubDate>Fri, 03 Nov 2023 13:02:53 +0000</pubDate>
      <link>https://forem.com/cloudedthings/finding-your-fit-crafting-diverse-development-environments-on-aws-lightsail-18ah</link>
      <guid>https://forem.com/cloudedthings/finding-your-fit-crafting-diverse-development-environments-on-aws-lightsail-18ah</guid>
      <description>&lt;p&gt;💡&lt;strong&gt;Exploring new development environments? AWS Lightsail offers cost-effective access to Windows and Linux operating systems. While primarily focusing on Windows connecting to Linux, this guide offers pathways for all. Get hands-on and explore a range of development opportunities affordably and flexibly. This guide helps you start, connect, and set up an alternative environment that suits your needs.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📋Table of Contents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Working in a Windows Environment: Exploring WSL and Its Limitations&lt;/li&gt;
&lt;li&gt;
Building Your Own Linux Development Environment

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Setting up an AWS Lightsail Instance&lt;/li&gt;
&lt;li&gt;Connecting to Your Lightsail Instance with VS Code&lt;/li&gt;
&lt;li&gt;Configuring the Development Environment&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Understanding Costs: AWS Lightsail Billing&lt;/li&gt;

&lt;li&gt;Final Thoughts and Considerations&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;My everyday machine is Windows, serving me well for most tasks. However, I found it limiting for code development and AWS interactions. Navigating through PowerShell and the absence of essential CLI tools became obstacles (could you live without &lt;a href="https://dev.to/lissy93/cli-tools-you-cant-live-without-57f6"&gt;these cli tools&lt;/a&gt;?). This isn't about pitting one OS against another, but about enabling a smoother development journey. Here, I'll share a straightforward method to establish a Linux-based development environment. &lt;/p&gt;




&lt;p&gt;☁️ Utilizing AWS credits, I explored a cost-saving solution. This guide showcases how to set up a Linux environment on AWS Lightsail, offering an alternative OS for developers seeking flexibility. While I focus on enabling Linux for Windows users, Lightsail provides &lt;a href="https://lightsail.aws.amazon.com/ls/docs/en_us/articles/compare-options-choose-lightsail-instance-image" rel="noopener noreferrer"&gt;various OS&lt;/a&gt; types for diverse developer needs. &lt;/p&gt;




&lt;p&gt;❗&lt;strong&gt;This solution will incur monthly charges that you have to be aware of (see the Understanding Costs: AWS Lightsail Billing).&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Working in a Windows Environment: Exploring WSL and Its Limitations
&lt;/h3&gt;

&lt;p&gt;While an apparent and straightforward alternative is using WSL on Windows (&lt;a href="https://learn.microsoft.com/en-us/windows/wsl/install" rel="noopener noreferrer"&gt;see here for setup instructions&lt;/a&gt;), my experience in Python and AWS SAM development revealed potential drawbacks. WSL often becomes unresponsive due to memory management inefficiencies. The memory allocation within WSL, managed by the Windows operating system, can lead to performance degradation and unresponsiveness, particularly evident when handling resource-intensive tasks in development environments. Despite my mighty 32GB RAM machine, every time I unleash &lt;code&gt;sam local start-api&lt;/code&gt; with a medley of Lambda function fiestas, my WSL slowly morphs into the 'Snail Subsystem for Linux.' It huffs, puffs, and eventually naps, leaving me in the lurch. 😊&lt;/p&gt;

&lt;h3&gt;
  
  
  Building Your Own Linux Development Environment
&lt;/h3&gt;

&lt;h4&gt;
  
  
  ⚓ Prerequisites
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;An AWS Account&lt;/li&gt;
&lt;li&gt;VS Code on your Windows machine&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  💻 Setting up an AWS Lightsail Instance
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Open Lightsail Console. And choose &lt;strong&gt;Create instance&lt;/strong&gt;
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ai3m2gefalgcliyww5n.png" alt="lightsail_console"&gt;
&lt;/li&gt;
&lt;li&gt;Choose the &lt;strong&gt;OS Only&lt;/strong&gt; and your preferred Linux Distribution.&lt;/li&gt;
&lt;li&gt;Use either the Default key or create/upload your own. Download the key.&lt;/li&gt;
&lt;li&gt;Choose the instance plan. I wouldn't the smallest one, since it has only 512 MB of RAM. Go with a bit larger one. Give it a name, tags, and launch. After a couple of minutes, it'll be in the &lt;em&gt;Running&lt;/em&gt; state.💤&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flfiyhvatrxhmyvwz3m96.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flfiyhvatrxhmyvwz3m96.png" alt="running_instance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Time for some additional setup. Choose your instance and go to the &lt;strong&gt;Networking&lt;/strong&gt; tab. I would recommend attaching a static IP so that you can easily reconnect to your instance. You can remove the HTTP rule from the IPv4 Firewall, we'll be connecting through SSH. Configure the SSH rule to allow connections only from your IP (you can keep the &lt;em&gt;Allow Lightsail browser SSH&lt;/em&gt; option enabled so that you can easily connect to your instance through the AWS Console). Check your IP and replace it as Source IP:
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1anw43y5j9n8kght6uix.png" alt="firewall"&gt;
You might want to disable the IPv6 networking if you're not planning on using it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Connecting to Your Lightsail Instance with VS Code
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Store locally the SSH Key from the Lightsail console. Remember the path to the &lt;code&gt;.pem&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Start Visual Studio Code.&lt;/li&gt;
&lt;li&gt;Install the &lt;strong&gt;Remote Explorer&lt;/strong&gt; extension through the &lt;strong&gt;Extensions&lt;/strong&gt; menu.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5n5b3cuh368xdv8a61jk.png" alt="remote_explorer"&gt;
&lt;/li&gt;
&lt;li&gt;You should see the &lt;em&gt;Open a Remote Window&lt;/em&gt; icon on the left bottom of VS Code.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz10ncq9jvemt4o72jfig.png" alt="vscode_remote"&gt;
Click on it and then choose Connect to Host.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbh5yzp21unvzlfc377rt.png" alt="vscode_connect"&gt;
And then Add New Host.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzv9vymc5rtehl7pw69tq.png" alt="host"&gt;
Give it a name like &lt;code&gt;ubuntu@&amp;lt;your.lightsail.static.ip&amp;gt;&lt;/code&gt;. Select SSH configuration file or create it (on Windows it's usually stored at &lt;code&gt;C:\Users\{USERNAME}\.ssh\config&lt;/code&gt;.
The config file will open and then specify the path to the SSH key or rename the host if you want:
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fznya11wj5wj1etq2xy6k.png" alt="host_name"&gt;
&lt;/li&gt;
&lt;li&gt;Press F1 or Ctrl+Shift+P to open the command palette in VS Code.
Type and select "Remote-SSH: Connect to Host...".
Choose your Host. Choose Linux. Accept the fingerprint. 
🏁 And voila! You're connected!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8zi96o1rwqzo9i0k8g4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8zi96o1rwqzo9i0k8g4.png" alt="ssh_connected"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using the left menu bar you can choose Explorer -&amp;gt; Open Folder to browse the instances file system:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fex3j7537k98bl98o7uop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fex3j7537k98bl98o7uop.png" alt="explorer_files"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  🚧 Configuring the Development Environment
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Access the Terminal within Visual Studio Code:
Once connected to your Lightsail instance via SSH in VS Code, go to the top menu and select Terminal &amp;gt; New Terminal. This action will open a new terminal window within VS Code, connected to your Lightsail instance.&lt;/li&gt;
&lt;li&gt;Start off with updating and upgrading the packages (below commands for Ubuntu):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Depending on your needs you might want to download additional packages. Ubuntu image comes with Python 3.10 installed.&lt;/li&gt;
&lt;li&gt;Let's install AWS CLI
Install unzip
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;unzip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download the AWS CLI&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"awscliv2.zip"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unzip the downloaded package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;unzip awscliv2.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the installation script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; ./aws/install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Understanding Costs: AWS Lightsail Billing
&lt;/h3&gt;

&lt;p&gt;💵 One important aspect to note is that charges apply not only to actively running instances but also to stopped instances. Whether your Lightsail instance is actively running or stopped, you'll incur charges. According to Lightsail's documentation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Q: When am I getting charged for a plan?&lt;br&gt;
Your Lightsail instances are charged only when they're in the running or stopped state. If you delete your Lightsail instance before the end of the month, we only charge you a prorated cost, based on the total number of hours that you used your Lightsail instance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AWS &lt;a href="https://lightsail.aws.amazon.com/ls/docs/en_us/articles/understanding-your-amazon-lightsail-bill" rel="noopener noreferrer"&gt;bills&lt;/a&gt; the instances by the hour, but advertises the monthly price by capping it for a whole month. For example, if you use a $5/1GB per month plan for 5 days, you will be charged 120 hours (5 days x 24 hours) at an hourly rate of $0.00672 (10 USD / 720 hours)(depending on the AWS Region). This amounts to $0.81 for 5 days of usage. More details on additional costs can be found &lt;a href="https://aws.amazon.com/lightsail/faq/#Billing_and_account_management" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
⭐ But remember that the first three months are free! ⭐&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts and Considerations
&lt;/h3&gt;

&lt;p&gt;📜 Cloud-based development environments offer enhanced productivity and flexibility. You can connect to your Linux instance on Lightsail from any machine supporting SSH and have a separate environment fitting your needs. Since there are many OS options to choose from you can start a Windows machine if that's what you need. While Windows Subsystem for Linux (WSL) is free, AWS Lightsail's Linux environment incurs additional costs. The crucial consideration is enabling both Linux users to initiate Windows and vice versa, balancing the limitations of local setups against the incurred expenses of cloud alternatives.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Cover image generated with AI. Content credentials: Generated with AI ∙ November 3, 2023 at 11:57 AM.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>development</category>
      <category>linux</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Event-driven file management using S3 Notifications and Step Functions</title>
      <dc:creator>Leszek Ucinski</dc:creator>
      <pubDate>Mon, 23 Jan 2023 10:55:41 +0000</pubDate>
      <link>https://forem.com/cloudedthings/event-driven-file-management-using-s3-notifications-and-step-functions-3kcd</link>
      <guid>https://forem.com/cloudedthings/event-driven-file-management-using-s3-notifications-and-step-functions-3kcd</guid>
      <description>&lt;p&gt;If our looking for a solution to handle file management of S3 objects, but listing a Bucket doesn't work for you, maybe this approach will.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ez4adXH9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/38jo75fhglb48oywa1f9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ez4adXH9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/38jo75fhglb48oywa1f9.png" alt="AWS-event-driven-diagram" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Problem and solution:&lt;/p&gt;

&lt;p&gt;You want to log S3 objects metadata and expose it through an API backed with superfast DynamoDB. I've chosen to write this simple example without even using any Lambda functions. We'll be using the build in StepFunctions integration with DynamoDB. So no code at all.&lt;/p&gt;

&lt;p&gt;In this first step of building that kind of solution I will describe how to log newly uploaded files in the DynamoDB table in an event-driven fashion. In the next step, I’ll describe how to expose that data through a Lambda-backed API.&lt;/p&gt;

&lt;p&gt;What will we build:&lt;/p&gt;

&lt;p&gt;An event-driven architecture deployed with AWS SAM.&lt;/p&gt;

&lt;p&gt;Resources used (might incur costs):&lt;/p&gt;

&lt;p&gt;Serverless StateMachine&lt;br&gt;
EventBridge Rule&lt;br&gt;
S3 Bucket&lt;br&gt;
DynamoDB table&lt;/p&gt;

&lt;p&gt;Requirements:&lt;br&gt;
An AWS Account obviously&lt;br&gt;
AWS SAM CLI installed and configured&lt;/p&gt;

&lt;p&gt;Let’s start! You can either run the console command to initiate SAM App using one of the Quick Start Templates or choose the Custom Template that we will write here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sam init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’ve chosen the first option and provided Python as my runtime even though I won't need any code in this example. Then just clear the template.yaml and remove the existing lambda code or else get started with a clean slave.&lt;/p&gt;

&lt;p&gt;We’ll start with deploying our Bucket and set up Notifications to be sent to EventBridge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Event-driven file management

Resources:
  FilesBucket:
    Type: AWS::S3::Bucket
    Properties:
      NotificationConfiguration:
        EventBridgeConfiguration:
          EventBridgeEnabled: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step into your App folder and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sam deploy --guided
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have our bucket and deployed with EventBridge configuration all S3 event notifications will be sent to the default Event Bridge bus.&lt;/p&gt;

&lt;p&gt;In the next step, we will deploy a DynamoDB table. We’ll create two string attributes for now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FilesTable:
    Type: AWS::DynamoDB::Table
    Properties:
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: 'fileName'
          AttributeType: S
        - AttributeName: 'lastModified'
          AttributeType: S
      KeySchema:
        - AttributeName: fileName
          KeyType: HASH
        - AttributeName: lastModified
          KeyType: RANGE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s write the definition of our StateMachine in ASL (Amazon States Language) that we’ll be deploying when creating the StateMachine resource.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Comment": "Triggered on EventBridge S3 Object Created notification",
  "StartAt": "Query",
  "States": {
    "Query": {
      "Type": "Task",
      "Next": "ObjectExists",
      "Parameters": {
        "TableName": &amp;lt;&amp;lt;TABLE_NAME&amp;gt;&amp;gt;,
        "KeyConditionExpression": "fileName = :fileName",
        "ExpressionAttributeValues": {
          ":fileName": {
            "S.$": "$.detail.object.key"
          }
        }
      },
      "Resource": "arn:aws:states:::aws-sdk:dynamodb:query",
      "ResultPath": "$.dynamoDbResult"
    },
    "ObjectExists": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.dynamoDbResult.Items",
          "NumericGreaterThan": 0,
          "Next": "UpdateObject"
        }
      ],
      "Default": "PutObject"
    },
    "UpdateObject": {
      "Type": "Task",
      "Resource": "arn:aws:states:::dynamodb:updateItem",
      "Parameters": {
        "TableName": &amp;lt;&amp;lt;TABLE_NAME&amp;gt;&amp;gt;,
        "Key": {
          "fileName": {
            "S": "$.detail.object.key"
          }
        },
        "UpdateExpression": "set lastModified : lastModified",
        "ExpressionAttributeValues": {
          ":lastModified": {
            "S": "$.time"
          }
        }
      },
      "Next": "ObjectUpdated"
    },
    "PutObject": {
      "Type": "Task",
      "Resource": "arn:aws:states:::dynamodb:putItem",
      "Parameters": {
        "TableName": &amp;lt;&amp;lt;TABLE_NAME&amp;gt;&amp;gt;,
        "Item": {
          "fileName": {
            "S": "$.detail.object.key"
          },
          "lastModified": {
            "S": "$.time"
          }
        }
      },
      "Next": "ObjectAdded"
    },
    "ObjectUpdated": {
      "Type": "Succeed"
    },
    "ObjectAdded": {
      "Type": "Succeed"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The visual workflow would look like that:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oNI-ovix--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ymi1ikxmlk9cwa44lo8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oNI-ovix--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ymi1ikxmlk9cwa44lo8d.png" alt="stepfunctions-workflow" width="354" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The StateMachine would be triggered on S3 Object Created notification. In the ‘Query’ step will check if the file already exists in the DynamoDB table. Then will do the ‘ObjectExists’ Choice operation on the output from the query step. If there’s no Attribute with the newly created object the ‘PutObject’ operation will run. If there’s one will update the ‘lastModified’ attribute will the event time.&lt;/p&gt;

&lt;p&gt;Now let’s create our StateMachine Resource in our SAM template and specify the definition parameter providing a path to the above JSON file (mine is at ‘definitions/object_created.asl.json’):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ObjectCreatedStateMachine:
    Type: AWS::Serverless::StateMachine
    Properties:
      DefinitionUri: definitions/object_created.asl.json
      Policies:
        - CloudWatchLogsFullAccess
        - DynamoDBCrudPolicy:
            TableName: !Ref FilesTable
      Type: STANDARD
      DefinitionSubstitutions:
        TableName: !Ref FilesTable
      Events:
        EBPutRule:
          Type: EventBridgeRule
          Properties:
            Pattern:
              source:
                - aws.s3
              detail-type:
                - Object Created
              detail:
                bucket:
                  name:
                    - !Ref FilesBucket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above snippet creates the StateMachine for us, an IAM Role with permissions to perform CRUD operations on DynamoDB Table. It even creates EventBridge Rule with patern that will trigger StateMachine on S3 Object Created events in the FilesBucket.&lt;/p&gt;

&lt;p&gt;This is just a beginning of a potentially powerful event-driven architecture. Thanks to the power of EventBridge and the flexibility of the Rules and patterns, one might filter the events granularly and route the events to corresponding processes. &lt;br&gt;
This simple app would definitely need some error handling and maybe integration with Lambda functions to get more adjusted data out of events and into DynamoDB. In another part I will describe how one might integrate the data stored in DynamoDB table with serverless HTTP API.&lt;/p&gt;

&lt;p&gt;Projects repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/CloudedThings/AWS-SAM-event-driven-file-management"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>sam</category>
      <category>serverless</category>
      <category>eventdriven</category>
    </item>
    <item>
      <title>Cloud Resume Challenge - AWS</title>
      <dc:creator>Leszek Ucinski</dc:creator>
      <pubDate>Wed, 27 Oct 2021 20:52:55 +0000</pubDate>
      <link>https://forem.com/cloudedthings/cloud-resume-challenge-aws-1mhh</link>
      <guid>https://forem.com/cloudedthings/cloud-resume-challenge-aws-1mhh</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I stumbled upon the &lt;a href="https://cloudresumechallenge.dev/docs/the-challenge/aws/" rel="noopener noreferrer"&gt;Cloud Resume Challenge&lt;/a&gt; while preparing myself for the AWS Certified Solution Architect exam. I already passed the Cloud Practitioner and was looking for some hands-on labs or challenges to get my hands &lt;em&gt;cloudy&lt;/em&gt;...&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jxmkk1i78tk88ttfqul.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jxmkk1i78tk88ttfqul.gif" alt="cloudy-hands"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've come up with my own challenge &lt;a href="https://cloudofthings.net/category/aws-labs/" rel="noopener noreferrer"&gt;100 days in Cloud&lt;/a&gt; during which I go through one lab a day and describe how I solved it. But I needed a bigger project that would demand some more digging and sweating to accomplish, hence the CRC. &lt;/p&gt;
&lt;h3&gt;
  
  
  Challenge instructions:
&lt;/h3&gt;

&lt;p&gt;✔️ &lt;strong&gt;Certification&lt;/strong&gt;  - got &lt;a href="https://www.credly.com/badges/5aab882a-2ced-4a72-9bcd-e92d8b99f1e5" rel="noopener noreferrer"&gt;my&lt;/a&gt; AWS Certified Cloud Practitioner&lt;br&gt;
 ✔️ &lt;strong&gt;HTML&lt;/strong&gt;  - check [my profile](&lt;a href="https://myprofile.cloudofthings.link/" rel="noopener noreferrer"&gt;https://myprofile.cloudofthings.link/&lt;/a&gt;&lt;br&gt;
 ✔️ &lt;strong&gt;CSS&lt;/strong&gt;  - &lt;a href="https://github.com/CloudedThings/aws-crc-sam/blob/main/website/style.css" rel="noopener noreferrer"&gt;style.css&lt;/a&gt;&lt;br&gt;
 ✔️ &lt;strong&gt;Static Website&lt;/strong&gt; - AWS SAM &lt;a href="https://github.com/CloudedThings/aws-crc-sam/blob/main/template.yaml" rel="noopener noreferrer"&gt;template&lt;/a&gt; takes care of that&lt;br&gt;
 ✔️ &lt;strong&gt;HTTPS&lt;/strong&gt;  - Amazon CloudFront takes care of that&lt;br&gt;
 ✔️ &lt;strong&gt;DNS&lt;/strong&gt;  - Route 53 points to my profile page as part of &lt;a href="https://cloudofthings.net/" rel="noopener noreferrer"&gt;cloudofthings.net&lt;/a&gt;&lt;br&gt;
 ✔️ &lt;strong&gt;Javascript&lt;/strong&gt;  - there's some script in &lt;a href="https://github.com/CloudedThings/aws-crc-sam/blob/main/website/script.js" rel="noopener noreferrer"&gt;script.js&lt;/a&gt; and in index.html&lt;br&gt;
 ✔️ &lt;strong&gt;Database&lt;/strong&gt;  - DynamoDB deployed using SAM&lt;br&gt;
 ✔️ &lt;strong&gt;API&lt;/strong&gt;  - similarly here&lt;br&gt;
 ✔️ &lt;strong&gt;Python&lt;/strong&gt; - &lt;a href="https://github.com/CloudedThings/aws-crc-sam/blob/main/get-function/app.py" rel="noopener noreferrer"&gt;Lambda functions&lt;/a&gt; &lt;br&gt;
 ✔️ &lt;strong&gt;Tests&lt;/strong&gt; - Integration and &lt;a href="https://github.com/CloudedThings/aws-crc-sam/blob/main/tests/end-to-end-test/index.js" rel="noopener noreferrer"&gt;End-to-end&lt;/a&gt; tests in &lt;a href="https://github.com/CloudedThings/aws-crc-sam/blob/main/.github/workflows/deploy.yml" rel="noopener noreferrer"&gt;GitHub actions&lt;/a&gt;&lt;br&gt;
 ✔️ &lt;strong&gt;Infrastructure as Code&lt;/strong&gt; - AWS SAM &lt;a href="https://github.com/CloudedThings/aws-crc-sam/blob/main/template.yaml" rel="noopener noreferrer"&gt;template&lt;/a&gt;&lt;br&gt;
 ✔️ &lt;strong&gt;CI/CD&lt;/strong&gt; - &lt;a href="https://github.com/CloudedThings/aws-crc-sam/blob/main/.github/workflows/deploy.yml" rel="noopener noreferrer"&gt;GitHub actions&lt;/a&gt;&lt;br&gt;
 ✔️ &lt;strong&gt;Blog post&lt;/strong&gt; - obviously... 😏&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqf33ynicchio7uwylizo.jpg" alt="diagram"&gt;
&lt;/h2&gt;
&lt;h2&gt;
  
  
  My challenge experience
&lt;/h2&gt;

&lt;p&gt;I started with creating a sample HelloWorld application using SAM. This way I got Lambda with API Layer as a starting point for my infrastructure. Not everything went smoothly as one might have wished for so I'll focus mainly on my greatest challenges and solutions that thought me something new.&lt;/p&gt;

&lt;p&gt;An example of an issue I got stuck on was when making the bucket accessible for the CloudFront distribution so I've decided to make my website bucket private and used CloudFront Origin Access Identity. It somehow felt more secure as well, so win-win situation even though it drove me crazy not being able to figure out what's blocking CloudFront access to the previously public bucket. &lt;/p&gt;

&lt;p&gt;Creating the ACM Certificate and attaching it to my CloudFront. I live in Sweden and I thought it's only logical to use resources nearby and to find out if there are any services that I won't be able to use. And Certificates for CloudFront distribution happen to be an example of that. Since CloudFront uses certificates created only in the us-east-1 region I had to create one in AWS Console and use its ARN in the template. I suspect that there is a pure IaC-ish type of solution but this one works too.&lt;/p&gt;

&lt;p&gt;The most giving lesson from the challenge was the CI/CD with GitHub Actions. What I revelation that was. Even though that I used &lt;a href="https://dev.toLive%20Server%20extension%20for%20VSC"&gt;Live Server extension for VSC&lt;/a&gt; - which I strongly recommend - I was struck by how easy it is to upload and deploy your code with Actions. When I set up my Workflow to use AWS SAM it builds and deploys changes in the infrastructure. Similarly for the website contents making the pushes would trigger the upload of the website content.&lt;/p&gt;

&lt;p&gt;Working on the backend consisting of &lt;strong&gt;API Gateway&lt;/strong&gt;, &lt;strong&gt;Lambda&lt;/strong&gt;, &lt;strong&gt;DynamoDB&lt;/strong&gt; was relatively easy since I've done it many times. Here I've learned that you can easily increment values in tables using update expression.&lt;/p&gt;

&lt;p&gt;Another challenging part was to write a SAM template, getting the syntax right, using &lt;strong&gt;!Ref&lt;/strong&gt; and &lt;strong&gt;Fn::Sub&lt;/strong&gt; functions. But it was a great practice. Infrastructure as Code feels like the only way to design and deploy resources in AWS.&lt;/p&gt;


&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I got so much out of this Challenge! I needed that kind of project to get my head around all of the things I've been learning recently while preparing for the Solution Architect Associate exam and put my skills into action. I wrote two separate posts on my blog detailing the steps I took, so if you are curious have a look at the &lt;a href="https://cloudofthings.net/lab-70/" rel="noopener noreferrer"&gt;first&lt;/a&gt; and &lt;a href="https://cloudofthings.net/lab-76/" rel="noopener noreferrer"&gt;second&lt;/a&gt; one. &lt;/p&gt;


&lt;h3&gt;
  
  
  Additional notes
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/LesUski" rel="noopener noreferrer"&gt;
        LesUski
      &lt;/a&gt; / &lt;a href="https://github.com/LesUski/AWS-Cloud-Resume-Challenge-SAM" rel="noopener noreferrer"&gt;
        AWS-Cloud-Resume-Challenge-SAM
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      AWS Cloud Resume Challenge using AWS SAM
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Check my website if you’re looking for inspiration on AWS &lt;a href="https://cloudofthings.net/category/aws-labs/" rel="noopener noreferrer"&gt;hands-on labs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
