<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Samuel Ronick</title>
    <description>The latest articles on Forem by Samuel Ronick (@samuelronick).</description>
    <link>https://forem.com/samuelronick</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1256623%2F3e7fad78-886f-458b-9be4-aa3c40e20971.jpg</url>
      <title>Forem: Samuel Ronick</title>
      <link>https://forem.com/samuelronick</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/samuelronick"/>
    <language>en</language>
    <item>
      <title>Deploy Express App as AWS Lambda Container with API Gateway using Terraform</title>
      <dc:creator>Samuel Ronick</dc:creator>
      <pubDate>Wed, 31 Jan 2024 12:51:15 +0000</pubDate>
      <link>https://forem.com/samuelronick/deploy-express-app-as-aws-lambda-container-with-api-gateway-using-terraform-35k3</link>
      <guid>https://forem.com/samuelronick/deploy-express-app-as-aws-lambda-container-with-api-gateway-using-terraform-35k3</guid>
      <description>&lt;p&gt;Welcome to a comprehensive tutorial where we'll navigate through a seamless step-by-step process to containerize your application, deploy it to AWS Elastic Container Registry (ECR), craft a Lambda function derived from the container image, and effortlessly establish a connection with API Gateway – all orchestrated using Terraform.&lt;/p&gt;

&lt;p&gt;In this guide, we'll demystify the intricacies of each stage, ensuring you grasp the nuances of containerization, AWS ECR deployment, Lambda function creation, and API Gateway integration, all while embracing the efficiency and simplicity that Terraform brings to the table.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites:
&lt;/h2&gt;

&lt;p&gt;Ensure you have a solid understanding of the following tools and have them installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.docker.com/products/docker-desktop/"&gt;Docker&lt;/a&gt;:  Containerization made easy &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.hashicorp.com/terraform/install?product_intent=terraform"&gt;Terraform&lt;/a&gt;: Infrastructure as code, simplified.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Agenda:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Setup AWS Access Key and Secret Key&lt;/li&gt;
&lt;li&gt;Develop an express application&lt;/li&gt;
&lt;li&gt;Containarize and deploy to AWS with Terraform&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup AWS Access Key and Secret Key
&lt;/h2&gt;

&lt;p&gt;go to aws console, navigate to the IAM and create a programmatic user with access policy of fullAdminAccess. copy your access key and secret key to a safe place.&lt;/p&gt;

&lt;p&gt;NOTE: &lt;span&gt;fullAdminAccess policy is not recommended for a production application, we are only using it for the purpose of this tutorial.&lt;/span&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Develop an express application.
&lt;/h2&gt;

&lt;p&gt;create a root directory&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd&lt;/code&gt; into root directory and create two folders. you can name the folders what ever you want.&lt;/p&gt;

&lt;h3&gt;
  
  
  folders
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;example. application code lives here.&lt;/li&gt;
&lt;li&gt;infrastructure. terraform code lives here.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;cd&lt;/code&gt; into example folder and enter the following commands&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm init -y&lt;/code&gt; &lt;code&gt;npm i cors&lt;/code&gt; &lt;code&gt;npm i express&lt;/code&gt; &lt;code&gt;npm i serverless-http&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  create index.js file in the example directory. copy and past the code below.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- index.js --&amp;gt;
import express from "express";
import cors from "cors";
import serverless from "serverless-http";

const app = express();

app.use(cors({ origin: true }));
app.use(express.json());

app.get("/", (req, res) =&amp;gt; {
  return res.status(200).json({ data: "welcome to lambda" });
});

app.post("/api", (req, res) =&amp;gt; {
  return res
    .status(200)
    .json({ data: "welcome to lambda post", registerData: req.body });
});

app.get("/apples", (req, res) =&amp;gt; {
  return res.status(200).json({ data: "welcome to apples route" });
});

app.post("/api/v1/register", (req, res) =&amp;gt; {
  return res
    .status(200)
    .json({ data: "register route", registerData: req.body });
});

export const handler = serverless(app);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create Dockerfile and .dockerignore file in the example directory.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Dockerfile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM public.ecr.aws/lambda/nodejs:20
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . . ${LAMBDA_TASK_ROOT}

CMD [ "index.handler" ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NOTE: &lt;span&gt;&lt;code&gt;{LAMBDA_TASK_ROOT}&lt;/code&gt; environment variable represents the root directory of the Lambda function&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;.dockerignore&lt;/p&gt;

&lt;p&gt;In here you can add files and folders you don't want docker to copy&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Containarize and deploy to AWS with Terraform
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;cd&lt;/code&gt; into "infrastructure" directory&lt;/p&gt;

&lt;p&gt;create a &lt;code&gt;data.tf&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data "aws_caller_identity" "current" {}

# token is needed for our local docker demeon to connect to aws ecr
data "aws_ecr_authorization_token" "token" {}

# lambda policy_document
data "aws_iam_policy_document" "assume_role" {
  statement {
    effect = "Allow"

    principals {
      type        = "Service"
      identifiers = ["lambda.amazonaws.com"]
    }

    actions = ["sts:AssumeRole" ]
  }
}

# lambda cloudwatch_policy_document
data "aws_iam_policy_document" "cloudwatch_policy" {
 statement {
    effect = "Allow"
    actions = [
      "logs:CreateLogGroup",
      "logs:CreateLogStream",
      "logs:PutLogEvents"
      ]
    resources = ["arn:aws:logs:*:*:*"]  // Allows access to all CloudWatch Logs resources
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  create a &lt;code&gt;variables.tf&lt;/code&gt; file
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "aws_region" {
  type        = string
  default     = "eu-west-1"
  description = "aws region for current resource"
}

variable "name_alias" {
  type = string
  default = "example_app"
  description = "name alias"  // ad your descrioption as needed
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  create a &lt;code&gt;local.tf&lt;/code&gt; file
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;locals {
  aws_ecr_url = "${data.aws_caller_identity.current.account_id}.dkr.ecr.${var.aws_region}.amazonaws.com"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  create a &lt;code&gt;provider.tf&lt;/code&gt; file
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }

    docker = {
      source  = "kreuzwerker/docker"
    }
  }
}

provider "aws" {
  region     = "eu-west-1" // you can choose your region of prefrence
  access_key = "YOUR AWS ACCESS KEY GOES HERE"
  secret_key = "YOUR AWS SECRET KEY GOES HERE"
}

provider "docker" {
    registry_auth {
        address  = local.aws_ecr_url
        username = data.aws_ecr_authorization_token.token.user_name
        password = data.aws_ecr_authorization_token.token.password
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Containarize and deploy to AWS with Terraform
&lt;/h2&gt;

&lt;p&gt;we are now going to containarize our application, create an ecr repo, deploy the application image, create lambda function from the image and integrate api-gateway to lambda.&lt;/p&gt;

&lt;h3&gt;
  
  
  create a &lt;code&gt;main.tf&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# create ecr repository
resource "aws_ecr_repository" "shedular" {
  name                 = "repo_${var.name_alias}"
  image_tag_mutability = "MUTABLE"
}

# build and push image to ecr with docker
resource "docker_image" "lambda_image" {
  name = "${aws_ecr_repository.shedular.repository_url}:latest"
  build {
    context = "../example"
    dockerfile = "Dockerfile"
  }

  triggers = {
    dir_sha1 = sha1(join("", [for f in fileset(path.module, "../example/*/*") : filesha1(f)]))
  }
}

# push image to ecr
resource "docker_registry_image" "helloworld" {
  name          = docker_image.lambda_image.name 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  create a &lt;code&gt;lambda.tf&lt;/code&gt; file
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# lambda iam role
resource "aws_iam_role" "iam_for_lambda" {
  name               = "iam_for_lambda_${var.name_alias}"
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

# Attach CloudWatch policy to IAM role
resource "aws_iam_role_policy" "cloudwatch_policy" {
  name   = "cloudwatch_lambda_policy"
  role   = aws_iam_role.iam_for_lambda.id
  policy = data.aws_iam_policy_document.cloudwatch_policy.json
}

resource "aws_lambda_function" "test_lambda" {
  function_name = "fuction_${var.name_alias}"
  role          = aws_iam_role.iam_for_lambda.arn
  package_type  = "Image"
  image_uri     = docker_registry_image.helloworld.name
  architectures = ["x86_64"]
  depends_on = [aws_ecr_repository.shedular]
}

resource "aws_lambda_permission" "apigw_lambda" {
  statement_id  = "AllowExecutionFromAPIGateway"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.test_lambda.function_name
  principal     = "apigateway.amazonaws.com"

  # More: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-control-access-using-iam-policies-to-invoke-api.html
  source_arn = "${aws_api_gateway_rest_api.api_gateway.execution_arn}/*/*"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  create an &lt;code&gt;api-gateway.tf&lt;/code&gt; file. Here we are integrating api-gateway to lambda.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_api_gateway_rest_api" "api_gateway" {
  name = "api-gateway_${var.name_alias}"
  endpoint_configuration {
    types = ["REGIONAL"]
  }
}

resource "aws_api_gateway_resource" "catch_all_resource" {
  parent_id   = aws_api_gateway_rest_api.api_gateway.root_resource_id
  rest_api_id = aws_api_gateway_rest_api.api_gateway.id
  path_part   = "{proxy+}"  # This will capture any sub-route
}

resource "aws_api_gateway_method" "catch_all_method" {
  rest_api_id   = aws_api_gateway_rest_api.api_gateway.id
  resource_id   = aws_api_gateway_resource.catch_all_resource.id
  http_method   = "ANY"  # Set the method to ANY to catch all HTTP methods
  authorization = "NONE"
}

resource "aws_api_gateway_integration" "integration" {
  rest_api_id             = aws_api_gateway_rest_api.api_gateway.id
  resource_id             = aws_api_gateway_resource.catch_all_resource.id
  http_method             = aws_api_gateway_method.catch_all_method.http_method
  integration_http_method = "POST"
  type                    = "AWS_PROXY"
  uri                     = aws_lambda_function.test_lambda.invoke_arn
}


resource "aws_api_gateway_deployment" "example_deployment" {
  depends_on = [aws_api_gateway_integration.integration]

  rest_api_id = aws_api_gateway_rest_api.api_gateway.id
  stage_name  = "prod"  # Replace with your desired stage name
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ensure you are on the infrastructure directory on your terminal and run &lt;code&gt;terraform init&lt;/code&gt; to initialize terraform&lt;/p&gt;

&lt;p&gt;then run &lt;code&gt;terraform apply&lt;/code&gt; to deploy the application and your pre-defined infrastructure.&lt;/p&gt;

&lt;p&gt;if deployed successfully, go to aws console and test the lambda function by calling the api endpoints.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/sammy0055/tutorial_examples/tree/main/deploy_express_app_to_ecr"&gt;you can drop you question on the discussion section of this repo.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>terraform</category>
      <category>aws</category>
      <category>containers</category>
    </item>
    <item>
      <title>How to Effectively Organize and Complete a New Project</title>
      <dc:creator>Samuel Ronick</dc:creator>
      <pubDate>Sun, 14 Jan 2024 21:03:14 +0000</pubDate>
      <link>https://forem.com/samuelronick/how-to-effectively-organize-and-complete-a-new-project-4ga5</link>
      <guid>https://forem.com/samuelronick/how-to-effectively-organize-and-complete-a-new-project-4ga5</guid>
      <description>&lt;p&gt;Starting a new project, whether it's a side project or a startup idea, is always exciting in the beginning. However, as you progress, challenges may arise, especially when implementing core features crucial to your product's value proposition. In this article, we will explore strategies to stay organized and ensure successful project completion without unexpected hiccups during development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agenda&lt;/strong&gt;&lt;br&gt;
To achieve our goal, we will focus on the technical plan of the project with the following key points:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify primary requirements and features.&lt;/li&gt;
&lt;li&gt;Build out challenging individual features as tests before 
implementing the actual project.&lt;/li&gt;
&lt;li&gt;Distribute individual features into small tasks that can be 
accomplished daily.&lt;/li&gt;
&lt;li&gt;Set weekly targets to track progress.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Outline the Primary Features and Requirements of the Project.
&lt;/h2&gt;

&lt;p&gt;The primary features are the core components that make the application function as a whole. It's essential to align individual features with the project's requirements. Consider aspects such as user needs, business profiles, and relevant hot topics within your business domain. For instance, ensure users can generate images and create content based on their business profiles and trending topics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Challenging Features as Tests.
&lt;/h2&gt;

&lt;p&gt;While some features may be straightforward to develop, others can pose significant challenges, especially if you lack experience with them. Experiment with these challenging features as tests before incorporating them into the actual project. This proactive approach allows you to assess their fit for your use case, making it easier to integrate or switch between services for better results. By addressing potential hurdles in advance, the actual development process will be smoother.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distribute Features into Daily Tasks.
&lt;/h2&gt;

&lt;p&gt;Staying organized is crucial for efficient product development. Divide each feature into small tasks that can be accomplished on a daily basis. This approach not only breaks down complex features into manageable parts but also ensures steady progress. By tackling smaller tasks regularly, you maintain momentum and make consistent strides toward completing the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set Weekly Targets for Progress Tracking.
&lt;/h2&gt;

&lt;p&gt;Establishing weekly targets is a practical strategy to monitor your progress and gain insights into when the project will reach completion. These targets act as milestones, allowing you to assess whether you're on track and make necessary adjustments. Regularly tracking progress enhances accountability and helps you identify any potential delays or areas that require additional attention.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, successfully navigating the challenges of a new project or startup requires meticulous planning and organization. By outlining primary features, testing challenging components early on, breaking down tasks into manageable daily goals, and setting weekly targets, you can ensure a smoother development process and bring your idea to life with confidence.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>projectmanagement</category>
      <category>productivity</category>
      <category>codenewbie</category>
    </item>
  </channel>
</rss>
