<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Phillip Ninan's Blog]]></title><description><![CDATA[Follow my software blog about Docker, Spring, Angular, and many other technologies. Learn how to become a senior software engineer. ]]></description><link>https://blog.phillipninan.com</link><generator>RSS for Node</generator><lastBuildDate>Tue, 19 May 2026 18:38:10 GMT</lastBuildDate><atom:link href="https://blog.phillipninan.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Mitigating the Log4J Vulnerability in Spring Boot]]></title><description><![CDATA[A lot of the documentation can be found here on Spring's website about the threat.
The most important part is the second paragraph.

Spring Boot users are only affected by this vulnerability if they have switched the default logging system to Log4J2....]]></description><link>https://blog.phillipninan.com/mitigating-the-log4j-vulnerability-in-spring-boot</link><guid isPermaLink="true">https://blog.phillipninan.com/mitigating-the-log4j-vulnerability-in-spring-boot</guid><category><![CDATA[Security]]></category><category><![CDATA[Springboot]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Thu, 23 Dec 2021 21:24:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1640276848765/aFCP7UbBA.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A lot of the documentation can be found <a target="_blank" href="https://spring.io/blog/2021/12/10/log4j2-vulnerability-and-spring-boot">here</a> on Spring's website about the threat.</p>
<p>The most important part is the second paragraph.</p>
<blockquote>
<p>Spring Boot users are only affected by this vulnerability if they have switched the default logging system to Log4J2. The log4j-to-slf4j and log4j-api jars that we include in spring-boot-starter-logging cannot be exploited on their own. Only applications using log4j-core and including user input in log messages are vulnerable.</p>
</blockquote>
<p>Therefore, If you have not explicitly brought in <code>log4j-core</code> into your application you SHOULD be fine. Although, there is a possibility that you are using a <a target="_blank" href="https://stackoverflow.com/questions/41725810/what-is-a-transitive-maven-dependency">transitive dependency</a> (dependency of a dependency) in your application. </p>
<p><a target="_blank" href="https://nvd.nist.gov/vuln/detail/CVE-2021-44228#vulnCurrentDescriptionTitle">Full details</a> here and <a target="_blank" href="https://www.deepwatch.com/blog/3-steps-to-detect-patch-log4j-log4shell-vulnerability/">here</a> on the threat. <a target="_blank" href="https://logging.apache.org/log4j/2.x/security.html">More</a> directly from Apache. </p>
<p><a target="_blank" href="https://www.lunasec.io/docs/blog/log4j-zero-day/">Here</a> is a good read on what the vulnerability is and who is impacted.</p>
<p><a target="_blank" href="https://stackoverflow.com/questions/70326613/how-to-identify-log4j2-or-log4j-in-maven-project">This</a> is how I used maven and the <code>grep</code> to determine if my projects were affected. If you find <code>log4j-core</code> version that is &lt; <code>2.17.0</code> you should update it immediately!</p>
<pre><code>mvn dependency:tree <span class="hljs-operator">-</span>Dverbose <span class="hljs-operator">|</span> grep <span class="hljs-built_in">log4</span>
</code></pre><p>I did find a transitive dependency was using the affected jar. I am the maintainer of the dependency so I was quickly able to put in a patch. Make sure you look for updates to your own dependencies if they contain the affected jar!</p>
<p>Best of luck!</p>
]]></content:encoded></item><item><title><![CDATA[When to Use AWS CDK Constructs vs Stacks]]></title><description><![CDATA[Are you confused about when to use a Construct vs a Stack when using the AWS CDK? They can be used interchangeably in a lot of situations. So when do you use one over the other? I could not find many resources on this topic so I decided to write abou...]]></description><link>https://blog.phillipninan.com/when-to-use-aws-cdk-constructs-vs-stacks</link><guid isPermaLink="true">https://blog.phillipninan.com/when-to-use-aws-cdk-constructs-vs-stacks</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws-cdk]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Mon, 30 Aug 2021 04:34:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1630034703977/cHF2ejAiA.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Are you confused about when to use a <code>Construct</code> vs a <code>Stack</code> when using the <a target="_blank" href="https://aws.amazon.com/cdk/">AWS CDK</a>? They can be used interchangeably in a lot of situations. So when do you use one over the other? I could not find many resources on this topic so I decided to write about it!</p>
<h2 id="heading-contents">☁️ Contents ☁️</h2>
<ul>
<li><a class="post-section-overview" href="#constructs">Constructs</a></li>
<li><a class="post-section-overview" href="#stacks">Stacks</a></li>
<li><a class="post-section-overview" href="#apps">Apps</a></li>
<li><a class="post-section-overview" href="#conclusion">Conclusion (TLDR)</a></li>
</ul>
<h2 id="heading-constructs">Constructs</h2>
<p>Constructs are the basic building blocks of the <a target="_blank" href="https://aws.amazon.com/cdk/">AWS CDK</a>. They create "cloud components" and encapsulate everything needed to provision the component. Under the hood, Constructs are deconstructed into <a target="_blank" href="https://aws.amazon.com/cloudformation/">AWS CloudFormation</a> templates. Almost anything you can do in AWS CloudFormation you can do with the AWS CDK!</p>
<p>A construct represents a single resource. For example, an <a target="_blank" href="https://aws.amazon.com/s3/">Amazon S3 bucket</a> or an <a target="_blank" href="https://aws.amazon.com/ec2/">Amazon EC2 server</a>. AWS has also developed higher-level Constructs. Higher-level Constructs can be created to abstract the complexity of provisioning multiple AWS resources. <a target="_blank" href="https://aws.amazon.com/ecs">AWS Elastic Container Service (ECS)</a> and <a target="_blank" href="https://docs.aws.amazon.com/cdk/api/latest/docs/aws-ecs-patterns-readme.html">ecsPatterns</a> are great examples of being able to create complicated cloud infrastructure in a handful of lines of code. </p>
<pre><code><span class="hljs-comment">// provision a load balancers, ECR repository, ECS service and task using one Contstuct!</span>
const loadBalancedEcsService <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> ecsPatterns.ApplicationLoadBalancedEc2Service(stack, <span class="hljs-string">'Service'</span>, {
  cluster,
  memoryLimitMiB: <span class="hljs-number">1024</span>,
  taskImageOptions: {
    image: ecs.ContainerImage.fromRegistry(<span class="hljs-string">'test'</span>),
    environment: {
      TEST_ENVIRONMENT_VARIABLE1: <span class="hljs-string">"test environment variable 1 value"</span>,
      TEST_ENVIRONMENT_VARIABLE2: <span class="hljs-string">"test environment variable 2 value"</span>
    },
  },
  desiredCount: <span class="hljs-number">2</span>,
});
</code></pre><p>Constructs communicate with each other. The AWS CDK team has done a great job of exposing attributes that allow you to create AWS CloudWatch Metrics, Alerts, and Dashboards. </p>
<h2 id="heading-stacks">Stacks</h2>
<p>Each group of deployed resources in the AWS CDK is called a stack. These resources are directly or indirectly provisioned as a single unit. This allows you to create modular cloud infrastructure that is interchangeable. </p>
<p>A great example of this is grouping frontend and backend components into their own stacks. If you are building a backend for an application using AWS ECS you can encapsulate all the resources into one stack. If you decide you would like to migrate your infrastructure to serverless using AWS Lambda, you can easily spin up a new stack and tear down the old one once you are done. </p>
<p>Here is an example of a <code>MetricsProps</code>. This provisions several AWS CloudWatch metrics for a number of <a target="_blank" href="https://aws.amazon.com/fargate/">AWS ECS Fargate Services</a>.</p>
<pre><code><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> cdk <span class="hljs-keyword">from</span> <span class="hljs-string">'@aws-cdk/core'</span>;
<span class="hljs-keyword">import</span> { Dashboard } <span class="hljs-keyword">from</span> <span class="hljs-string">"@aws-cdk/aws-cloudwatch"</span>;
<span class="hljs-keyword">import</span> { GraphWidget} <span class="hljs-keyword">from</span> <span class="hljs-string">"@aws-cdk/aws-cloudwatch"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> MetricsProps <span class="hljs-keyword">extends</span> cdk.StackProps {
    fargateService: ecs.FargateService[],
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> MetricsStack <span class="hljs-keyword">extends</span> cdk.Stack {
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">scope: cdk.Construct, id: <span class="hljs-built_in">string</span>, props: MetricsProps</span>) {
        <span class="hljs-built_in">super</span>(scope, id, props);

        <span class="hljs-comment">// dashboard</span>
        <span class="hljs-keyword">const</span> dashboard = <span class="hljs-keyword">new</span> Dashboard(<span class="hljs-built_in">this</span>, <span class="hljs-string">`'dev-dashboard`</span>, {
        });

        <span class="hljs-comment">// ecs     </span>
        <span class="hljs-keyword">const</span> ecsCPU = <span class="hljs-keyword">new</span> GraphWidget({
            width: <span class="hljs-number">6</span>,
            title: <span class="hljs-string">`ECS CPU Utilization`</span>,
            left: props.fargateService.map(<span class="hljs-function"><span class="hljs-params">service</span> =&gt;</span> service.metricCpuUtilization())
        });
        <span class="hljs-keyword">const</span> ecsMemory = <span class="hljs-keyword">new</span> GraphWidget({
            width: <span class="hljs-number">6</span>,
            title: <span class="hljs-string">`ECS Memory Utilization`</span>,
            left: props.fargateService.map(<span class="hljs-function"><span class="hljs-params">service</span> =&gt;</span> service.metricMemoryUtilization())
        });
        dashboard.addWidgets(ecsCPU, ecsMemory);
    }
}
</code></pre><h2 id="heading-apps">Apps</h2>
<p>Apps in the AWS CDK encapsulate Constructs and Stacks. Each component must be defined in an App. Each CDK project starts with an App! This construct is normally the root of the Construct tree.</p>
<pre><code><span class="hljs-meta">#!/usr/bin/env node</span>
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> cdk <span class="hljs-keyword">from</span> <span class="hljs-string">'@aws-cdk/core'</span>;
<span class="hljs-keyword">import</span> { Construct } <span class="hljs-keyword">from</span> <span class="hljs-string">'@aws-cdk/core'</span>;
<span class="hljs-keyword">import</span> { CdkApiStack, CdkApiStackProps } <span class="hljs-keyword">from</span> <span class="hljs-string">'../lib/cdk-base-stack/cdk-api-stack'</span>;
<span class="hljs-keyword">import</span> { CdkBaseStack, CdkBaseStackProps } <span class="hljs-keyword">from</span> <span class="hljs-string">'../lib/cdk-base-stack/cdk-base-stack'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DemoApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Construct</span></span>{
    <span class="hljs-keyword">constructor</span>(scope: cdk.App, id:string){
        <span class="hljs-built_in">super</span>(scope,id);
        <span class="hljs-comment">// create a small vpc for the demo</span>
        <span class="hljs-keyword">const</span> vpcProps: CdkBaseStackProps = {
            <span class="hljs-attr">stage</span>: id, 
            <span class="hljs-attr">description</span>: <span class="hljs-string">"Base VPC for AWS Cloud Application"</span>,
            <span class="hljs-attr">yourIpAddres</span>: <span class="hljs-string">""</span>,
            <span class="hljs-attr">tags</span>: {<span class="hljs-attr">env</span>: id},
            <span class="hljs-attr">stackName</span>: <span class="hljs-string">`PublicVpcStack-<span class="hljs-subst">${id}</span>`</span> <span class="hljs-comment">// used in cloudformation for naming stack</span>
        }        

        <span class="hljs-keyword">const</span> base:CdkBaseStack = <span class="hljs-keyword">new</span> CdkBaseStack(<span class="hljs-built_in">this</span>, <span class="hljs-string">`CdkVpcStack-<span class="hljs-subst">${id}</span>`</span>,
            vpcProps);

        <span class="hljs-comment">// create an API            </span>
        <span class="hljs-keyword">const</span> apiProps: CdkApiStackProps = {
            <span class="hljs-attr">stage</span>: id,
            <span class="hljs-attr">securityGroup</span>: base.defaultSecurityGroup,
            <span class="hljs-attr">vpc</span>: base.vpc,
            <span class="hljs-attr">secretName</span>: base.databaseCredentialsSecret.secretName
        }            

        <span class="hljs-keyword">const</span> api: CdkApiStack = <span class="hljs-keyword">new</span> CdkApiStack(<span class="hljs-built_in">this</span>, <span class="hljs-string">`CdkApiStack-<span class="hljs-subst">${id}</span>`</span>,
            apiProps);
    }
}
<span class="hljs-keyword">const</span> app = <span class="hljs-keyword">new</span> cdk.App();
<span class="hljs-keyword">new</span> DemoApp(app, <span class="hljs-string">'dev'</span>);
</code></pre><h2 id="heading-conclusion">Conclusion</h2>
<p>Let's sum up what we have just learned!</p>
<ul>
<li>Use Constructs to provision resources. </li>
<li>Use higher-level constructs to provision complex cloud components. </li>
<li>Use Stacks to group resources you would like to be deployed and destroyed together. </li>
<li>An App instance is your program's entry-point. This construct is normally the root of the Construct tree.</li>
</ul>
<blockquote>
<p>Pro Tip:
A common pattern is grouping stateful and stateless components. Stateful resources are such that cannot be easily recreated like a database. Stateless are easily re-creatable such as an AWS ECS Service.</p>
<p>Read my <a target="_blank" href="https://blog.phillipninan.com/a-no-nonsense-guide-to-aws-cloud-development-kit-cdk">No-Nonsense Guide To AWS Cloud Development Kit</a> to learn more!</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[AWS Lambda - Query Amazon RDS using Secrets]]></title><description><![CDATA[TLDR: Check out the complete code on  Github.

In this post, we will use AWS Lambda,  AWS Secrets Manager, and the node  pg package. I'll show you how to query a Postgres database using these resources. 
In my previous post, we used the AWS CDK to sp...]]></description><link>https://blog.phillipninan.com/aws-lambda-query-amazon-rds-using-secrets</link><guid isPermaLink="true">https://blog.phillipninan.com/aws-lambda-query-amazon-rds-using-secrets</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws lambda]]></category><category><![CDATA[PostgreSQL]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Tue, 27 Jul 2021 03:40:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1626930069381/uG_4f8xWZ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>TLDR: Check out the complete code on  <a target="_blank" href="https://github.com/fourgates/aws-cdk-rds-lambda-ssm/tree/main/src/get-query">Github</a>.</p>
</blockquote>
<p>In this post, we will use <a target="_blank" href="https://aws.amazon.com/lambda/">AWS Lambda</a>,  <a target="_blank" href="https://aws.amazon.com/secrets-manager/">AWS Secrets Manager</a>, and the <a target="_blank" href="https://github.com/brianc/node-postgres">node  pg</a> package. I'll show you how to query a <a target="_blank" href="https://www.postgresql.org">Postgres</a> database using these resources. </p>
<p>In my <a target="_blank" href="https://blog.phillipninan.com/provision-an-rds-instance-using-the-aws-cdk-and-secrets">previous post</a>, we used the <a target="_blank" href="https://aws.amazon.com/cdk/">AWS CDK</a> to spin up a Virtual Private Cloud (<a target="_blank" href="https://aws.amazon.com/vpc/">VPC</a>) and a Relational Database Service (<a target="_blank" href="https://aws.amazon.com/rds/">RDS</a>) Postgres database. We stored all the information we needed to log in to our RDS instance in AWS Secrets Manager. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627356785299/mwfiV8dBA.png" alt="query-rds-lambda.png" /></p>
<p>This is what we will be building. ☝🏽</p>
<h2 id="word-to-the-wise">Word to The Wise</h2>
<p>Using a serverless technology to query a relational database should be used cautiously. Constantly opening and closing database connections may be costly. Please read my <a class="post-section-overview" href="#relational-database-serverless-notes">Relational Database Serverless Notes</a> if you plan on uses a serverless technology to heavily query a relational database. My use case was a CRON that would execute periodically to check for errors. </p>
<blockquote>
<p>Note, if your database is not publically accessible this Lambda will need to be deployed in the VPC with proper <a target="_blank" href="https://docs.aws.amazon.com/vpc/latest/privatelink/vpc-endpoints.html">VPC endpoints</a> setup. I will be writing this up in a subsequent blog post. Please read this <a target="_blank" href="https://aws.amazon.com/premiumsupport/knowledge-center/connect-lambda-to-an-rds-instance/">AWS document</a>. It details the networking needed two allow communication between AWS Lambda and an RDS instance.</p>
</blockquote>
<h2 id="contents">☁️ Contents ☁️</h2>
<ul>
<li><a class="post-section-overview" href="#1-initialize-the-project">1. Initialize the Project</a></li>
<li><a class="post-section-overview" href="#2-create-folders-for-lambda-handler--optional-">2. Create Folders for Lambda Handler (Optional)</a></li>
<li><a class="post-section-overview" href="#3-install--pg-">3. Install <code>pg</code></a></li>
<li><a class="post-section-overview" href="#4-create-a-lambda-handler">4. Create a Lambda Handler</a></li>
<li><a class="post-section-overview" href="#5-load-secret">5. Load Secret</a></li>
<li><a class="post-section-overview" href="#6-create-database-connection">6. Create Database Connection</a></li>
<li><a class="post-section-overview" href="#7-query-the-database">7. Query the Database</a></li>
<li><a class="post-section-overview" href="#8-deploy">8. Deploy</a></li>
<li><a class="post-section-overview" href="#relational-database-serverless-notes">Relational Database Serverless Notes</a></li>
<li><a class="post-section-overview" href="#conclusion">Conclusion</a></li>
</ul>
<h2 id="1-initialize-the-project">1. Initialize the Project</h2>
<p>You can follow my <a target="_blank" href="https://blog.phillipninan.com/provision-an-rds-instance-using-the-aws-cdk-and-secrets">previous post</a> on how to deploy a VPC and RDS database using the <a target="_blank" href="https://aws.amazon.com/cdk/">AWS CDK</a>. Also, I have a post on using <a target="_blank" href="https://blog.phillipninan.com/deploy-a-lambda-function-using-aws-sam-in-5-minutes">AWS Serverless Application Model (SAM)</a>. You can use this to start a boilerplate Lambda in 5 minutes, but that is not required.</p>
<h2 id="2-create-folders-for-lambda-handler-optional">2. Create Folders for Lambda Handler (Optional)</h2>
<p>If you are following along with the AWS CDK blog post, we will be writing the Lambda function code in <code>src/get-query</code>. This folder will contain <code>app.js</code>. This is the code that the Lambda is going to execute. There will also be <code>package.json</code> and <code>node_modules</code> to store dependencies. (We could use a Lambda layer, but I'll leave that for a future post)</p>
<pre><code>mkdir -p src/<span class="hljs-keyword">get</span>-query
touch app.js
npm <span class="hljs-keyword">init</span>
</code></pre><h2 id="3-install-pg">3. Install <code>pg</code></h2>
<pre><code><span class="hljs-built_in">npm</span> i pg
</code></pre><h2 id="4-create-a-lambda-handler">4. Create a Lambda Handler</h2>
<p>The Lambda handler is the code that gets executed when a Lambda function is invoked. Let's start with boilerplate Lambda code. We are going to import the <code>pg</code> client to connect and query the database. Then we will instantiate a <code>SecretsManager</code> client to get the database info.</p>
<pre><code><span class="hljs-keyword">const</span> pg = <span class="hljs-built_in">require</span>(<span class="hljs-string">'pg'</span>)
<span class="hljs-keyword">var</span> AWS = <span class="hljs-built_in">require</span>(<span class="hljs-string">'aws-sdk'</span>),
    region = <span class="hljs-string">"us-east-1"</span>,
    secretParams,
    pgClient;

<span class="hljs-comment">// Create a Secrets Manager client</span>
<span class="hljs-keyword">var</span> client = <span class="hljs-keyword">new</span> AWS.SecretsManager({
    <span class="hljs-attr">region</span>: region
});

<span class="hljs-built_in">exports</span>.handler = <span class="hljs-keyword">async</span> (event, context, callback) =&gt; {

    <span class="hljs-keyword">return</span> {
        <span class="hljs-string">"isBase64Encoded"</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-string">"statusCode"</span>: <span class="hljs-number">200</span>,
        <span class="hljs-string">"body"</span>: <span class="hljs-string">"hello!"</span>
    }
}
</code></pre><h2 id="5-load-secret">5. Load Secret</h2>
<blockquote>
<p>If you are not following along with my <a target="_blank" href="https://blog.phillipninan.com/provision-an-rds-instance-using-the-aws-cdk-and-secrets">AWS CDK post</a> you can follow <a target="_blank" href="https://docs.aws.amazon.com/secretsmanager/latest/userguide/tutorials_basic.html">this tutorial</a> on how to add a secret to AWS Secrets Manager. </p>
</blockquote>
<p>Next, let's update the handler code. We will load the secret from Secrets Manager. We use a reference from an environment variable containing the name of our secret. You only need to do this if the Lambda is cold starting. Otherwise, we will reuse the cached credentials. Note, if you are deploying this in a private VPC you will need to deploy an <a target="_blank" href="https://docs.aws.amazon.com/systems-manager/latest/userguide/setup-create-vpc.html">SSM VPC Endpoint</a>.</p>
<pre><code>    <span class="hljs-comment">// cache the secret</span>
    <span class="hljs-keyword">if</span>(!secretParams){
        <span class="hljs-comment">// get secret string from secret manager</span>
        <span class="hljs-keyword">const</span> secretValue = <span class="hljs-keyword">await</span> client.getSecretValue({ <span class="hljs-attr">SecretId</span>: process.env.SECRET_NAME }).promise();
        secretParams = <span class="hljs-built_in">JSON</span>.parse(secretValue.SecretString);
    }
</code></pre><h2 id="6-create-database-connection">6. Create Database Connection</h2>
<p>Next, use the <code>secretParams</code> and <code>pg</code> to make a database connection! Again, the client will be reused on subsequent executions.</p>
<pre><code>    <span class="hljs-comment">// cache the client</span>
    <span class="hljs-keyword">if</span>(!pgClient){
        <span class="hljs-comment">// https://node-postgres.com/api/client</span>
        <span class="hljs-keyword">var</span> connectionInfo = {
            user: secretParams.username,
            password: secretParams.password,
            host: secretParams.host,
            database: <span class="hljs-string">"postgres"</span>,
            port: secretParams.port
        };
        pgClient = <span class="hljs-keyword">new</span> pg.Client(connectionInfo);
        <span class="hljs-keyword">await</span> pgClient.connect();
    }
</code></pre><h2 id="7-query-the-database">7. Query the Database</h2>
<p>Finally, you can use the client to perform a query and return it to the user!</p>
<pre><code>    <span class="hljs-keyword">const</span> queryResult = <span class="hljs-keyword">await</span> pgClient.query(<span class="hljs-string">"SELECT 'Eli' as player_name"</span>);
    <span class="hljs-keyword">return</span> {
        <span class="hljs-string">"isBase64Encoded"</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-string">"statusCode"</span>: <span class="hljs-number">200</span>,
        <span class="hljs-string">"body"</span>: <span class="hljs-built_in">JSON</span>.stringify(queryResult.rows ? queryResult.rows : <span class="hljs-literal">undefined</span>)
    }
</code></pre><h2 id="8-deploy">8. Deploy</h2>
<p>To deploy you can read <a target="_blank" href="https://blog.phillipninan.com/deploy-a-lambda-function-using-aws-sam-in-5-minutes">my post to use AWS SAM</a>, <a target="_blank" href="https://www.serverless.com/framework/docs/providers/aws/guide/deploying/">The Serverless Framework</a>, or manually copy and paste the code using the <a target="_blank" href="https://www.serverless.com/framework/docs/providers/aws/guide/deploying/">AWS Console</a>. </p>
<h2 id="relational-database-serverless-notes">Relational Database Serverless Notes</h2>
<p>Using a serverless technology to query a relational database can cause a lot of overhead with managing connections. If this is done on a regular basis it may be worth having a layer in between your Lambda and RDS. You can use <a target="_blank" href="https://aws.amazon.com/rds/proxy/">RDS Proxy</a> which will manage all the connection pooling for you. Or you can give <a target="_blank" href="https://aws.amazon.com/rds/aurora/serverless/">Amazon Aurora Serverless</a> a try! It's the only serverless relational database that I have come across.</p>
<h2 id="conclusion">Conclusion</h2>
<p>That's it! Deploy your Lambda or test it locally. You should be able to communicate with RDS (if it's publically accessible). We set this up without having to use any plaintext credentials. Secrets Manager gives you a secure way of storing and retrieving sensitive information.</p>
<p>Check out the complete code on <a target="_blank" href="https://github.com/fourgates/aws-cdk-rds-lambda-ssm/tree/main/src/get-query">Github</a>! If you have any questions feel free to DM me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a>! </p>
<p>I have another post on deck utilizing the AWS CDK to deploy these resources (VPC, RDS instance, Secrets Manager, Lamda, API Gateway). Stay tuned!</p>
]]></content:encoded></item><item><title><![CDATA[Types in TypeScript]]></title><description><![CDATA[TypeScript is a strict superset of ECMAScript 2015, which is itself a superset of ECMAScript 5, commonly referred to as JavaScript. As such, a JavaScript program is also a valid TypeScript program, and a TypeScript program can seamlessly consume Java...]]></description><link>https://blog.phillipninan.com/types-in-typescript</link><guid isPermaLink="true">https://blog.phillipninan.com/types-in-typescript</guid><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Thu, 17 Jun 2021 03:30:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1623898422481/EtFXyVoRm.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>TypeScript is a strict superset of ECMAScript 2015, which is itself a superset of ECMAScript 5, commonly referred to as JavaScript. As such, a JavaScript program is also a valid TypeScript program, and a TypeScript program can seamlessly consume JavaScript. - <a target="_blank" href="https://en.wikipedia.org/wiki/TypeScript#:~:text=TypeScript%20is%20a%20strict%20superset,program%20can%20seamlessly%20consume%20JavaScript.">Wikipedia</a></p>
</blockquote>
<p>One of the best features of TypeScript is, wait for it, Types! However, one of the most cumbersome features of TypeScript, for newbies, is Types! Let's talk about what they are, why you should use them, and the problems they can cause.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#what-are-types">What are Types?</a></li>
<li><a class="post-section-overview" href="#why-should-you-use-types">Why should you use Types?</a></li>
<li><a class="post-section-overview" href="#what-are-the-downsides-of-using-types">What are the downsides of using Types?</a></li>
<li><a class="post-section-overview" href="#conclusion">Conclusion</a></li>
<li><a class="post-section-overview" href="#bonus-content">Bonus Content</a></li>
</ul>
<h2 id="what-are-types">What are Types? 🤔</h2>
<p>TypeScript is a strongly typed, object-oriented, compiled language. Conversely, JavaScript is not strongly typed. In JavaScript, a variable can take many forms. A variable can be any type of object. For example a String or a Number. However, in TypeScript an object can only be one or the other. </p>
<pre><code>// this <span class="hljs-keyword">is</span> <span class="hljs-keyword">valid</span> <span class="hljs-keyword">in</span> JavaScript
let <span class="hljs-type">name</span> = "Phillip";
<span class="hljs-type">name</span> = <span class="hljs-number">4</span>;
</code></pre><pre><code><span class="hljs-comment">// this is NOT valid in TypeScript</span>
<span class="hljs-keyword">let</span> name: <span class="hljs-built_in">String</span> = <span class="hljs-string">"Phillip"</span>;
name = <span class="hljs-number">4</span>; <span class="hljs-comment">// this will cause compiler errors!</span>
</code></pre><h2 id="why-should-you-use-types">Why should you use Types?</h2>
<p>Types are great! They allow you to see which fields are available for an object. It also prevents developers from assigning the wrong value to a field. </p>
<p>A wonderful example is refactoring. I recently had to make major updates to an Angular application. Since we use Types we were able to easily modify fields and the compiler allowed us to easily make the appropriate changes to fix them! ALL HAIL TYPESCRIPT! 🙌🏽</p>
<h2 id="what-does-a-type-look-like">What does a Type look like?</h2>
<p>A Type in TypeScript is a simple interface. You define fields and the distinct type of the field.</p>
<pre><code><span class="hljs-selector-tag">interface</span> <span class="hljs-selector-tag">User</span> {
   <span class="hljs-attribute">id</span>: number;
   <span class="hljs-attribute">name</span>: string;
   <span class="hljs-attribute">dateOfBirth</span>: date;
   <span class="hljs-attribute">age</span>: number;
   <span class="hljs-attribute">funFacts</span>: string[];
   <span class="hljs-attribute">activeFlg</span>: boolean;
   <span class="hljs-attribute">mother</span>: User;
   <span class="hljs-attribute">father</span>: User;
   <span class="hljs-attribute">someObj</span>: any;
   <span class="hljs-attribute">idk</span>: unknown;
}
</code></pre><h2 id="what-are-the-downsides-of-using-types">What are the downsides of using Types?</h2>
<p>A strongly typed language means there is less flexibility. You need to define what your interfaces will look like. Based on how you configure your compiler there may be some strict rules to follow. </p>
<p>I have helped many developers debugs errors having to do with implicitly <code>any</code>. This means that a type for a parameter has not been explicitly defined.</p>
<p>Here are some examples of errors I have seen:</p>
<pre><code>parameter <span class="hljs-symbol">'req</span>' implicitly has an <span class="hljs-symbol">'any</span>' <span class="hljs-class"><span class="hljs-keyword">type</span>
<span class="hljs-title">parameter</span></span> <span class="hljs-symbol">'res</span>' implicitly has an <span class="hljs-symbol">'any</span>' <span class="hljs-class"><span class="hljs-keyword">type</span>
<span class="hljs-title">parameter</span></span> <span class="hljs-symbol">'res</span>' implicitly has an <span class="hljs-symbol">'any</span>' <span class="hljs-keyword">type</span>.ts(<span class="hljs-number">7006</span>)
error ts7006: parameter <span class="hljs-symbol">'req</span>' implicitly has an <span class="hljs-symbol">'any</span>' <span class="hljs-class"><span class="hljs-keyword">type</span>
<span class="hljs-title">error</span></span> ts7006: parameter <span class="hljs-symbol">'res</span>' implicitly has an <span class="hljs-symbol">'any</span>' <span class="hljs-class"><span class="hljs-keyword">type</span>
<span class="hljs-title">parameter</span></span> <span class="hljs-symbol">'user</span>' implicitly has an <span class="hljs-symbol">'any</span>' <span class="hljs-keyword">type</span>.ts(<span class="hljs-number">7006</span>)
</code></pre><p>This is a great example of code that I found on <a target="_blank" href="https://stackoverflow.com/questions/43064221/typescript-ts7006-parameter-xxx-implicitly-has-an-any-type">StackOverflow</a> which would produce one of these beautiful exceptions.</p>
<pre><code><span class="hljs-keyword">const</span> users = [...]
<span class="hljs-comment">// this line does not compile</span>
<span class="hljs-keyword">let</span> user = users.find(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> user.id === query);
</code></pre><p>The parameter <code>user</code> is being used in the <code>find</code> method but its type is unknown. Therefore, <code>id</code> may not be a valid attribute. </p>
<p>How do you fix this? 🔎</p>
<ol>
<li><p>You can EXPLICITLY use <code>any</code>! The <code>any</code> type allows us to assign literally “any” particular value to that variable, simulating vanilla JavaScript.</p>
<pre><code><span class="hljs-keyword">const</span> users = [...]
<span class="hljs-keyword">let</span> user = users.find(<span class="hljs-function">(<span class="hljs-params">user: <span class="hljs-built_in">any</span></span>) =&gt;</span> user.id === query);
</code></pre></li>
<li><p>The best thing to do would be to use a type to define the <code>users</code> array or the <code>find</code> method.</p>
<pre><code><span class="hljs-keyword">interface</span> User {id: <span class="hljs-built_in">number</span>;...}
...
...
<span class="hljs-keyword">const</span> users: User[] =[...]
<span class="hljs-keyword">let</span> user = users.find(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> user.id === query);
</code></pre></li>
<li><p>In your <code>tsconfig.json</code>, add <code>"noImplicitAny": false</code> to <code>"compilerOptions":{}</code>.</p>
<blockquote>
<p>What is <code>tsconfig.json</code>?
You will see this file is all TypeScript projects! This specifies the root files and the compiler options required to compile the project. </p>
<pre><code>{
<span class="hljs-string">"compilerOptions"</span>: {
<span class="hljs-keyword">...</span>
<span class="hljs-string">"noImplicitAny"</span>: false,
<span class="hljs-keyword">...</span>
},
<span class="hljs-string">"files"</span>: [
<span class="hljs-string">"core.ts"</span>,
<span class="hljs-keyword">...</span>
]
}
</code></pre></blockquote>
</li>
</ol>
<h2 id="conclusion">Conclusion</h2>
<p>TypeScript is awesome! Almost all of the projects I work on today leverage TypeScript. I feel the pros far outweigh the cons of using TypeScript over vanilla JavaScript. I highly recommend giving it a try on your next project! </p>
<blockquote>
<p>Pro Tip: If you know JavaScript you already know TypeScript! 😉</p>
</blockquote>
<h2 id="bonus-content">Bonus Content</h2>
<p>If you are interested in getting started with TypeScript read my article on <a target="_blank" href="https://blog.phillipninan.com/how-to-convert-expressjs-to-typescript">How to Convert Express.js to Typescript</a>!</p>
<h2 id="resources">Resources</h2>
<ul>
<li><a target="_blank" href="https://stackoverflow.com/questions/43064221/typescript-ts7006-parameter-xxx-implicitly-has-an-any-type">Typescript: TS7006: Parameter 'xxx' implicitly has an 'any' type</a></li>
<li><a target="_blank" href="https://basarat.gitbook.io/typescript/intro/noimplicitany">noImplicitAny</a></li>
<li><a target="_blank" href="https://www.typescriptlang.org/tsconfig">Intro to the TSConfig Reference</a></li>
<li><a target="_blank" href="https://angular.io/guide/typescript-configuration">Angular TypeScript Configuration</a></li>
<li><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/tsconfig-json.html">What is a tsconfig.json</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[What is Serverless?]]></title><description><![CDATA[How is serverless different than a normal server? What are the pros and cons? 
Serverless is a new buzzword. It's a popular way to deploy your code in the cloud. You can use serverless to scale to millions of requests! Serverless can execute code or ...]]></description><link>https://blog.phillipninan.com/what-is-serverless</link><guid isPermaLink="true">https://blog.phillipninan.com/what-is-serverless</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws lambda]]></category><category><![CDATA[lambda]]></category><category><![CDATA[serverless]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Thu, 20 May 2021 03:32:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1621396402020/mMyYRIWSt.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>How is serverless different than a normal server? What are the pros and cons? </p>
<p>Serverless is a new buzzword. It's a popular way to deploy your code in the cloud. You can use serverless to scale to millions of requests! Serverless can execute code or event host a database. This article is a high-level overview of what serverless is.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#what-is-a-server">What Is a Server?</a></li>
<li><a class="post-section-overview" href="#what-problem-does-serverless-solve">What Problem Does Serverless Solve?</a></li>
<li><a class="post-section-overview" href="#scalability">Scalability</a></li>
<li><a class="post-section-overview" href="#how-can-you-use-serverless">How Can You Use Serverless?</a></li>
<li><a class="post-section-overview" href="#serverless-advantages">Serverless Advantages</a></li>
<li><a class="post-section-overview" href="#serverless-drawbacks">Serverless Drawbacks</a></li>
<li><a class="post-section-overview" href="#conclusion">Conclusion</a></li>
</ul>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> if you would like to see more content like this! 🐦</p>
<h2 id="what-is-a-server">What Is a Server?</h2>
<blockquote>
<p>"In computing, a server is a piece of computer hardware or software that provides functionality for other programs or devices, called "clients". This architecture is called the client-server model." - <a target="_blank" href="https://en.wikipedia.org/wiki/Server_(computing%29">Wikipedia</a></p>
</blockquote>
<p>A server is someone else's computer, although you can own/run your own. The server is where an application is deployed. Most developers deploy their code to a remote server where someone else handles maintaining the hardware and software. This blog runs on a server!</p>
<h2 id="what-problem-does-serverless-solve">What Problem Does Serverless Solve?</h2>
<p>Servers can be expensive. For small projects, it can be a big financial obstacle. Your server needs to be running 24 hours a day to be able to handle requests at any given time. These costs add up when you pay hourly!</p>
<p>Here comes serverless to the rescue! You only pay <strong>when</strong> your code is being executed. Your code will get run when it needs to. You are charged for the amount of time and memory used.</p>
<p>Please note, serverless doesn't mean there is an absence of a server. Serverless infrastructure is running on someone else's managed server. This means you don't have to worry about patching software, network security, or uptime. You only pay when it's being used. Sounds great! Right?</p>
<h2 id="scalability">Scalability</h2>
<p>When your application (running on a classical server) starts to slow down, there are two ways to speed it up. Get a bigger server (scale-up/vertically) or get more servers (scale-out/horizontal). Both can be expensive options. You either need to provision these new servers or use services that will scale up and down automatically. </p>
<p>In a serverless world, you can scale to millions of requests. No new infrastructure required! There is no need to provision new servers. Hence, serverless!</p>
<h2 id="how-can-you-use-serverless">How Can You Use Serverless?</h2>
<h3 id="execute-your-code-in-the-cloud">Execute your code in the cloud</h3>
<ul>
<li><a target="_blank" href="https://aws.amazon.com/lambda/">AWS Lambda</a></li>
<li><a target="_blank" href="https://azure.microsoft.com/en-us/services/functions/">Azure Functions</a></li>
<li><a target="_blank" href="https://cloud.google.com/functions">GCP Cloud Functions</a></li>
<li><a target="_blank" href="https://vercel.com/docs/serverless-functions/introduction">Vercel</a><h3 id="serverless-databases">Serverless Databases</h3>
</li>
<li><a target="_blank" href="https://aws.amazon.com/dynamodb/">AWS DynamoDb</a></li>
<li><a target="_blank" href="https://aws.amazon.com/rds/aurora/serverless/">Amazon Aurora Serverless</a><h3 id="serverless-framework">Serverless Framework</h3>
</li>
<li><a target="_blank" href="https://www.serverless.com/">Serverless.com</a></li>
</ul>
<h2 id="serverless-advantages">Serverless Advantages</h2>
<ul>
<li>No servers to manage!</li>
<li>Scalability from the start</li>
<li>Cost-effective</li>
<li>Modular code</li>
<li>Easy to use deployment tools</li>
</ul>
<h2 id="serverless-drawbacks">Serverless Drawbacks</h2>
<p>It's not all rainbows.</p>
<ul>
<li>Cold starts - When your code has not been run recently there is latency</li>
<li>Requires proprietary tools</li>
<li>May result in redundant code</li>
<li>Complex caching</li>
<li>Debugging can tricky</li>
<li>Potential for costs to skyrocket due to buggy code or edge cases</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>In a world surrounded by servers, serverless infrastructure is coming to the forefront. Serverless can be leverage to be able to build infrastructure ready to scale from the start. You can also take advantage of the low cost to get started. Serverless is not a blanket solution. It is not perfect for all solutions. Yet, I strongly recommend you give it a try and decide for yourself. </p>
<p>Cheers! 🍻</p>
<h2 id="inspired-by">Inspired By</h2>
<p><a target="_blank" href="https://technically.substack.com/p/whats-serverless">Whats Serverless - Technically Substack</a></p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> if you would like to see more content like this! 🐦</p>
]]></content:encoded></item><item><title><![CDATA[Provision an RDS Instance using the AWS CDK and Secrets]]></title><description><![CDATA[TLDR: Checkout the complete code on GitHub Repo.
🐦 Follow me on Twitter if you would like to see more content like this! 🐦

Introduction
Today, I am going to show you how to provision an RDS instance using the AWS CDK. We will set up an AWS Secret ...]]></description><link>https://blog.phillipninan.com/provision-an-rds-instance-using-the-aws-cdk-and-secrets</link><guid isPermaLink="true">https://blog.phillipninan.com/provision-an-rds-instance-using-the-aws-cdk-and-secrets</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws-cdk]]></category><category><![CDATA[PostgreSQL]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Thu, 22 Apr 2021 03:03:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1619059552397/a08L713XW.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>TLDR:</strong> Checkout the complete code on <a target="_blank" href="https://github.com/fourgates/aws-cdk-rds-ssm">GitHub Repo</a>.</p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> if you would like to see more content like this! 🐦</p>
</blockquote>
<h2 id="introduction">Introduction</h2>
<p>Today, I am going to show you how to provision an RDS instance using the AWS CDK. We will set up an AWS Secret and System Parameter that can be used to allow other resources to connect without using plaintext credentials. Never keep database credentials in plaintext!</p>
<blockquote>
<p>Table Of Contents</p>
<ul>
<li><a class="post-section-overview" href="#introduction">Introduction</a></li>
<li><a class="post-section-overview" href="#check-out-a-starter-project">Check Out a Starter Project</a></li>
<li><a class="post-section-overview" href="#update-dependencies">Update Dependencies</a></li>
<li><a class="post-section-overview" href="#add-a-database-secret">Add a Database Secret</a></li>
<li><a class="post-section-overview" href="#create-a-system-parameter">Create a System Parameter</a></li>
<li><a class="post-section-overview" href="#load-default-security-group">Load Default Security Group</a></li>
<li><a class="post-section-overview" href="#optionally-open-access-from-your-ip">Optionally Open Access From Your IP</a></li>
<li><a class="post-section-overview" href="#configure--rds-instance">Configure  RDS Instance</a></li>
<li><a class="post-section-overview" href="#output-rds-endpoint">Output RDS Endpoint</a></li>
<li><a class="post-section-overview" href="#deploy">Deploy</a></li>
<li><a class="post-section-overview" href="#conclusion">Conclusion</a></li>
</ul>
</blockquote>
<h2 id="check-out-a-starter-project">Check Out a Starter Project</h2>
<p>We are going to start from <a target="_blank" href="https://blog.phillipninan.com/insider-secrets-of-aws-cdk-the-base-stack">my last post</a>, here is the <a target="_blank" href="https://github.com/fourgates/aws-cdk-base">GitHub Repo</a>. We want to start with a base stack. A base stack is where you should keep your stateful resources. Since a database cannot be easily re-constructed you should consider this stateful. We will be updating the base stack by adding an RDS database. </p>
<h2 id="update-dependencies">Update Dependencies</h2>
<p>First, we need to update the <code>dependencies</code> in <code>package.json</code>. We are going to need some new dependencies for this tutorial. Note, you should try to keep all the CDK dependency versions the same. </p>
<pre><code>  <span class="hljs-string">"dependencies"</span>: {
    ...
    <span class="hljs-string">"@aws-cdk/aws-rds"</span>: <span class="hljs-string">"1.95.1"</span>,
    <span class="hljs-string">"@aws-cdk/aws-secretsmanager"</span>: <span class="hljs-string">"1.95.1"</span>,
    <span class="hljs-string">"@aws-cdk/aws-ssm"</span>: <span class="hljs-string">"1.95.1"</span>
  }
</code></pre><h2 id="add-a-database-secret">Add a Database Secret</h2>
<p>Next, we will start to update the base stack! First, we need to set up a secret and a system parameter. You should never keep plaintext credentials in plaintext or in source control. The <a target="_blank" href="https://aws.amazon.com/secrets-manager/">AWS Secrets Manager</a> allows you to provide credentials to a number of other AWS resources in a secure way. Let's add the secret.</p>
<pre><code>    <span class="hljs-comment">// first, lets generate a secret to be used as credentials for our database</span>
    <span class="hljs-keyword">const</span> databaseCredentialsSecret = <span class="hljs-keyword">new</span> secretsManager.Secret(<span class="hljs-built_in">this</span>, <span class="hljs-string">`<span class="hljs-subst">${props?.stage}</span>-DBCredentialsSecret`</span>, {
      <span class="hljs-attr">secretName</span>: <span class="hljs-string">`<span class="hljs-subst">${props?.stage}</span>-credentials`</span>,
      <span class="hljs-attr">generateSecretString</span>: {
        <span class="hljs-attr">secretStringTemplate</span>: <span class="hljs-built_in">JSON</span>.stringify({
          <span class="hljs-attr">username</span>: <span class="hljs-string">'postgres'</span>,
        }),
        <span class="hljs-attr">excludePunctuation</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">includeSpace</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">generateStringKey</span>: <span class="hljs-string">'password'</span>
      }
    });    

    <span class="hljs-comment">// lets output a few properties to help use find the credentials </span>
    <span class="hljs-keyword">new</span> cdk.CfnOutput(<span class="hljs-built_in">this</span>, <span class="hljs-string">'Secret Name'</span>, { <span class="hljs-attr">value</span>: databaseCredentialsSecret.secretName }); 
    <span class="hljs-keyword">new</span> cdk.CfnOutput(<span class="hljs-built_in">this</span>, <span class="hljs-string">'Secret ARN'</span>, { <span class="hljs-attr">value</span>: databaseCredentialsSecret.secretArn }); 
    <span class="hljs-keyword">new</span> cdk.CfnOutput(<span class="hljs-built_in">this</span>, <span class="hljs-string">'Secret Full ARN'</span>, { <span class="hljs-attr">value</span>: databaseCredentialsSecret.secretFullArn || <span class="hljs-string">''</span> });
</code></pre><p>A couple of notes here:</p>
<ul>
<li>This is going to generate a password for the username <code>postgres</code></li>
<li>We are using a few <code>CfnOutput</code>s to print some of the secret resource values. This will allow you to either identify which secret we just created or be able to access it via the AWS CLI. Note, this will not actually output a password! These values will be output in the terminal when you deploy your infrastructure. </li>
</ul>
<h2 id="create-a-system-parameter">Create a System Parameter</h2>
<p>Next, we can simply create a system parameter with the secret. You will use this service to provide other AWS services with credentials to connect to RDS. </p>
<pre><code>    // next, <span class="hljs-keyword">create</span> a <span class="hljs-keyword">new</span> <span class="hljs-keyword">string</span> parameter <span class="hljs-keyword">to</span> be used
    <span class="hljs-keyword">new</span> ssm.StringParameter(this, <span class="hljs-string">'DBCredentialsArn'</span>, {
      parameterName: <span class="hljs-string">`${props?.stage}-credentials-arn`</span>,
      stringValue: databaseCredentialsSecret.secretArn,
    });
</code></pre><h2 id="load-default-security-group">Load Default Security Group</h2>
<p>Our next step will be to get the VPC default security group. The database should be in a security group so that we can set up connectivity between other resources deployed in a VPC.</p>
<pre><code>    // <span class="hljs-keyword">get</span> the <span class="hljs-keyword">default</span> <span class="hljs-keyword">security</span> <span class="hljs-keyword">group</span>
    let defaultSecurityGroup = SecurityGroup.fromSecurityGroupId(this, "SG", vpc.vpcDefaultSecurityGroup);
</code></pre><h2 id="optionally-open-access-from-your-ip">Optionally Open Access From Your IP</h2>
<p>You can optionally add a rule to allow access to the database from your IP. <strong>NOTE THIS IS NOT SECURE</strong>! You should always put your database in a private subnet! This part is for educational purposes. </p>
<pre><code>    <span class="hljs-selector-tag">if</span>(props?.yourIpAddres){
      <span class="hljs-comment">// your to access your RDS instance!</span>
      <span class="hljs-selector-tag">defaultSecurityGroup</span><span class="hljs-selector-class">.addIngressRule</span>(ec2.Peer.ipv4(props.yourIpAddres), ec2.Port.tcp(<span class="hljs-number">5432</span>), <span class="hljs-string">'allow 5432 access from my IP'</span>);
    }
</code></pre><h2 id="configure-rds-instance">Configure  RDS Instance</h2>
<p>Now, let us configure and create our RDS instance.</p>
<pre><code>    // finally, lets configure and <span class="hljs-keyword">create</span> our <span class="hljs-keyword">database</span>!
    const rdsConfig: rds.DatabaseInstanceProps = {
      <span class="hljs-keyword">engine</span>: rds.DatabaseInstanceEngine.postgres({ <span class="hljs-keyword">version</span>: rds.PostgresEngineVersion.VER_12_3 }),
      // optional, <span class="hljs-keyword">defaults</span> <span class="hljs-keyword">to</span> m5.large
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL),
      vpc,
      // make the db publically <span class="hljs-keyword">accessible</span>
      vpcSubnets: {
        subnetType: ec2.SubnetType.PUBLIC,
      },
      instanceIdentifier: <span class="hljs-string">`${props?.stage}`</span>,
      maxAllocatedStorage: <span class="hljs-number">200</span>,
      securityGroups: [defaultSecurityGroup],
      credentials: rds.Credentials.fromSecret(databaseCredentialsSecret), // <span class="hljs-keyword">Get</span> <span class="hljs-keyword">both</span> username <span class="hljs-keyword">and</span> <span class="hljs-keyword">password</span> <span class="hljs-keyword">from</span> existing secret
    }

    // <span class="hljs-keyword">create</span> the <span class="hljs-keyword">instance</span>
    this.rdsInstance = <span class="hljs-keyword">new</span> rds.DatabaseInstance(this, <span class="hljs-string">`${props?.stage}-instance`</span>, rdsConfig);
</code></pre><p>A couple of notes here:</p>
<ul>
<li>We are putting this into a public subnet. <strong>THIS IS NOT SECURE</strong>. You should always put your database in a private subnet. We are doing this for educational purposes. </li>
<li>I am creating the smaller database possible to save on costs. </li>
</ul>
<h2 id="output-rds-endpoint">Output RDS Endpoint</h2>
<p>Lastly, let's output the RDS endpoint so you can actually connect publically. Again, this is just for educational purposes. <strong>ALWAYS KEEP YOUR DATABASE IN A PRIVATE SUBNET.</strong></p>
<pre><code>    <span class="hljs-comment">// output the endpoint so we can connect!</span>
    new cdk.CfnOutput(<span class="hljs-keyword">this</span>, <span class="hljs-string">'RDS Endpoint'</span>, { value: <span class="hljs-keyword">this</span>.rdsInstance.dbInstanceEndpointAddress });
</code></pre><h2 id="deploy">Deploy</h2>
<p>That's it! Synthesize and deploy your code and you will have a provisioned database! This may take some time to come up. </p>
<pre><code><span class="hljs-attribute">cdk</span> synth
cdk deploy
</code></pre><h2 id="conclusion">Conclusion</h2>
<p>To get the credentials to connect to your new database you can either use the <a target="_blank" href="https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/get-secret-value.html">CLI</a> using the <code>CfnOutput</code> or you can manually find it in your AWS Secrets Manager console. In my subsequent posts, I will be using the RDS tutorial as a starting point for other resources to access it. Enjoy! 🍺 </p>
<blockquote>
<p><strong>TLDR:</strong> Checkout the <a target="_blank" href="https://github.com/fourgates/aws-cdk-rds-ssm">GitHub Repo</a> with the complete code.</p>
</blockquote>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> if you would like to see more content like this! 🐦</p>
<blockquote>
<p>Interested in having a 1:1 chat with me over this story, or AWS in general? Head over to <a target="_blank" href="https://www.hiretheauthor.com/phillip">Hire The Author</a> and let’s connect!</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Insider Secrets Of AWS CDK - The Base Stack]]></title><description><![CDATA[I just finished my No-Nonsense Guide To AWS Cloud Development Kit (CDK). Today, I am going to show you one of the essential AWS CDK building blocks: the Base Stack. So, grab your favorite cup of joe, and let me give you a quick overview.

TLDR: Check...]]></description><link>https://blog.phillipninan.com/insider-secrets-of-aws-cdk-the-base-stack</link><guid isPermaLink="true">https://blog.phillipninan.com/insider-secrets-of-aws-cdk-the-base-stack</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws-cdk]]></category><category><![CDATA[Cloud]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Fri, 09 Apr 2021 03:45:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1617939885499/_76pvLoAW.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I just finished my <a target="_blank" href="https://blog.phillipninan.com/a-no-nonsense-guide-to-aws-cloud-development-kit-cdk">No-Nonsense Guide To AWS Cloud Development Kit (CDK)</a>. Today, I am going to show you one of the essential AWS CDK building blocks: the Base Stack. So, grab your favorite cup of joe, and let me give you a quick overview.</p>
<blockquote>
<p><strong>TLDR:</strong> Checkout my <a target="_blank" href="https://github.com/fourgates/aws-cdk-base">GitHub Repo</a>. There are only two classes you need to be worried about, <code>cdk-base-stack.ts</code> and <code>cdk-app.ts</code>.</p>
</blockquote>
<h2 id="table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#base-stack">Base Stack</a></li>
<li><a class="post-section-overview" href="#cdk-app">CDK App</a></li>
<li><a class="post-section-overview" href="#conclusion">Conclusion</a></li>
</ul>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> if you would like to see more content like this! 🐦</p>
<h2 id="base-stack">Base Stack</h2>
<p>The base stack of a CDK app is where you should put resources that are not going to change, they are stateless. Using this pattern, you can keep your stateful resources (VPC, RDS, DDB, etc) intact while being able to tear down and recreate your stateless (EC2, ECS, S3, etc) resources. Stateless resources can be replaced without the risk of data loss.</p>
<p>In this example, we will be adding a Virtual Private Cloud (VPC) to our base stack. We will be extending a <code>Stack</code> in this <code>class</code>. A <code>Stack</code> should be used to deploy resources independently from the rest of the app resources. Conversely, <code>Constructs</code> all get deployed together. </p>
<p>Finally, we are going to make our VPC public. Here is a reference to the <a target="_blank" href="https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-ec2.Vpc.html">VPC construct</a>. You can create a public VPC to save costs. Private VPC's contain private subnets which require a <a target="_blank" href="https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html">NAT Gateway</a>. These incur costs on an hourly basis. </p>
<pre><code><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> cdk <span class="hljs-keyword">from</span> <span class="hljs-string">'@aws-cdk/core'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> ec2 <span class="hljs-keyword">from</span> <span class="hljs-string">'@aws-cdk/aws-ec2'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> CdkBaseStackProps <span class="hljs-keyword">extends</span> cdk.StackProps {
  stage: <span class="hljs-built_in">string</span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> CdkBaseStack <span class="hljs-keyword">extends</span> cdk.Stack {
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> vpc:ec2.Vpc;
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">scope: cdk.Construct, id: <span class="hljs-built_in">string</span>, 
                              props?: CdkBaseStackProps</span>) {
    <span class="hljs-built_in">super</span>(scope, id, props);

    <span class="hljs-comment">// create a VPC with no private subnets. </span>
    <span class="hljs-comment">// this is for our demo purpose as this will be </span>
    <span class="hljs-comment">// cheaper since you do not need a nat gateway</span>
    <span class="hljs-keyword">const</span> vpc = <span class="hljs-keyword">new</span> ec2.Vpc(<span class="hljs-built_in">this</span>, <span class="hljs-string">`VPC-<span class="hljs-subst">${props?.stage}</span>`</span>, {
      natGateways:<span class="hljs-number">0</span>,
      maxAzs: <span class="hljs-number">2</span>,
    });    

    <span class="hljs-built_in">this</span>.vpc = vpc;
  }
  get stackVpc() : ec2.Vpc{
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.vpc;
  }  
}
</code></pre><p>A couple of notes:</p>
<ul>
<li><code>CdkBaseStackProps</code> is a pattern you can follow to pass parameters your <code>Stack</code> or <code>Construct</code>. I added a <code>stage</code> field to distinguish environments. </li>
<li><code>natGateways:0</code> - this option ensures there are no private subnets</li>
</ul>
<h2 id="cdk-app">CDK App</h2>
<p>To bring everything together, you can look at our app. I have created a <code>DemoApp</code> class <code>Construct</code>. This will be composed of our <code>CdkBaseStack</code>.  You will ultimately end up adding more <code>Construct</code>s here to provision resources for your cloud application. </p>
<pre><code><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> cdk <span class="hljs-keyword">from</span> <span class="hljs-string">'@aws-cdk/core'</span>;
<span class="hljs-keyword">import</span> { Construct } <span class="hljs-keyword">from</span> <span class="hljs-string">'@aws-cdk/core'</span>;
<span class="hljs-keyword">import</span> { CdkBaseStack, CdkBaseStackProps } <span class="hljs-keyword">from</span> <span class="hljs-string">'../lib/cdk-base-stack/cdk-base-stack'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DemoApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Construct</span></span>{
    <span class="hljs-keyword">constructor</span>(scope: cdk.App, id:string){
        <span class="hljs-built_in">super</span>(scope,id);
        <span class="hljs-comment">// create a small vpc for the demo</span>
        <span class="hljs-keyword">const</span> vpcProps: CdkBaseStackProps = {
            <span class="hljs-attr">stage</span>: id, 
            <span class="hljs-attr">description</span>: <span class="hljs-string">"Base VPC for AWS Cloud Application"</span>,
            <span class="hljs-attr">tags</span>: {<span class="hljs-attr">env</span>: id},
            <span class="hljs-attr">stackName</span>: <span class="hljs-string">`PublicVpcStack-<span class="hljs-subst">${id}</span>`</span> <span class="hljs-comment">// used in cloudformation for naming stack</span>
        }        

        <span class="hljs-keyword">const</span> base:CdkBaseStack 
                  = <span class="hljs-keyword">new</span> CdkBaseStack(<span class="hljs-built_in">this</span>, <span class="hljs-string">`CdkVpcStack-<span class="hljs-subst">${id}</span>`</span>,
            vpcProps);
    }
}
<span class="hljs-keyword">const</span> app = <span class="hljs-keyword">new</span> cdk.App();
<span class="hljs-keyword">new</span> DemoApp(app, <span class="hljs-string">'dev'</span>);
</code></pre><p>A couple of notes here:</p>
<ul>
<li><code>const app = new cdk.App();</code> - this is what initializes our app. </li>
<li><code>new DemoApp(app, 'dev');</code> - this creates a <code>Construct</code> for our app. I am using <code>dev</code> as an environment. Once you are happy with this <code>Construct</code> you can simply instantiate a <code>DemoApp</code> for each environment! This will save you time and money. </li>
<li><code>tags: {env: id}</code> -  tags are very useful and can help you distinguish resources in diff environments. This can come in handy when looking at your billing. </li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>You now have a base class to use when deploying any infrastructure that requires a VPC by using the AWS CDK! As stated before, keep stateful resources (VPC, RDS, DDB, etc) in your base stack since you cannot easily recreate these. Stateless resources (EC2, ECS, S3, etc) can be encapsulated in constructs of their own. Stay tuned! More CDK tutorials to come!</p>
<blockquote>
<p><strong>TLDR:</strong> Checkout my <a target="_blank" href="https://github.com/fourgates/aws-cdk-base">GitHub Repo</a>. There are only two classes you need to be worried about, <code>cdk-base-stack.ts</code> and <code>cdk-app.ts</code>.</p>
</blockquote>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> if you would like to see more content like this! 🐦</p>
]]></content:encoded></item><item><title><![CDATA[A No-Nonsense Guide To AWS Cloud Development Kit (CDK)]]></title><description><![CDATA[In my previous post, I gave you five reasons why you should use the AWS Cloud Development Kit (CDK)! Today, I will give you a high-level overview of what the CDK is and how to use it. This guide assumes you already have an AWS account, have a basic u...]]></description><link>https://blog.phillipninan.com/a-no-nonsense-guide-to-aws-cloud-development-kit-cdk</link><guid isPermaLink="true">https://blog.phillipninan.com/a-no-nonsense-guide-to-aws-cloud-development-kit-cdk</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws-cdk]]></category><category><![CDATA[Cloud]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Mon, 05 Apr 2021 04:33:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1617137740513/5XC2jt7JK.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my <a target="_blank" href="https://blog.phillipninan.com/5-reasons-to-use-aws-cdk">previous post</a>, I gave you <strong>five</strong> reasons why you should use the AWS Cloud Development Kit (CDK)! Today, I will give you a high-level overview of what the CDK is and how to use it. This guide assumes you already have an AWS account, have a basic understanding of some AWS resources, and have <code>npm</code> installed.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#key-cdk-terms">Key CDK Terms</a></li>
<li><a class="post-section-overview" href="#aws-construct-library">AWS Construct Library</a><ul>
<li><a class="post-section-overview" href="#l1">L1</a></li>
<li><a class="post-section-overview" href="#l2">L2</a></li>
<li><a class="post-section-overview" href="#l3">L3 / Patterns</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#stacks-vs-constructs">Stacks vs Constructs</a></li>
<li><a class="post-section-overview" href="#how-many-stacks-should-my-application-have">How Many Stacks Should My Application Have?</a></li>
<li><a class="post-section-overview" href="#getting-started-cdk-example">Getting Started - CDK Example</a><ul>
<li><a class="post-section-overview" href="#install-aws-cli">Install AWS CLI</a></li>
<li><a class="post-section-overview" href="#install-aws-cdk">Install AWS CDK</a></li>
<li><a class="post-section-overview" href="#create-the-app">Create the app</a></li>
<li><a class="post-section-overview" href="#build-the-app">Build the app</a></li>
<li><a class="post-section-overview" href="#list-stacks-in-your-app">List stacks in your app</a></li>
<li><a class="post-section-overview" href="#add-an-amazon-s3-bucket">Add an Amazon S3 bucket</a></li>
<li><a class="post-section-overview" href="#synthesize-app">Synthesize App</a></li>
<li><a class="post-section-overview" href="#deploy-app">Deploy App</a></li>
<li><a class="post-section-overview" href="#modify-app">Modify App</a></li>
<li><a class="post-section-overview" href="#destroy-app-resources">Destroy App Resources</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#next-steps">Next Steps</a></li>
<li><a class="post-section-overview" href="#writing-your-own-constructs">Writing Your Own Constructs</a></li>
<li><a class="post-section-overview" href="#conclusion">Conclusion</a></li>
</ul>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> if you would like to see more content like this! 🐦</p>
<h2 id="key-cdk-terms">Key CDK Terms</h2>
<ul>
<li><strong>App</strong> - You can think of a CDK app as the <strong>composition of all the resources</strong> needed for your application. This can deploy your entire AWS infrastructure.</li>
<li><strong>Stacks</strong> - A stack in AWS CDK is the same as in AWS CloudFormation. You can think of stacks as <strong>groups of resources</strong> needed for your application. This is defined as a single unit of deployment.  An app can be composed of one or more stacks. </li>
<li><strong>Constructs</strong> - You can think of constructs as an <strong>individual object</strong> in a stack. These objects can be composed of one or many AWS resources. Constructs are the basic building blocks of an app or stack. Each stack is composed of constructs. </li>
<li><strong>Etc</strong> - I have listed the most important concepts. You can read more on the <a target="_blank" href="https://docs.aws.amazon.com/cdk/latest/guide/core_concepts.html">AWS documentation</a>!</li>
</ul>
<blockquote>
<p>Here is a useful diagram explaining these relationships.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1617136509362/C7AdUxn5w.png" alt="AppStacks.png" /></p>
</blockquote>
<h2 id="aws-construct-library">AWS Construct Library</h2>
<p>AWS provides an entire <a target="_blank" href="https://docs.aws.amazon.com/cdk/api/latest/docs/aws-construct-library.html">library full of constructs</a> that are ready to use. They are very well documented and provide no-nonsense example. Let's look at the different types of constructs. </p>
<h3 id="l1">L1</h3>
<p>Some constructs provide a single resource such as an Amazon S3 bucket or a Lambda function. These are known as <strong>level-one</strong> or <strong>L1</strong> for short. <strong>These constructs are very basic and must be manually configured. </strong> They will have a <code>Cfn</code> prefix and correspond directly to AWS CloudFormation specifications. New AWS services are supported in the AWS CDK as soon as AWS CloudFormation does. <a target="_blank" href="https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.CfnBucket.html"><code>CfnBucket</code></a> is a good example. It represents an Amazon S3 bucket where you MUST <strong>explicitly configure ALL the properties. </strong></p>
<pre><code><span class="hljs-keyword">const</span> bucket = new s3.CfnBucket(<span class="hljs-keyword">this</span>, <span class="hljs-string">"MyBucket"</span>, {
  bucketName: <span class="hljs-string">"MyBucket"</span>
});
</code></pre><h3 id="l2">L2</h3>
<p>The next level, <strong>curated</strong> or <strong>L2</strong>, provides constructs with common boilerplates and glue logic. <strong>These will come with convenient defaults and reduces the amount of knowledge you need to know about them.</strong> They will typically encapsulate their corresponding L1 modules. A good example is <a target="_blank" href="https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.Bucket.html"><code>s3.Bucket</code></a>. This class will create an Amazon S3 bucket with default properties and methods such as <a target="_blank" href="https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.Bucket.html#add-wbr-lifecycle-wbr-rulerule"><code>bucket.addLifeCycleRule()</code></a>, which adds a lifecycle rule to the bucket.</p>
<pre><code>new s3.Bucket(<span class="hljs-keyword">this</span>, <span class="hljs-string">'MyFirstBucket'</span>, {
  versioned: <span class="hljs-literal">true</span>
});
</code></pre><h3 id="l3">L3</h3>
<p>While others, <strong>called high-level</strong> or <em>patterns</em>, allow you to provision resources that are commonly used together. <strong>Construct <em>patterns</em> are designed to help you provision multiple resources based on common patterns with a limited amount of knowledge in a concise manner. </strong> <code>s3deploy.BucketDeployment</code> is a great example of a high-level construct. The L3 construct takes a bucket as an argument and uploads your code.</p>
<pre><code><span class="hljs-keyword">const</span> websiteBucket = new s3.Bucket(<span class="hljs-keyword">this</span>, <span class="hljs-string">'WebsiteBucket'</span>, {
  websiteIndexDocument: <span class="hljs-string">'index.html'</span>,
  publicReadAccess: <span class="hljs-literal">true</span>
});

new s3deploy.BucketDeployment(<span class="hljs-keyword">this</span>, <span class="hljs-string">'DeployWebsite'</span>, {
  sources: [s3deploy.Source.asset(<span class="hljs-string">'./website-dist'</span>)],
  destinationBucket: websiteBucket,
  destinationKeyPrefix: <span class="hljs-string">'web/static'</span> <span class="hljs-comment">// optional prefix in destination bucket</span>
});
</code></pre><h2 id="stacks-vs-constructs">Stacks vs Constructs</h2>
<p>Stacks and constructs can both be used to provision groups of AWS resources. Your cloud application can have many stacks leveraging different levels of constructs. The key difference is that stacks are deployed independently. <strong>Therefore, you should decouple constructs into stacks if you would like to isolate different layers of your cloud infrastructure.</strong> For example, you could compose multiple constructs into a<code>DevStack</code>. This stack can be configured for a development environment while having a different composition for production.</p>
<h2 id="how-many-stacks-should-my-application-have">How Many Stacks Should My Application Have?</h2>
<p>There is no hard and fast rule to determine this. I asked an <a target="_blank" href="https://twitter.com/nathankpeck">AWS employee</a> this question. He gave me a great response! </p>
<p>A stack is just a group of resources. One giant group of resources will inhibit your ability to tear down resources independently of your other resources.
Dividing your resources into smaller groups can make it easier to manage and roll back/forward changes.</p>
<p>He recommended always putting your networking and database layer (stateful resources) into a base stack. Next, you should put your application (stateless) resources into one or more stacks. This way you can tear down the app and recreate it while leaving up your network and database layer intact.</p>
<p>A second recommendation came from another <a target="_blank" href="https://twitter.com/realadamjkeller">AWS employee</a>. He noted the parallels between <a target="_blank" href="https://en.wikipedia.org/wiki/Conway%27s_law">Conway's law</a> and deploying stacks. </p>
<blockquote>
<p>"Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure."
— Melvin E. Conway</p>
</blockquote>
<p>Essentially, you may want to break down your stacks to mirror how your teams operates. At the end of the day, build in a way that makes the most sense for you and your team.</p>
<h2 id="getting-started-cdk-example">Getting Started - CDK Example</h2>
<blockquote>
<p><strong>TLDR</strong> - Here is a link to my <a target="_blank" href="https://github.com/fourgates/hello-cdk">Github Repo</a> with the fulling working example. </p>
</blockquote>
<h3 id="install-aws-cli">Install AWS CLI</h3>
<blockquote>
<p>First, you need to have the <a target="_blank" href="https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html">AWS CLI installed and configured</a>. The CDK uses the same credentials as AWS CLI.</p>
</blockquote>
<h3 id="install-aws-cdk">Install AWS CDK</h3>
<blockquote>
<p>Next, install the AWS CDK Toolkit using <code>npm</code></p>
<pre><code>npm <span class="hljs-keyword">install</span> -g aws-cdk
<span class="hljs-comment"># verify installation</span>
cdk <span class="hljs-comment">--version</span>
</code></pre></blockquote>
<h3 id="create-the-app">Create The App</h3>
<blockquote>
<p>Create a directory and initialize a project with your language of choice. I love TypeScript! </p>
<pre><code>mkdir hello-cdk
cd hello-cdk
# <span class="hljs-keyword">init</span> project
cdk <span class="hljs-keyword">init</span> app --language typescript
</code></pre></blockquote>
<h2 id="app-structure">App Structure</h2>
<blockquote>
<p>This is what the app file structure should looked like. A few notes. <code>bin</code> folder is the entry point. This is where the app is initialized. <code>cdk.out</code> directory is where the CloudFormation template gets generated. Lastly, <code>lib</code> is where all of your stacks and constructs will live.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1617596519813/CwvPI-ICs.png" alt="image.png" /></p>
</blockquote>
<h3 id="build-the-app">Build The App</h3>
<blockquote>
<p>Next, you will need to build your project whenever you make coding changes.</p>
<pre><code><span class="hljs-built_in">npm</span> run build
<span class="hljs-comment"># or you can watch</span>
<span class="hljs-built_in">npm</span> run watch
</code></pre></blockquote>
<h3 id="list-stacks-in-your-app">List Stacks in Your App</h3>
<blockquote>
<p>Verify everything is working and you see the stacks you are expecting. You should only have one stack at this point. </p>
<pre><code><span class="hljs-attribute">cdk</span> ls
</code></pre></blockquote>
<h3 id="add-an-amazon-s3-bucket">Add an Amazon S3 bucket</h3>
<blockquote>
<p>Next, I will show you how to add a construct. We will add a simply S3 bucket. You need to add dependencies for each package you wish to use. Please make sure all of your cdk package versions match or you can run into trouble!</p>
<pre><code><span class="hljs-built_in">npm</span> install @aws-cdk/aws-s3
</code></pre></blockquote>
<p>Update the stack inside the <code>lib</code> folder (~<code>hello-cdk-stack.ts</code>)</p>
<pre><code><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> cdk <span class="hljs-keyword">from</span> <span class="hljs-string">'@aws-cdk/core'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> s3 <span class="hljs-keyword">from</span> <span class="hljs-string">'@aws-cdk/aws-s3'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloCdkStack</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">cdk</span>.<span class="hljs-title">Stack</span> </span>{
  <span class="hljs-keyword">constructor</span>(scope: cdk.App, id: string, props?: cdk.StackProps) {
    <span class="hljs-built_in">super</span>(scope, id, props);

    <span class="hljs-comment">// new code</span>
    <span class="hljs-keyword">new</span> s3.Bucket(<span class="hljs-built_in">this</span>, <span class="hljs-string">'MyFirstBucket'</span>, {
      <span class="hljs-attr">versioned</span>: <span class="hljs-literal">true</span>
    });
  }
}
</code></pre><p>A couple of notes here</p>
<ul>
<li>The <code>scope</code>, <code>id</code>, and <code>props</code> variables are used as parameters for constructing both stacks and constructs. </li>
<li><strong>scope</strong> - This is the parent of the stack. In this case, the parent is our app. The scope for the s3 bucket is the <code>HelloCdkStack</code> stack. </li>
<li><strong>id</strong> - This is a way to uniquely identify resources across deployments. <code>MyFirstBucket</code> is the id of the s3 bucket construct. </li>
<li><strong>props</strong> - These are values that will be used to define our construct. You can see in the <code>Bucket</code> constructor that we are passing an option of <code>versioned: true</code>. These are typically always going to be optional. </li>
</ul>
<h3 id="synthesize-app">Synthesize App</h3>
<blockquote>
<p>As I stated in my previous post, CDK uses AWS CloudFormation under the hood. We need to convert our app code into a CloudFormation template. You can take a look in the <code>cdk.out</code> directory to see what the template looks like!</p>
<pre><code><span class="hljs-attribute">cdk</span> synth
</code></pre></blockquote>
<h3 id="deploy-app">Deploy App</h3>
<blockquote>
<p>The moment of truth! Let's deploy our bucket! If you have more than one stack defined you will need to choose one or use the <code>--all</code> option. You will see a nice progress bar.</p>
<pre><code><span class="hljs-attribute">cdk</span> deploy
</code></pre></blockquote>
<p>This is a <a target="_blank" href="https://docs.aws.amazon.com/cdk/latest/guide/apps.html">high-level</a> diagram of the workflow of building and deploying a CDK app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1617147103874/5cQpq3W_6.png" alt="image.png" /> </p>
<h3 id="modify-app">Modify App</h3>
<blockquote>
<p>At some point, you will need to update your infrastructure. Let's update our S3 construct.</p>
<pre><code><span class="hljs-string">new</span> <span class="hljs-string">s3.Bucket(this,</span> <span class="hljs-string">'MyFirstBucket'</span><span class="hljs-string">,</span> {
  <span class="hljs-attr">versioned:</span> <span class="hljs-literal">true</span>,
  <span class="hljs-attr">removalPolicy:</span> <span class="hljs-string">cdk.RemovalPolicy.DESTROY</span>,
  <span class="hljs-attr">autoDeleteObjects:</span> <span class="hljs-literal">true</span>
}<span class="hljs-string">);</span>
</code></pre><p>CDK offers a very nice tool to see what changes will be deployed. This is useful for see what resources will be removed, added, or modified. You can see what IAM policies will be adjusted.</p>
<pre><code><span class="hljs-attribute">cdk</span> diff
</code></pre><p>If you are happy with your changes you can deploy!</p>
<pre><code><span class="hljs-attribute">cdk</span> deploy
</code></pre></blockquote>
<h3 id="destroy-app-resources">Destroy App Resources</h3>
<blockquote>
<p>Finally, the day will come when you no longer need your resources! You can either just remove the resources you no longer need from your CDK code or destroy all the resources using a very useful command.</p>
<pre><code><span class="hljs-attribute">cdk</span> destroy
</code></pre></blockquote>
<h2 id="writing-your-own-constructs">Writing Your Own Constructs</h2>
<p>In addition to using the AWS Construct library, you can also create your own! Writing your own is as simple as composing a number of constructs already available via the Construct library. This allows you to encapsulate a number of constructs and easily reuse them. Let's look at a simple example:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> NotifyingBucketProps {
  prefix?: <span class="hljs-built_in">string</span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> NotifyingBucket <span class="hljs-keyword">extends</span> Construct {
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">scope: Construct, id: <span class="hljs-built_in">string</span>, props: NotifyingBucketProps = {}</span>) {
    <span class="hljs-built_in">super</span>(scope, id);
    <span class="hljs-keyword">const</span> bucket = <span class="hljs-keyword">new</span> s3.Bucket(<span class="hljs-built_in">this</span>, <span class="hljs-string">'bucket'</span>);
    <span class="hljs-keyword">const</span> topic = <span class="hljs-keyword">new</span> sns.Topic(<span class="hljs-built_in">this</span>, <span class="hljs-string">'topic'</span>);
    bucket.addObjectCreatedNotification(<span class="hljs-keyword">new</span> s3notify.SnsDestination(topic),
      { prefix: props.prefix });
  }
}
</code></pre><p>A couple of notes here:</p>
<ul>
<li>All you have to do to create your own Construct is use <code>extends Construct</code> and instantiate!</li>
<li>This construct encapsulates an Amazon S3 bucket and a AWS SNS notification into a class named <code>NotifyingBucket</code>.</li>
<li>You can use this custom construct by simply creating a new instance <code>new NotifyingBucket(this, 'MyNotifyingBucket');</code></li>
</ul>
<h2 id="next-steps">Next Steps</h2>
<p>I highly recommend giving the <a target="_blank" href="https://cdkworkshop.com/">CDK Workshop</a> a try! They go through a bigger example with fine details. Read <a target="_blank" href="https://aws.amazon.com/blogs/devops/best-practices-for-developing-cloud-applications-with-aws-cdk/">Best practices for developing cloud applications with AWS CDK</a>.</p>
<h2 id="conclusion">Conclusion</h2>
<p>The AWS CDK is a great tool for provisioning your cloud infrastructure! You can easily set up and destroy resources with a few lines of code. Keep this code in source control to monitor changes. Reuse your code for new projects or clients! I hope you enjoyed this tutorial! I will be writing some more in-depth articles going forward. </p>
<h2 id="special-thanks">Special Thanks</h2>
<p>I would like to take a moment to thank both <a target="_blank" href="https://twitter.com/nathankpeck">Nathan Peck</a> and <a target="_blank" href="https://twitter.com/realadamjkeller">Adam Keller</a> for helping me fine-tune this guide! They both gave me great feedback for improving this guide. </p>
<p>Cheers!</p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> if you would like to see more content like this! 🐦</p>
<blockquote>
<p>Here is a link to my <a target="_blank" href="https://github.com/fourgates/hello-cdk">Github Repo</a> with the fulling working example. </p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[5 Reasons to Use AWS CDK!]]></title><description><![CDATA[What is AWS CDK?
The AWS Cloud Development Kit (AWS CDK) is an open-source framework to help you provision cloud application resources by using your favorite programming languages! You can choose from TypeScript, JavaScript, Python, Java, or C#. 
Sim...]]></description><link>https://blog.phillipninan.com/5-reasons-to-use-aws-cdk</link><guid isPermaLink="true">https://blog.phillipninan.com/5-reasons-to-use-aws-cdk</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws-cdk]]></category><category><![CDATA[Amazon S3]]></category><category><![CDATA[ECS]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Wed, 24 Mar 2021 04:12:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1616558761879/Lztih-MEB.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="what-is-aws-cdk">What is AWS CDK?</h2>
<p>The <a target="_blank" href="https://aws.amazon.com/cdk/">AWS Cloud Development Kit (AWS CDK)</a> is an open-source framework to help you provision cloud application resources by using your favorite programming languages! You can choose from TypeScript, JavaScript, Python, Java, or C#. </p>
<p>Simply put, you can leverage the AWS CDK to write code that will provision (create) AWS resources. If you are familiar with AWS CloudFormation, you should feel pretty comfortable using the AWS CDK. The CDK actually uses CloudFormation under the hood!</p>
<h2 id="why-should-you-use-the-cdk">Why should you use the CDK?</h2>
<p>Provisioning cloud applications can be very challenging. This may require a lot of manual work, maintaining templates, or using domain-specific languages. The AWS CDK allows you to harness the power of languages you already know to model your applications. You can also leverage <strong>high-level constructs</strong> that do a lot of the heavy lifting for you!</p>
<p>Here are MY favorite reasons:</p>
<ol>
<li>You can spin up cloud infrastructure using <strong>TypeScript</strong>!</li>
<li>It allows you to <strong>reuse code</strong>. This is extremely useful when setting up multiple environments or applications.</li>
<li>The AWS CDK framework was built with <strong>best practices</strong> in mind. Using their framework and high-level constructs helps ensure, but does not guarantee, that you are using them correctly.</li>
<li>You can commit your code and leverage the AWS CDK as <strong>Infrastructure as Code (IaC)</strong>. This allows each change to be documented in source control and gives you the ability to utilize the same systems as your application source code. </li>
<li>You need to <strong>write less to achieve more</strong> when compared to CloudFormation or Terraform. </li>
</ol>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> if you would like to see more content like this! 🐦</p>
<h2 id="what-are-constructs">What are Constructs?</h2>
<p>Constructs are a fundamental building block of AWS CDK. Each construct represents a "cloud component". A construct encapsulates everything AWS CloudFormation needs to create the component. </p>
<p>A construct can be as simple as an Amazon Simple Storage Service (AWS S3) bucket:</p>
<pre><code>    new s3.Bucket(<span class="hljs-keyword">this</span>, <span class="hljs-string">'MyFirstBucket'</span>, {
      versioned: <span class="hljs-literal">true</span>
    });
</code></pre><p>It can also be abstract enough to create higher-level components that require multiple AWS resources. A great example of this is AWS Elastic Container Service (AWS ECS) constructs. This can require many components such as a cluster, service, task, and an Elastic Load Balancer (ELB). You can configure this with a handful of lines of code:</p>
<pre><code>    // <span class="hljs-keyword">Create</span> a <span class="hljs-keyword">load</span>-balanced Fargate service <span class="hljs-keyword">and</span> make it <span class="hljs-built_in">public</span>
    <span class="hljs-built_in">new</span> ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", {
      <span class="hljs-keyword">cluster</span>: <span class="hljs-keyword">cluster</span>, // Required
      cpu: <span class="hljs-number">512</span>, // <span class="hljs-keyword">Default</span> <span class="hljs-keyword">is</span> <span class="hljs-number">256</span>
      desiredCount: <span class="hljs-number">6</span>, // <span class="hljs-keyword">Default</span> <span class="hljs-keyword">is</span> <span class="hljs-number">1</span>
      taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") },
      memoryLimitMiB: <span class="hljs-number">2048</span>, // <span class="hljs-keyword">Default</span> <span class="hljs-keyword">is</span> <span class="hljs-number">512</span>
      publicLoadBalancer: <span class="hljs-keyword">true</span> // <span class="hljs-keyword">Default</span> <span class="hljs-keyword">is</span> <span class="hljs-keyword">false</span>
    });
</code></pre><p>The AWS CDK provisions these resources in a safe and repeatable manner. You can reuse this code to provision multiple environments. You can also compose your own custom constructs allowing you to start new projects much faster!</p>
<h2 id="conclusion">Conclusion</h2>
<p>At a high level, that's it! AWS CDK is a useful library that allows you to use your favorite programming language to provision cloud infrastructure. It allows you to quickly generate AWS resources, promotes best practices, and allows you to reuse code! </p>
<blockquote>
<p>Stay Tuned -- I am writing several tutorials demonstrating how to use the AWS CDK!</p>
</blockquote>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> if you would like to see more content like this! 🐦</p>
<h2 id="resources">Resources</h2>
<ul>
<li><a target="_blank" href="https://docs.aws.amazon.com/cdk/api/latest/docs/aws-construct-library.html">AWS CDK Construct Library</a></li>
<li><a target="_blank">AWS CDK TypeScript Docs</a></li>
<li><a target="_blank" href="https://docs.aws.amazon.com/cdk/latest/guide/ecs_example.html">AWS ECS Example</a></li>
<li><a target="_blank" href="https://cdkworkshop.com/">AWS CDK Workshop</a></li>
<li><a target="_blank" href="https://cdkworkshop.com/20-typescript.html">AWS CDK Workshop</a></li>
<li><a target="_blank" href="https://github.com/aws-samples/aws-cdk-examples/blob/master/typescript/ecs/fargate-service-with-local-image/index.ts">Github Examples provided by AWS</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Send an SNS notification using AWS Lambda]]></title><description><![CDATA[Welcome! Today, I am going to show you how to write an AWS Lambda Function that sends an SNS notification. 
🐦 Follow me on Twitter if you would like to see more content like this! 🐦
TLDR - Here is a link to my Github with the given code.
1. Initial...]]></description><link>https://blog.phillipninan.com/send-an-sns-notification-using-aws-lambda</link><guid isPermaLink="true">https://blog.phillipninan.com/send-an-sns-notification-using-aws-lambda</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws lambda]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Fri, 19 Mar 2021 04:31:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1616127970530/_ArCMhKp7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome! Today, I am going to show you how to write an AWS Lambda Function that sends an SNS notification. </p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> if you would like to see more content like this! 🐦</p>
<p>TLDR - Here is a link to my <a target="_blank" href="https://github.com/fourgates/blog-lambda-sns-demo">Github</a> with the given code.</p>
<h2 id="1-initialize-the-project">1. Initialize the Project</h2>
<blockquote>
<p>You can follow my <a target="_blank" href="https://blog.phillipninan.com/deploy-a-lambda-function-using-aws-sam-in-5-minutes">previous post</a> on how to use <a target="_blank" href="https://aws.amazon.com/serverless/sam/">AWS SAM</a> to spin up a boilerplate Lambda function. </p>
</blockquote>
<h2 id="2-email">2. Email</h2>
<blockquote>
<p>First, let's write a function to send an email and return a promise. </p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendEmail</span>(<span class="hljs-params">message</span>)</span>{
    <span class="hljs-keyword">const</span> awsRegion = <span class="hljs-string">"us-east-1"</span>;
    <span class="hljs-comment">// FIXME - update this ARN</span>
    <span class="hljs-keyword">const</span> snsTopic = <span class="hljs-string">'arn:aws:sns:us-east-1:12341234-ABCDABCD'</span>;
    <span class="hljs-keyword">const</span> snsSubject = <span class="hljs-string">'SNS Subject'</span>;
    <span class="hljs-comment">// Create publish parameters</span>
    <span class="hljs-keyword">var</span> params = {
      Message: message,
      Subject: snsSubject,
      TopicArn: snsTopic
    };
    <span class="hljs-keyword">var</span> sns = <span class="hljs-keyword">new</span> AWS.SNS({ region: awsRegion });
    <span class="hljs-keyword">return</span> sns.publish(params).promise();
}
</code></pre></blockquote>
<h2 id="3-next-we-bring-it-all-together-in-the-handler">3. Next, we bring it all together in the handler.</h2>
<pre><code><span class="hljs-keyword">const</span> AWS = <span class="hljs-built_in">require</span>(<span class="hljs-string">"aws-sdk"</span>);    

<span class="hljs-comment">/**
 * A Lambda function that sends an SNS message
 */</span>
<span class="hljs-built_in">exports</span>.handler = <span class="hljs-function">(<span class="hljs-params">event, context</span>) =&gt;</span> {
    <span class="hljs-keyword">let</span> message = <span class="hljs-string">"Hello from Lambda!"</span>;
    <span class="hljs-keyword">return</span> sendEmail(msg).then(<span class="hljs-function">(<span class="hljs-params">err,data</span>)=&gt;</span>{
        <span class="hljs-built_in">console</span>.log (<span class="hljs-string">"We are in the callback!"</span>);
        <span class="hljs-keyword">if</span> (err) {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Error sending a message'</span>, err);
            context.fail(err);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Sent message:'</span>, data.MessageId);
            context.succeed(<span class="hljs-string">"Done!"</span>);
        }      
    });
};
...
...
</code></pre><h2 id="4-add-an-sns-role">4. Add an SNS Role</h2>
<blockquote>
<p>You will need to add a policy for this Lambda to be able to properly send SNS messages. We need to make a small update to the CloudFormation template to make use of this. If you did not use AWS SAM to generate the project, you can simply update the assigned role using the AWS Console.</p>
<pre><code>  <span class="hljs-attr">snsLambdaFunction:</span>
    <span class="hljs-attr">Type:</span> <span class="hljs-string">AWS::Serverless::Function</span>
    <span class="hljs-attr">Properties:</span>
      <span class="hljs-attr">Handler:</span> <span class="hljs-string">src/handlers/index.handler</span>
      <span class="hljs-attr">Runtime:</span> <span class="hljs-string">nodejs12.x</span>
      <span class="hljs-attr">MemorySize:</span> <span class="hljs-number">128</span>
      <span class="hljs-attr">Timeout:</span> <span class="hljs-number">100</span>
      <span class="hljs-attr">Description:</span> <span class="hljs-string">A</span> <span class="hljs-string">Lambda</span> <span class="hljs-string">function</span> <span class="hljs-string">sends</span> <span class="hljs-string">an</span> <span class="hljs-string">SNS</span> <span class="hljs-string">notification.</span>
      <span class="hljs-attr">Policies:</span>
        <span class="hljs-comment"># Give Lambda basic execution Permission to the helloFromLambda</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">AWSLambdaBasicExecutionRole</span>
        <span class="hljs-comment"># This is the new policy</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">AmazonSNSFullAccess</span>
</code></pre><p>TLDR - Here is a link to my <a target="_blank" href="https://github.com/fourgates/blog-lambda-sns-demo">Github</a> with the given code.</p>
</blockquote>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> if you would like to see more content like this! 🐦</p>
<h2 id="conclusion">Conclusion</h2>
<p>That's it! In a couple of dozen lines of code, you can easily utilize SNS subscriptions to send notifications.</p>
]]></content:encoded></item><item><title><![CDATA[Deploy a Lambda Function using AWS SAM in 5 Minutes]]></title><description><![CDATA[Today, I am going to show you how to quickly get started with AWS Lambda Functions! I will show you how you can use Amazon's Serverless Application Model (SAM) to quickly generate a project and then seamlessly deploy it!
Prerequisite
To use AWS servi...]]></description><link>https://blog.phillipninan.com/deploy-a-lambda-function-using-aws-sam-in-5-minutes</link><guid isPermaLink="true">https://blog.phillipninan.com/deploy-a-lambda-function-using-aws-sam-in-5-minutes</guid><category><![CDATA[aws lambda]]></category><category><![CDATA[cli]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Thu, 11 Mar 2021 04:22:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1615436352101/BHZ-33VVS.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today, I am going to show you how to quickly get started with AWS Lambda Functions! I will show you how you can use Amazon's Serverless Application Model (SAM) to quickly generate a project and then seamlessly deploy it!</p>
<h2 id="prerequisite">Prerequisite</h2>
<p>To use AWS services you must first have an AWS account. Also, you need to <a target="_blank" href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html">install SAM</a> from the command line along with a few other requirements.</p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> to see even more content! 🐦</p>
<h2 id="1-sam-init">1. SAM Init</h2>
<p>Once you have SAM installed you can get started with our first command!</p>
<pre><code>sam <span class="hljs-keyword">init</span>
</code></pre><blockquote>
<p>Lets run <code>sam init</code> and use the <code>AWS Quick Start Template</code>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1615433853934/0BUPU0CLk.png" alt="init-1.png" /></p>
<p>Next, you can choose between packaging the AWS Lambda as a Zip that will be uploaded to S3 or an image you can push to ECR. For right now, we are going to stick with the Zip file approach.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1615433847672/6FDWYJdvc.png" alt="init-2.png" /></p>
<p>Now you get to choose your own runtime! There is a wide variety and just about any programmer should be able to get started. I am going to choose nodejs12.x for this tutorial. 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1615433841295/rghHNPQS-.png" alt="init-3.png" /></p>
<p>You will subsequently need to create a project name and select a template to generate. There are some very useful options from creating an API endpoint to scheduling an event to be run periodically. We are going to use the <code>From Scratch</code> option
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1615433833997/6Zs_ksuiq.png" alt="init-4.png" /></p>
<p>Finally, the project is generated! That was almost too easy. A <code>README.md</code> file was generated inside your source files. This includes very useful information that is outside the scope of the article.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1615433816578/SbJg4zKUR.png" alt="init-5.png" /></p>
</blockquote>
<h2 id="sam-test">SAM Test</h2>
<p>One of the most frequently asked questions about AWS Lambda's is, "How do you test them?" Now that we have a project initialized you can test it locally! SAM comes with built-in functionality to test your Lamba Functions. There are a number of ways to be able to pass parameters as well. We are going to keep it simple for this demonstration. </p>
<pre><code>sam <span class="hljs-keyword">local</span> invoke
</code></pre><blockquote>
<p>You can see the message that was generated in the starter project. There is also some useful logging to help you determine what costs will be associated with your AWS Lambda. 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1615433905044/VWFs7HIkv.png" alt="deploy-4.png" /></p>
</blockquote>
<h2 id="3-sam-build-and-deploy">3. SAM build &amp; deploy</h2>
<p>Finally, we can build and deploy this Lambda to AWS in a single line of code! When you build the project SAM will compile an AWS CloudFormation template, <code>template.yml</code> and a <code>samconfig.toml</code> file encapsulating your settings. There is also a file included telling SAM how to build your Lambda Function named <code>buildspec.yml</code>. </p>
<pre><code>sam build &amp;&amp; sam deploy <span class="hljs-comment">--guided</span>
</code></pre><blockquote>
<p>The project will get built. You can see our <code>npm install</code> occurring. You will subsequently be asked a series of basic questions and you can use all the default values.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1615433916715/Cqwl3AxgF.png" alt="deploy-1.png" /></p>
<p>SAM is very smart! Using CloudFormation, it will let you know which resources will be added, removed, or modified. 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1615433926846/GHSD0Soix.png" alt="deploy-2.png" /></p>
<p>You will be asked to confirm the CloudFormation changes. Once you do so your changes will be deployed. This may take several minutes. 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1615433936424/_9PRZgzE7.png" alt="deploy-3.png" /></p>
</blockquote>
<h2 id="conclusion">Conclusion</h2>
<p>That's it! In as little as 5-10 mins you should have a testable and deployed AWS Lambda Function deployed using AWS SAM! Check your code into source control and treat it like any other part of your software system. Cheers!</p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> to see even more content! 🐦</p>
<h2 id="cleanup-pro-tips">Cleanup Pro Tips</h2>
<blockquote>
<p>Find the CloudFormation Stack</p>
<pre><code>aws cloudformation <span class="hljs-built_in">list</span>-stacks --<span class="hljs-built_in">stack</span>-status-filter CREATE_COMPLETE
</code></pre><p>Delete the CloudFormation Stack</p>
<pre><code>aws cloudformation <span class="hljs-keyword">delete</span>-<span class="hljs-built_in">stack</span> --<span class="hljs-built_in">stack</span>-name my-<span class="hljs-built_in">stack</span>
</code></pre></blockquote>
]]></content:encoded></item><item><title><![CDATA[How to Containerize Spring Boot & Postgres (JDBC)]]></title><description><![CDATA[Today, I am going to show you how you can use Docker to containerize a Spring Boot application, start a Postgres SQL database, and wire it all together by using a JDBC connection! This is a quick and seamless way to prototype new ideas. You can get t...]]></description><link>https://blog.phillipninan.com/how-to-containerize-spring-boot-and-postgres-jdbc</link><guid isPermaLink="true">https://blog.phillipninan.com/how-to-containerize-spring-boot-and-postgres-jdbc</guid><category><![CDATA[Docker]]></category><category><![CDATA[Springboot]]></category><category><![CDATA[PostgreSQL]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Tue, 09 Mar 2021 04:30:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1615263593130/5MIQ6tyD8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today, I am going to show you how you can use Docker to containerize a Spring Boot application, start a Postgres SQL database, and wire it all together by using a JDBC connection! This is a quick and seamless way to prototype new ideas. You can get this started with one command!</p>
<p><strong>TLDL</strong> - Here is a link to my <a target="_blank" href="https://github.com/fourgates/blog-spring-boot-postgres-jdbc-docker">GitHub</a> with all my Code.</p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> to see even more content! 🐦</p>
<p>Here is a look at what your file structure should look like at the end:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1615263103775/EygKYOZXd.png" alt="Screen Shot 2021-03-08 at 11.10.55 PM.png" /></p>
<h2 id="1-checkout-and-optionally-run-spring-boot-app">1. Checkout and (Optionally) Run Spring Boot App</h2>
<p><strong>Note:</strong> 
<strong><em>If you cannot run the app or don't have Maven installed it's not a big deal. We will get it running in the container! I just typically like to be able to run an app outside of a container before I containerize it. This helps me debug issues if the app does not run as expected in the container.</em></strong></p>
<p>First, let's create a new Spring Boot project. Checkout the following Spring Boot starter app:</p>
<p><code>git clone https://github.com/fourgates/blog-spring-starter.git</code></p>
<p>Finally (optionally), start the project using Maven:</p>
<p><code>mvn spring-boot:run</code></p>
<p>Navigate to http://localhost:8080 or <code>curl localhost:8080</code> and you should see the following message:</p>
<blockquote>
<p>Greetings from Spring Boot!</p>
</blockquote>
<h2 id="2-add-dependencies-to-pomxml">2. Add Dependencies to <code>pom.xml</code></h2>
<p>Next, we are going to some dependencies to the project. </p>
<pre><code>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
             <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.postgresql<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
             <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>postgresql<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
             <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>42.2.6<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
         <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>            
        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
             <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
             <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-jdbc<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
         <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</code></pre><p>What are these new dependencies?</p>
<ul>
<li><code>postgresql</code> - This is a Postgres driver</li>
<li><code>spring-boot-starter-jdbc</code> - This is a JDBC driver to be able to communicate with a DB</li>
</ul>
<h2 id="3-create-a-datasource">3. Create a DataSource</h2>
<p>Create <code>SqlConfiguration.java</code> in <code>com/example/springboot/configuration</code>:</p>
<pre><code><span class="hljs-keyword">package</span> com.example.springboot.configuration;

<span class="hljs-keyword">import</span> javax.sql.DataSource;

<span class="hljs-keyword">import</span> org.springframework.beans.factory.<span class="hljs-keyword">annotation</span>.Value;
<span class="hljs-keyword">import</span> org.springframework.context.<span class="hljs-keyword">annotation</span>.Bean;
<span class="hljs-keyword">import</span> org.springframework.context.<span class="hljs-keyword">annotation</span>.Configuration;
<span class="hljs-keyword">import</span> org.springframework.jdbc.datasource.DriverManagerDataSource;

<span class="hljs-meta">@Configuration</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SqlConfiguration</span> </span>{

    <span class="hljs-meta">@Value(<span class="hljs-meta-string">"<span class="hljs-subst">${POSTGRES_USER}</span>"</span>)</span>
    <span class="hljs-keyword">private</span> String user;
    <span class="hljs-meta">@Value(<span class="hljs-meta-string">"<span class="hljs-subst">${POSTGRES_PASSWORD}</span>"</span>)</span>
    <span class="hljs-keyword">private</span> String password;
    <span class="hljs-meta">@Value(<span class="hljs-meta-string">"<span class="hljs-subst">${POSTGRES_DB}</span>"</span>)</span>
    <span class="hljs-keyword">private</span> String db;

    <span class="hljs-meta">@Bean</span>
    <span class="hljs-keyword">public</span> DataSource primary() {
      DriverManagerDataSource dataSource = new DriverManagerDataSource();
      dataSource.setDriverClassName(<span class="hljs-string">"org.postgresql.Driver"</span>);

      dataSource.setUrl(<span class="hljs-string">"jdbc:postgresql://spring_dev_db:5432/"</span> + db);
      dataSource.setUsername(user);
      dataSource.setPassword(password);

      <span class="hljs-keyword">return</span> dataSource;
    }
}
</code></pre><p>A couple of notes here:</p>
<ul>
<li><code>@Configuration</code> - This is a Spring Boot annotation that will initialize this class before the app starts.</li>
<li><code>@Value</code> - These values are going to get populated from environment variables</li>
<li><code>spring_dev_db:5432</code> - This is going to be the containerized DB we are going to run with our Spring Boot container. <code>5432</code> is the port we are going to use. </li>
</ul>
<h2 id="4-update-hellocontroller">4. Update <code>HelloController</code></h2>
<p>Next, we are going to add a very crude example demonstrating a JDBC connection with out containerized database.</p>
<pre><code><span class="hljs-keyword">package</span> com.example.springboot;

<span class="hljs-keyword">import</span> org.springframework.web.bind.<span class="hljs-keyword">annotation</span>.RestController;
<span class="hljs-keyword">import</span> org.springframework.beans.factory.<span class="hljs-keyword">annotation</span>.Autowired;
<span class="hljs-keyword">import</span> org.springframework.jdbc.core.JdbcTemplate;
<span class="hljs-keyword">import</span> org.springframework.web.bind.<span class="hljs-keyword">annotation</span>.RequestMapping;

<span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloController</span> </span>{

    <span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> JdbcTemplate jdbcTemplate;

    <span class="hljs-meta">@RequestMapping(<span class="hljs-meta-string">"/"</span>)</span>
    <span class="hljs-keyword">public</span> String index() {
        <span class="hljs-comment">// simply query to count the number of tables in our DB</span>
        int result = jdbcTemplate.queryForObject(<span class="hljs-string">"select count(*) from information_schema.tables"</span>, Integer.<span class="hljs-keyword">class</span>);
        return <span class="hljs-string">"Greetings from Spring Boot! table_count = "</span> + result;
    }
}
</code></pre><p>What did we do here?</p>
<ul>
<li><code>@Autowired</code> - This injects a <code>Bean</code></li>
<li><code>private  JdbcTemplate</code> - This is an interface to communicate with our DB</li>
<li><code>jdbcTemplate.queryForObject(...)</code> - Here we are simply making a query to demonstrate we have connectivity with our DB</li>
</ul>
<h2 id="5-create-a-dockerfile">5. Create a <code>Dockerfile</code></h2>
<p>Almost done! Let's create a <code>Dockerfile</code> to create a container to run our Spring Boot app inside of.</p>
<pre><code><span class="hljs-comment">### BUILD a maven builder. This will contain all mvn dependencies and act as an abstraction for all mvn goals</span>
<span class="hljs-attribute">FROM</span> maven:<span class="hljs-number">3</span>.<span class="hljs-number">5</span>.<span class="hljs-number">4</span>-jdk-<span class="hljs-number">8</span>-alpine as builder

<span class="hljs-comment"># create app folder for sources</span>
<span class="hljs-attribute">RUN</span> mkdir -p /build
<span class="hljs-attribute">RUN</span> mkdir -p /build/logs

<span class="hljs-comment"># The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile.</span>
<span class="hljs-attribute">WORKDIR</span> /build
<span class="hljs-attribute">COPY</span> pom.xml /build
<span class="hljs-comment">#Download all required dependencies into one layer</span>
<span class="hljs-attribute">RUN</span> mvn dependency:resolve &amp;&amp; mvn compile
</code></pre><h2 id="6-create-docker-composeyml">6. Create <code>docker-compose.yml</code></h2>
<p>Now we bring everything together with the <code>docker-compose</code> file! This file will start up our maven container for our Spring Boot app and another container with Postgres database. </p>
<pre><code><span class="hljs-attr">version:</span> <span class="hljs-string">"3.7"</span>
<span class="hljs-attr">services:</span>
  <span class="hljs-attr">spring_dev:</span>
    <span class="hljs-attr">build:</span>
      <span class="hljs-attr">context:</span> <span class="hljs-string">.</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">maven/builder:0.0.1</span>
    <span class="hljs-attr">container_name:</span> <span class="hljs-string">spring_container_api</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"8080:8080"</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">POSTGRES_USER=docker</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">POSTGRES_PASSWORD=docker</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">POSTGRES_DB=docker</span>      
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"./src:/build/src"</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"./target:/build/target:cached"</span>
    <span class="hljs-attr">command:</span> <span class="hljs-string">"mvn spring-boot:run"</span>
    <span class="hljs-attr">depends_on:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">spring_dev_db</span>    
  <span class="hljs-attr">spring_dev_db:</span>
    <span class="hljs-attr">container_name:</span> <span class="hljs-string">spring_dev_db</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">"postgres:12"</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"5432:5432"</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">POSTGRES_USER=docker</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">POSTGRES_PASSWORD=docker</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">POSTGRES_DB=docker</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">spring_dev_data:/var/lib/postgresql/data</span>
<span class="hljs-attr">volumes:</span>
  <span class="hljs-attr">spring_dev_data:</span> {}
</code></pre><p>A few things worth noting here:</p>
<ul>
<li><code>depends_on</code> - We use this here because out web app needs the database to start before the app 
itself starts</li>
<li>'spring_dev_db' - This is the name of the database container</li>
<li><code>image: "postgres:12"</code> - This is an official Postgres image we are pulling</li>
<li><code>ports</code> - What ports we want to map</li>
<li><code>environment</code> - This is a VERY important part. When the database starts up these are the credentials that will be created. Additionally, a database named <code>docker</code> will be created.</li>
<li><code>volumes</code> - The first instance volume says we will be using a volume named <code>spring_dev_data</code> to persist data when the container is restarted. The second instance, <code>spring_dev_data: {}</code>, simply initializes the volume. </li>
</ul>
<h2 id="5-start-the-app">5. Start the App</h2>
<p>That's all the code we need! You just need to run a few commands and your app should be up and running! </p>
<pre><code>docker-compose build
</code></pre><pre><code>docker-compose up
</code></pre><p>Navigate to http://localhost:8080/ and you should be greeted with a message telling you how many tables are in our database!</p>
<p>Here is a look at what your file structure should look like:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1615263103775/EygKYOZXd.png" alt="Screen Shot 2021-03-08 at 11.10.55 PM.png" /></p>
<h2 id="conclusion">Conclusion</h2>
<p>This was a very rudimentary example of using Docker to start up a Spring Boot app with a Postgres SQL database and a JDBC connection. There are many ORM alternatives to use to better handling the middle tier of selecting objects from the database. I will be covering them in future posts. This should provide a solid base to get up and started VERY QUICKLY when developing a Java web application using Spring Boot.</p>
<p>Here is a link to my <a target="_blank" href="https://github.com/fourgates/blog-spring-boot-postgres-jdbc-docker">GitHub</a> with my all Code.</p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> to see even more content! 🐦</p>
]]></content:encoded></item><item><title><![CDATA[Land a Software Job in 6 Months!]]></title><description><![CDATA[I have JS, PHP, HTML & CSS, but where would you suggest I go next? There’s so much to learn and it’s very confusing. I’m really scared of getting things wrong. Or asking for a road map if you like. 

This is a hard question to answer. You need to ask...]]></description><link>https://blog.phillipninan.com/land-a-software-job-in-6-months</link><guid isPermaLink="true">https://blog.phillipninan.com/land-a-software-job-in-6-months</guid><category><![CDATA[Roadmap]]></category><category><![CDATA[Developer]]></category><category><![CDATA[jobs]]></category><category><![CDATA[HTML]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Wed, 03 Mar 2021 03:51:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1614662526996/X-kLVSIQH.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>I have JS, PHP, HTML &amp; CSS, but where would you suggest I go next? There’s so much to learn and it’s very confusing. I’m really scared of getting things wrong. Or asking for a road map if you like. </p>
</blockquote>
<p>This is a hard question to answer. You need to ask yourself, "What are my goals"?</p>
<ul>
<li>Do you want to be able to build apps? Web apps? </li>
<li>Do you want to design very pretty-looking websites? </li>
<li>Do you want to want to make cool websites and get them to be on the first page of Google (SEO)? </li>
<li>Are you interested in AI or ML? Do you like databases?</li>
</ul>
<p>Once you figure out your goal(s), you can put a plan in place. I can help you figure out what steps you should take forward! All you need are some stepping stones. We can create a road map on how to accomplish your goal. Here is a simple roadmap for becoming a web application developer. </p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> to see even more content! 🐦</p>
<h2 id="important">!IMPORTANT!</h2>
<p>This is a high-level roadmap. This is not intended to turn you into an expert. This is ONE of MANY ways to HELP you land an entry-level web developer job. I have close to a decade of experience writing code. I regularly interview entry-level developers. If you were to complete each of these steps, absorb the material, and be able to speak intelligently about these topics I would be impressed. Take this advice with a grain of salt.</p>
<h2 id="1-learn-html-and-css">1. Learn HTML and CSS</h2>
<p><a target="_blank" href="https://www.freecodecamp.org/news/the-html-handbook/">FreeCodeCamp</a> is a great resource for this.  HTML and CSS is the foundation for any web application. Allocate 2-3 weeks for this.</p>
<h2 id="2-recreate-3-popular-websites">2. Recreate 3 Popular Websites</h2>
<p>Develop a landing page(s) using only HTML and CSS. <a target="_blank" href="https://www.apple.com">Apple</a>, <a target="_blank" href="https://github.com">GitHub</a>, and <a target="_blank" href="https://www.netflix.com">Netflix</a> are great choices! Understanding how popular websites are built will allow you to follow great patterns when you develop your own. Allocate 1-2 weeks to accomplish this.</p>
<h2 id="3-learn-javascript-and-npm">3. Learn JavaScript and NPM</h2>
<p><a target="_blank" href="https://www.freecodecamp.org/news/learn-javascript-full-course/">FreeCodeCamp</a> and <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/JavaScript_basics">MDN</a> are great resources for this. All modern websites utilize some sort of JavaScript framework. <a target="_blank" href="https://www.freecodecamp.org/news/tag/npm/">Node and NPM</a> are tools used to work with these frameworks. They allow you to use libraries and tools that someone else has already written! Allocate 2-3 weeks.</p>
<h2 id="4-recreate-2-popular-websites-with-javascript">4. Recreate 2 Popular Websites with JavaScript</h2>
<p>Pick 2 complex projects and recreate their basic functionality using JavaScript, HTML, and CSS. <a target="_blank" href="https://soundcloud.com">Soundcloud</a> and <a target="_blank" href="https://twitter.com">Twitter</a> are great examples. Allocate 2-3 weeks.</p>
<h2 id="5-learn-how-computers-and-the-internet-works">5. Learn How Computers and the Internet Works</h2>
<p>Search <a target="_blank" href="https://youtube.com">YouTube</a> and <a target="_blank" href="https://wikipedia.com">Wikipedia</a> and focus on the Application layer, HTTP, and how modern web apps work. You need to understand the basics of how web applications communicate. Allocate 1-2 weeks.</p>
<h2 id="6-learn-git-and-deploying">6. Learn Git and Deploying</h2>
<p>All software projects should use source control. <a target="_blank" href="https://www.atlassian.com/git">Atlassian</a> has great git tutorials. Deploy your projects to <a target="_blank" href="https://www.netlify.com">Netlify</a> or <a target="_blank" href="https://vercel.com">Vercel</a>. Allocate 1-2 weeks.</p>
<h2 id="7-learn-nodejs-and-express">7. Learn NodeJs and Express</h2>
<p>Use <a target="_blank" href="https://expressjs.com/en/starter/installing.html">official tutorials</a>, then <a target="_blank" href="https://youtube.com">YouTube</a> and <a target="_blank" href="https://stackoverflow.com">StackOverflow</a> if you don't understand something. I have a getting started tutorial <a target="_blank" href="https://blog.phillipninan.com/getting-started-with-expressjs-in-5-minutes">here</a>. Express and Node are great frameworks for build web applications QUICKLY. Allocate 2 weeks.</p>
<h2 id="8-learn-reactjs-and-redux">8. Learn ReactJS and Redux.</h2>
<p>I am a big advocate for Angular. But I think ReactJS is in the <a target="_blank" href="https://javascript.plainenglish.io/top-5-in-demand-javascript-frameworks-for-front-end-development-in-2020-a59c4340d082">biggest demand right now</a>. <a target="_blank" href="https://epicreact.dev">Kent C. Dodds</a> has a great course. <a target="_blank" href="https://www.udemy.com/topic/react/">Udemy</a> also has some great courses. Allocate 3 weeks.</p>
<h2 id="9-learn-graphql">9. Learn GraphQL</h2>
<p>Use <a target="_blank" href="https://graphql.org/graphql-js/">official tutorials</a> and YouTube (Udemy if needed). Then transfer your created apps to GraphQL. It should be relatively easy to migrate a small project to GraphQL, especially if you've gotten this far! Allocate 1 week.</p>
<h2 id="10-learn-typescript">10. Learn TypeScript</h2>
<p>Learn it using <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html">official docs</a>, YouTube &amp; Udemy if needed. After, transfer all created apps to the TypeScript. I have written a <a target="_blank" href="https://blog.phillipninan.com/how-to-convert-expressjs-to-typescript">great article</a> describing how to convert ExpressJS to TypeScript. Allocate 1 week.</p>
<h2 id="11-build-2-complex-applications">11. Build 2 Complex Applications</h2>
<p>Pick a popular service and recreate the core functionality using learned stack: ReactJS, <a target="_blank" href="https://www.toptal.com/react/navigating-the-react-ecosystem">React Ecosystem</a>, GraphQL, TypeScript, and ExpressJS. Then you will deploy it and put it on your resume. Allocate 2-4 weeks.</p>
<h2 id="12-create-a-resume-linkedin-profile-and-apply-for-jobs">12. Create a resume, LinkedIn profile and apply for jobs</h2>
<p>It should take you 1-4 weeks to land a job.</p>
<h2 id="conclusion">Conclusion</h2>
<p>This should take you roughly ~6 months. This roadmap is not meant to make you an expert. But it should make you competent enough to land an entry-level software developer job. If you complete this roadmap I am very confident that you will be a very marketable developer! Good Luck! Reach out to me for ANY help!</p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> to see even more content! 🐦</p>
<p>This roadmap was inspired by <a target="_blank" href="https://twitter.com/nickbulljs/status/1358326430204125185">Nick Bull</a>!</p>
]]></content:encoded></item><item><title><![CDATA[AWS Certifications Tips]]></title><description><![CDATA[Last year I passed my AWS Solutions Architect Certification test. I took the test remotely. It was a stressful experience because I did not know what the expect. I would like to share some tips to make your experience less stressful. 
🐦 Follow me on...]]></description><link>https://blog.phillipninan.com/aws-certifications-tips</link><guid isPermaLink="true">https://blog.phillipninan.com/aws-certifications-tips</guid><category><![CDATA[AWS]]></category><category><![CDATA[Certification]]></category><category><![CDATA[remote]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Thu, 25 Feb 2021 03:45:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1614268110701/-X8l6jG3O.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Last year I passed my <a target="_blank" href="https://blog.phillipninan.com/aws-certified-solutions-architect-associate">AWS Solutions Architect Certification</a> test. I took the test remotely. It was a stressful experience because I did not know what the expect. I would like to share some tips to make your experience less stressful. </p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> to see all vital content! 🐦</p>
<p>Here are some tips for taking the exam remotely:</p>
<ul>
<li>Check-in exactly 30 mins before the test starts, it took longer than I expected</li>
<li>Make sure you download the software the day before! I did not know this beforehand. I thought the test was taken in the browser.</li>
<li>Restart your computer the night before. </li>
<li>DONT MAXIMIZE THE TEST PROGRAM WINDOW! As soon as the proctor started my test, my screen had the test toolbar on the top but the rest of the screen was black and I got an infinite spinner. I waited ~15 mins before restarting my computer and trying to start the test again. Luckily, this was only ~10 mins after my test was supposed to start bc I was able to get started earlier.</li>
<li>Use the restroom before the test!</li>
<li>Answer the easy questions first and come back to the hard ones. There are a bunch of questions that should be super easy.</li>
<li>Once you are halfway through the test or maybe if you quickly get to the end, close your eyes and do some deep breathing for 30s. this will help you relax and focus better. </li>
<li>Once the test is done and you get your pass/fail MAKE SURE YOU CLICK END TEST!! I got excited and had to use the restroom and left the room. The proctor called me and said I had to hit the button and I was not supposed to leave the room. I was not penalized since the test had ended, but I was very stressed for the next 24 hours.</li>
<li>I took my exam at 1PM and got my grade the next morning. </li>
<li>Celebrate your passing grade! Take the time to take notes on topics you remember that you have trouble with so you can pass the exam the next time!</li>
</ul>
<p>Thanks again, everyone!!</p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> to see all vital content! 🐦</p>
]]></content:encoded></item><item><title><![CDATA[Building a SaaS Product (2)]]></title><description><![CDATA[In my prvevious post we put together a starter project for a SaaS product. Today, I am going to show you how to add Authentication to an Angular project by using AWS Amplify. This requires you to have an AWS account and may incur small charges to get...]]></description><link>https://blog.phillipninan.com/building-a-saas-product-2</link><guid isPermaLink="true">https://blog.phillipninan.com/building-a-saas-product-2</guid><category><![CDATA[Angular]]></category><category><![CDATA[SaaS]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Amplify Hashnode]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Thu, 25 Feb 2021 03:34:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1614223040536/4Q_X0Hob1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my <a target="_blank" href="https://blog.phillipninan.com/building-a-saas-product-1-setting-up-the-project-angular-expressjs">prvevious post</a> we put together a starter project for a SaaS product. Today, I am going to show you how to add Authentication to an <a target="_blank" href="https://angular.io">Angular</a> project by using <a target="_blank" href="https://aws.amazon.com/amplify/">AWS Amplify</a>. This requires you to have an <a target="_blank" href="https://portal.aws.amazon.com/billing/signup?redirect_url=https%3A%2F%2Faws.amazon.com%2Fregistration-confirmation#/start">AWS account</a> and may incur small charges to get this working. </p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> to see all vital content! 🐦</p>
<p><strong> TLDL</strong>: Here is the code in my <a target="_blank" href="https://github.com/fourgates/blog-saas-starter/tree/feature/amplify-auth">GitHub</a>. Here is a look at my <a target="_blank" href="https://github.com/fourgates/blog-saas-starter/pull/1">pull-request</a> with the necessary changes.</p>
<h2 id="prerequisite">Prerequisite</h2>
<ol>
<li><p>Follow these <a target="_blank" href="https://docs.amplify.aws/start/getting-started/installation/q/integration/angular#option-1-watch-the-video-guide">instructions</a> on how to install and configure the Amplify CLI. </p>
</li>
<li><p>Checkout my starter project on <a target="_blank" href="https://github.com/fourgates/blog-saas-starter/tree/feature/step-1-setting-up">GitHub</a>. Make sure you start on the <code>feature/step-1-setting-up</code> branch!</p>
</li>
</ol>
<h2 id="initialize-amplify">Initialize Amplify</h2>
<ol>
<li><p>Run the following code in the <code>webapp</code> folder. This will initialize an amplify project in our Angular project. You will then configure authentication. Finally, we will push these changes to AWS. You will be asked to login to your AWS account.</p>
<pre><code>amplify init 
<span class="hljs-comment"># make sure you store your keys for the new user!</span>
amplify configure
amplify add auth
amplify <span class="hljs-keyword">push</span>
</code></pre></li>
<li><p>Install the UI using NPM.</p>
<pre><code><span class="hljs-built_in">npm</span> install aws-amplify @aws-amplify/ui-angular
</code></pre></li>
</ol>
<h2 id="update-angular">Update Angular</h2>
<ol>
<li><p>Update app.module with this new code. We need to add imports for the AWS packages.</p>
<pre><code><span class="hljs-keyword">import</span> Amplify, { Auth } <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-amplify'</span>;
<span class="hljs-keyword">import</span> {AmplifyUIAngularModule} <span class="hljs-keyword">from</span> <span class="hljs-string">"@aws-amplify/ui-angular"</span>;
<span class="hljs-keyword">import</span> awsconfig <span class="hljs-keyword">from</span> <span class="hljs-string">'./aws-exports'</span>; 
Amplify.configure(awsconfig);
...
imports: [
  ...,
 AmplifyUIAngularModule
],
</code></pre></li>
<li><p>AWS Amplify requires a global variable to be accessible. Add this to the top of the file <code>src/polyfill.ts</code></p>
<pre><code>(<span class="hljs-keyword">window</span> <span class="hljs-keyword">as</span> <span class="hljs-keyword">any</span>).<span class="hljs-keyword">global</span> = <span class="hljs-keyword">window</span>;
(<span class="hljs-keyword">window</span> <span class="hljs-keyword">as</span> <span class="hljs-keyword">any</span>).process = {
env: { <span class="hljs-keyword">DEBUG</span>: undefined },
};
</code></pre></li>
<li><p>Replace all the template code in <code>app.component.html</code> with this</p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">amplify-authenticator</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
 My App
 <span class="hljs-tag">&lt;<span class="hljs-name">amplify-sign-out</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">amplify-sign-out</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">amplify-authenticator</span>&gt;</span>
</code></pre></li>
<li><p>Use a git ignore for <code>amplify/team-provider-info.json</code>. The file has sensitive info you don't want in source control!</p>
</li>
</ol>
<p>That's it! You should be able to run <code>ng serve</code> and be greeted with a login screen. </p>
<p>If you simply want to pull my git repo you will need to delete the <code>amplify</code> folder and run the following commands:</p>
<pre><code>amplify init 
<span class="hljs-comment"># make sure you store your keys for the new user!</span>
amplify configure
amplify add auth
amplify <span class="hljs-keyword">push</span>
</code></pre><p>Here is the code in my <a target="_blank" href="https://github.com/fourgates/blog-saas-starter/tree/feature/amplify-auth">GitHub</a>. Here is a look at my <a target="_blank" href="https://github.com/fourgates/blog-saas-starter/pull/1">pull-request</a> with the necessary changes.</p>
<p>🐦 Follow me on <a target="_blank" href="https://twitter.com/ninan_phillip">Twitter</a> to see all vital content! 🐦</p>
<p>Here are some screenshots from my setup:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1614056046403/LdznHEeWA.png" alt="amp-init.png" />
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1614056058831/5OeA6f1bJ.png" alt="amp add auth.png" />
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1614056073391/d-eiu1XFD.png" alt="amplify-push.png" /></p>
<h2 id="resource">Resource</h2>
<ul>
<li><a target="_blank" href="https://docs.amplify.aws/cli/teams/shared#sharing-projects-within-the-team">Sharing Amplify Projects</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[AWS Certified Solutions Architect Associate]]></title><description><![CDATA[This blog post is to kick off my journey in completing the AWS Solutions Architect Associate Certification. I currently plan on taking 3 months during my full-time job to prepare for the exam. I will use this post to outline what resources I plan on ...]]></description><link>https://blog.phillipninan.com/aws-certified-solutions-architect-associate</link><guid isPermaLink="true">https://blog.phillipninan.com/aws-certified-solutions-architect-associate</guid><category><![CDATA[AWS]]></category><category><![CDATA[AWS Certified Solutions Architect Associate]]></category><category><![CDATA[Cloud]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Tue, 23 Feb 2021 04:03:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1614052975584/FSxc17MEq.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is to kick off my journey in completing the <a target="_blank" href="https://aws.amazon.com/certification/certified-solutions-architect-associate/">AWS Solutions Architect Associate Certification</a>. I currently plan on taking 3 months during my full-time job to prepare for the exam. I will use this post to outline what resources I plan on using and will try to come back and up this as this changes.</p>
<p>A little background on my experience, I am a senior software engineer and technical lead on several projects. I have spent the past year working with a couple of different apps that have been deployed to AWS. I first started with setting up a Postgres database in RDS, then got authentication working with Cognito. We set up our Jenkins server on an EC2 instance and first deployed our apps there. We run our apps in Docker containers so we were able to take advantage of ECR to store our images and ECS to deploy them in different clusters. I got pretty familiar with security groups and load balancers for handling access issues and traffic. CloudWatch has been awesome for monitoring all our applications and aggregating logs. In all, I have been exposed to a good chunk of AWS services and have deployed to dev, staging, and production environments.</p>
<p>I plan to follow a very similar plan I found on <a target="_blank" href="https://www.reddit.com/r/AWSCertifications/comments/gp6v4w/passed_caa02_at_3_am/frkpajc/?context=3">Reddit</a>:</p>
<ol>
<li>Go through the entire <a target="_blank" href="https://acloudguru.com/course/aws-certified-solutions-architect-associate-saa-c02">ACG</a> video course. In order to help me digest the content, I plan on writing up some additional blog posts on topics I review</li>
<li>Read through <a target="_blank" href="https://aws.amazon.com/architecture/well-architected/">AWS Well-Architected whitepapers</a></li>
<li>Go through and take <a target="_blank" href="https://www.udemy.com/course/aws-certified-solutions-architect-associate-amazon-practice-exams-saa-c02/">Jon Bonso exams</a></li>
<li>Go back through the correct/incorrect answers from Bonso tests and take notes</li>
<li>Take the AWS practice exam</li>
<li>Take the exam!</li>
</ol>
<p>I plan on watching ~2 hours of videos a week which would allow me to finish the ACG video course in ~8 weeks. I am not sure if I need to take all the labs, but I will find out! That may affect my timeline. Then I plan on spending ~4 weeks going through the whitepapers and taking practice exams.</p>
<h2 id="update-1">Update (1)</h2>
<p>When I first started this course it was 14.5 hours and now it is more than 22 hours! Between the added hours and aggressive timelines at work, it has taken me longer than expected to finish this course. I also did try to get this done a little sooner by averaging 30-60 mins a night ~5 days a week. Ultimately, it took me about 9 weeks.</p>
<p>Lo and behold I have finished this weekend! I was able to take advantage of the High Availability (HA) topics and S3 to make sure major improvements to the current architecture in my ongoing projects. Therefore, It has been very worth it!</p>
<p>I plan on using the next couple of weeks to take practice exams and read through some AWS Whitepapers. All in, it will be about 3 months to study, prepare, and take the AWS Certified Solutions Architect Associate exam. I will keep you updated!</p>
<h2 id="update-2-i-passed">Update (2) I Passed!</h2>
<p>I officially passed my SAA-CO2!! I just wanted to take a moment to thank TutorialsDojo &amp; Jon Bonso! I could not have done it without you! You have put together the highest quality exams to prepare me for the real deal. You have built a great community has always been very responsive! </p>
<p>I took the ACG course and then spent the rest of my time taking these exams and using the 30 question review feature. I spent 2-4 hours on each test. I took the exam then the next day I would go through every answer to take notes and read answers and documentation on every question. I only retook two practice tests that I did not pass. </p>
<p>I highly highly recommend joining both <a target="_blank" href="https://techstudyslack.com">Adrian Cantrill - techstudyslack.com</a> and <a target="_blank" href="https://tutorialsdojo.com/our-aws-community-is-expanding/">Tutorial Dojo's</a> slack channels! I learned a lot from being on these channels! People are constantly asking great questions and there are some really great cloud engineers on there! It's a great community. </p>
<p>Here are some study tips:</p>
<ul>
<li>Lots of autoscaling group questions, understand this topic very well!</li>
<li>RDS, Mutli-AZ vs Read Replica</li>
<li>ELB (classic vs network vs app)</li>
<li>SQS (visibility timeout) FIFO, priorities </li>
<li>Kinesis, firehose vs datastream. know what targets are available</li>
<li>Lambda + API Gateway, when to use throttling</li>
<li>IPv4 vs IPv6</li>
<li>Lots of S3 question with classes and cost, S3 Lifecycle rules, Glacier, vs Glacier Deep Archive, know which classes have lifecycle restraints </li>
<li>NACL vs Security Groups</li>
<li>Dynamo DB use cases</li>
<li>Elastic cache uses cases, Redis vs Memached</li>
<li>NAT Gateway vs NAT Instance</li>
<li>VPC Gateway Endpoint - which services use this and how to set this up</li>
<li>Direct Connect components</li>
<li>Lots of VPN questions, Site to Site, VPN Hub, Transit Gateway</li>
<li>AWS Cloudtrail</li>
<li>Diff EC2 classes (compute vs memory etc) I did not see the HDD(cold) vs SDD(general) etc questions that come up a lot on the practice </li>
<li>File Gateway types</li>
<li>Aurora Serverless</li>
<li>IAM policies - how to construct them and know what they do</li>
<li>IAM Roles when to use them? are they global?</li>
<li>A lot of which file system to use (EBS, EFS, Storage Gateway, File Gateway), </li>
<li>Spot Instances, in terms of cost and termination</li>
<li>AWS Config - how it can be used, useful for tagging resources</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Monitoring Memory Leaks with AWS CloudWatch]]></title><description><![CDATA[I recently found a memory leak in one of my applications. This motivated me to write a post about how you can profile a Spring Boot web app using Visual VM. Today, I will be discussing how I initially found this leak using Amazon CloudWatch and what ...]]></description><link>https://blog.phillipninan.com/monitoring-memory-leaks-with-aws-cloudwatch</link><guid isPermaLink="true">https://blog.phillipninan.com/monitoring-memory-leaks-with-aws-cloudwatch</guid><category><![CDATA[AWS]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[monitoring]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Tue, 23 Feb 2021 03:52:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1614052421907/nub7h9mX6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently found a memory leak in one of my applications. This motivated me to write a <a target="_blank" href="https://blog.phillipninan.com/profile-spring-boot-with-visual-vm">post</a> about how you can profile a <a target="_blank" href="https://spring.io/projects/spring-boot">Spring Boot</a> web app using <a target="_blank" href="https://visualvm.github.io">Visual VM</a>. Today, I will be discussing how I initially found this leak using <a target="_blank" href="https://aws.amazon.com/cloudwatch/">Amazon CloudWatch</a> and what steps I took to prevent unexpected mayhem from occurring!</p>
<h2 id="aws-cloudwatch">AWS CloudWatch</h2>
<p>First off — what is Amazon CloudWatch? CloudWatch is the control center for monitoring all your AWS resources in one place. You should regularly monitor your applications to ensure there are no surprise outages.</p>
<p>After I wake up I prepare breakfast and a coffee while I prepare for my daily standup meeting. In doing so, I normally log into our AWS account and take a look at CloudWatch to see traffic and look for anything out of the ordinary. CloudWatch is an Amazon service you can use to monitor AWS resources.</p>
<p>We had recently deployed a new <a target="_blank" href="https://www.docker.com">containerized</a> application to <a target="_blank" href="https://aws.amazon.com/ecs/">AWS Elastic Container Service (ECS)</a>. I noticed a few unusual metrics with the new application. The CPU seemed to be very active despite not be used and the memory utilization was increasing near 90% then diving back down.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1613969709442/Br8d0WmRA.png" alt="0.-Found-Leak-in-Cloud-Watch-1.png" />
These are not good metrics!</p>
<p>Immediately, I knew that something was not right. The app was frequently crashing which was causing the memory and CPU dips. Therefore, I set up a CloudWatch alarm with an SNS alert to email my team when the CPU spiked higher than 60%. In this case, someone could manually restart the application to reset the memory to prevent the application from crashing unexpectedly. This would be a bandaid until we found a proper solution. I documented the steps needed to create such an alarm.</p>
<h2 id="setup-a-cloudwatch-alarm">Setup a CloudWatch Alarm</h2>
<ol>
<li><p>Create an alarm from AWS CloudWatch
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1613969823841/qKvIjthxn.png" alt="1.-Create-Button.png" /></p>
</li>
<li><p>Select a metric for the alarm
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1613969893733/fxxF6Dl_-.png" alt="2.-Select-Metric.png" /></p>
</li>
<li><p>Select a metric category. Here I am going to use an ECS serviceName metric.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1613970001617/xaMBrL6bl.png" alt="3.-Select-Memory.png" /></p>
</li>
<li><p>Select “MemoryUtilization” for your category
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1613969967205/zZj1VYcYJ.png" alt="4.-Select-Cluster.png" /></p>
</li>
<li><p>I set the alarm to go off if the average Memory Utilization was &gt; 60%
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1613970055372/UKi7zIyiE.png" alt="Screen-Shot-2020-08-20-at-2.31.11-AM.png" /></p>
</li>
<li><p>Use an SNS topic to send you or your team an email
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1613970095186/cDe2holfh.png" alt="6.-Config-2.png" /></p>
</li>
<li><p>Make sure to add a description to keep track of different alarms
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1613970171179/KdgzhxmeG.png" alt="7.-Config-3.png" /></p>
</li>
<li><p>Finally hit create!
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1613970211080/tP4OLyEmj.png" alt="8.-Create.png" /></p>
</li>
</ol>
<h2 id="setup-a-cloudwatch-dashboard">Setup a CloudWatch Dashboard</h2>
<p>Next, I will show you how to create a dashboard so you can take a look for yourself without setting up an alarm! CloudWatch Dashboards are very useful to get metrics for a variety of metrics across different services all in one place. I personally create a dashboard for each environment for a client: develop, QA, UAT, staging, production, etc. You first need to navigate to CloudWatch in your AWS account.</p>
<ol>
<li><p>Navigate to the dashboard link in CloudWatch and create a description
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1613970269354/22WHsNj1E.png" alt="1.-Create-Dashboard.png" /></p>
</li>
<li><p>Select a type of graph
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1613970302670/cfCEz3Vm0.png" alt="2.-Select-type-of-graph.png" /></p>
</li>
<li><p>Select a metric. Here I am using MemoryUtilization, but CloudWatch has a huge set of metrics
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1613970351450/xPDpg1jfj.png" alt="3.-Select-Metric.png" /></p>
</li>
<li><p>Finally save the Dashboard!
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1613970396865/GLNylBrEq.png" alt="4.-Save-Dashboard.png" /></p>
</li>
</ol>
<h2 id="conclusion">Conclusion</h2>
<p>I hope you enjoyed this post! Next, I will be writing a post describing exactly how I fixed this memory leak. Tune in and make sure to read my post about how to profile a <a target="_blank" href="https://blog.phillipninan.com/profile-spring-boot-with-visual-vm">Spring Boot application using Visual VM</a>.</p>
]]></content:encoded></item><item><title><![CDATA[AMA Mentoring - How Did You Begin Learning?]]></title><description><![CDATA[Ok, so in terms of CS degree, I have done scratch, the IOT & wireless comms. Covered html etc. The next module is python, which again is taking me down a different road... they are the resources I use a lot or did do to help me. How did you begin lea...]]></description><link>https://blog.phillipninan.com/ama-mentoring-how-did-you-begin-learning</link><guid isPermaLink="true">https://blog.phillipninan.com/ama-mentoring-how-did-you-begin-learning</guid><category><![CDATA[mentor]]></category><category><![CDATA[mentorship]]></category><category><![CDATA[Developer]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Wed, 17 Feb 2021 04:25:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1613535846241/veTUSikrj.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>Ok, so in terms of CS degree, I have done scratch, the IOT &amp; wireless comms. Covered html etc. The next module is python, which again is taking me down a different road... they are the resources I use a lot or did do to help me. How did you begin learning?</p>
</blockquote>
<p>As a software engineer I literally never stop learning (and I've been out of school for 8+ years). I feel like I learn something new every day. There are a few ways to go about this:</p>
<p>One is setting annual goals. Every year I've made a list of things I want to learn or improve. When I first started working I wasn't very good at JavaScript. I made it a priority to take on tasks and ask for help learning JavaScript at work. In a subsequent year, I wanted to improve my SQL skills. I volunteered for every DB task my company allowed me to do!</p>
<p>Secondly, I am very ambitious. I love to build things! Therefore, sometimes I have an idea for an app and I just figure out how to do it! I find other apps that are similar and I try to use that as a starting point. I read articles on related topics. I try to talk to individuals who have done something similar or the same thing and ask for advice. This requires a lot of patients and you need to be driven!</p>
<p>Thirdly, I try to fill voids in my job or make improvements. Recently, we started doing a lot of AWS work. I asked if my company would pay for training. They agreed and now I am certified. I am now my companies go to Amazon guy. As an engineer, you need to try to solve problems!</p>
<p>I am not going to lie, this is <strong>NOT</strong> going to be easy. It is going to be hard. You are going to have to go outside your comfort zone and learn many foreign concepts. It will be like climbing a mountain. But at some point, the path will start to flatten out. You will find a comfortable pace and meet people to help you along the way. You don't need to do this alone. There is a great community out there just waiting to help you!</p>
]]></content:encoded></item><item><title><![CDATA[AMA Mentoring - How to Get Started with TypeScript?]]></title><description><![CDATA[Do you know if there are any good sites to have a look at TypeScript, I’m more confused about just where to go?

I would just start with getting a high-level understanding of what TypeScript is. You don't need to go crazy with understanding every lit...]]></description><link>https://blog.phillipninan.com/ama-mentoring-how-to-get-started-with-typescript</link><guid isPermaLink="true">https://blog.phillipninan.com/ama-mentoring-how-to-get-started-with-typescript</guid><category><![CDATA[mentor]]></category><category><![CDATA[mentorship]]></category><category><![CDATA[Developer]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Mon, 15 Feb 2021 15:56:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1613404504163/yxcMqtTWH.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>Do you know if there are any good sites to have a look at TypeScript, I’m more confused about just where to go?</p>
</blockquote>
<p>I would just start with getting a high-level understanding of what TypeScript is. You don't need to go crazy with understanding every little thing about it. Understand <strong>WHY</strong> you should use TypeScript. Here are some quick resources I found.</p>
<p><a target="_blank" href="https://www.freecodecamp.org/news/learn-typescript-in-5-minutes-13eda868daeb/">Learn TypeScript in 5 Minutes</a></p>
<p><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html">TypeScript From Scratch</a></p>
<p>Once you have a high-level understanding I would do something practical. If you have done something simple in JavaScript, try to do the same thing in TypeScript. A great example of something I did was using Express.js. I knew it very well and learned how to convert it from JavaScript to TypeScript. Here is a blog post describing this process. It might be a good exercise for you!</p>
<p><a target="_blank" href="https://pninan.hashnode.dev/how-to-convert-expressjs-to-typescript">How to Convert Express.js to Typescriptt</a></p>
<p>You could also do something a little more structured like following an Angular tutorial. (I am a bit bias to Angular). Angular uses TypeScript and they have some really easy to follow along with tutorials. BUILDING apps has always been the best way for me to learn something new!</p>
<p><a target="_blank" href="https://angular.io/start">https://angular.io/start</a></p>
<p>Good Luck!</p>
]]></content:encoded></item><item><title><![CDATA[2020 Accomplishments - 2021 Goals]]></title><description><![CDATA[I thought I would share some of the things I accomplished in 2020, including joining Hashnode! As well as some goals I have set for myself for 2021. I hope some of this can be motivational for others. Enjoy!
2020 Accomplishments
AWS

I got AWS certif...]]></description><link>https://blog.phillipninan.com/2020-accomplishments-2021-goals</link><guid isPermaLink="true">https://blog.phillipninan.com/2020-accomplishments-2021-goals</guid><category><![CDATA[Developer]]></category><category><![CDATA[DevLife]]></category><dc:creator><![CDATA[Phillip Ninan]]></dc:creator><pubDate>Mon, 15 Feb 2021 15:49:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1611845327633/lZENR0Beq.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I thought I would share some of the things I accomplished in 2020, including joining Hashnode! As well as some goals I have set for myself for 2021. I hope some of this can be motivational for others. Enjoy!</p>
<h1 id="2020-accomplishments">2020 Accomplishments</h1>
<h2 id="aws">AWS</h2>
<ul>
<li>I got AWS certified! </li>
<li>AWS ECS has become my bread and butter</li>
<li>I setup AWS infrastructure using the AWS CDK in Typescript</li>
</ul>
<h2 id="work-9-5">Work (9-5)</h2>
<ul>
<li>I built my public-facing API</li>
<li>Help develop a platform for a new sports league. </li>
<li>Started to master Docker</li>
</ul>
<h2 id="online-presence">Online Presence</h2>
<ul>
<li>Started blogging</li>
<li>Became active on Twitter</li>
</ul>
<h2 id="finances">Finances</h2>
<ul>
<li>I was able to achieve a 32% return on my portfolio!</li>
<li>Upped my 401k contribution from 7% to 8%</li>
<li>I was able to generate additional income by giving consulting advice on AWS!</li>
</ul>
<h2 id="dev-tools">Dev Tools</h2>
<ul>
<li>I switched from using Eclipse to VS Code. This has made me much for efficient but took a few weeks to get comfortable. I highly recommend it. </li>
<li>I learned how to use VS Code to develop code over SSH on a remote server on AWS. This is useful if you want to develop code on multiple devices and can't always commit all your code at once. It also allows you to easily demo or share your code. Developing code on a remote SSH server is seamless!</li>
<li>I started using Notion for note-taking and it has been a game-changer!</li>
</ul>
<h2 id="personal">Personal</h2>
<ul>
<li>I built a Portfolio website</li>
<li>I started a personal blog</li>
<li>Hashnode become my favorite blogging platform</li>
<li>I ran my first First 10k</li>
<li>I found a passion  for boxed wine</li>
</ul>
<h2 id="learned-something-new">Learned Something New</h2>
<ul>
<li>Learned .NET for a month</li>
<li>Learned how to model a relational in a non-relational database (DynamoDb)</li>
</ul>
<h1 id="2021-goals">2021 Goals</h1>
<h2 id="aws">AWS</h2>
<ul>
<li>AWS cert 2, maybe? I need to weigh either more AWS certs will help me accomplish my goals. </li>
<li>Start an AWS consulting business</li>
</ul>
<h2 id="work-9-5">Work (9-5)</h2>
<ul>
<li>My current role at my company is as a Senior Software Engineer. I would like to position myself to be able to directly generate some type of revenue for my company. </li>
<li>Take steps to improve me as a team lead and senior software engineer. My goal is to help improve the developers on my team by setting a high bar and mentoring. I want to help them complete tasks that they previously felt uncomfortable with because it was not their strong suit. </li>
</ul>
<h2 id="online-presence">Online Presence</h2>
<ul>
<li>Get 1,000 Twitter followers</li>
<li>Become more active on LinkedIn and network with like-minded individuals</li>
<li>Get started on YouTube</li>
</ul>
<h2 id="finances">Finances</h2>
<ul>
<li>1 additional stream of passive income</li>
<li>Market and sell something</li>
<li>Bump 401k contribution from 8% to 9%</li>
<li>Finish a blog series on SOLID programming that will drive an Ebook I can write</li>
</ul>
<h2 id="dev-tools">Dev tools</h2>
<ul>
<li>Document design patterns I use on my blog. This serves as a tool to remind me of how to do something and allows me to share it with others. </li>
</ul>
<h2 id="personal">Personal</h2>
<ul>
<li>Wake up earlier</li>
<li>Lift weights again</li>
<li>Run a half marathon</li>
<li>Start blogging about personal finances</li>
</ul>
<h2 id="learn-something-new">Learn Something New</h2>
<ul>
<li>Put up my first YouTube video</li>
<li>Help my wife become an Amazon affiliate </li>
</ul>
]]></content:encoded></item></channel></rss>